
# 实现DWS数据列的加解密
数据加密作为有效防止未授权访问和防护数据泄露的技术，在各种信息系统中广泛使用。作为信息系统的核心，DWS数仓也提供数据加密功能，包括透明加密和使用SQL函数加密。本章节主要讨论SQL函数加密。
![](https://support.huaweicloud.com/bestpractice-dws/public_sys-resources/note_3.0-zh-cn.png)
DWS目前不支持在Oracle、Teradata和MySQL中加密数据后再到DWS解密。Oracle、Teradata和MySQL与DWS加解密有区别，需要非加密数据迁移到DWS后在DWS侧进行加解密。
#### 技术背景
- 哈希函数 哈希函数又称为摘要算法，对于数据data，Hash函数会生成固定长度的数据，即Hash(data)=result。这个过程是不可逆的，即Hash函数不存在反函数，无法由result得到data。在不应保存明文场景（比如口令password属于敏感信息），系统管理员用户也不应该知道用户的明文口令，就应该使用哈希算法存储口令的单向哈希值。
  实际使用中会加入盐值和迭代次数，避免相同口令生成相同的哈希值，以防止彩虹表攻击。
  
- 对称密码算法 对称密码算法使用相同的密钥来加密和解密数据。对称密码算法分为分组密码算法和流密码算法。
  分组密码算法将明文分成固定长度的分组，用密钥对每个分组加密。由于分组长度固定，当明文长度不是分组长度的整数倍时，会对明文做填充处理。由于填充的存在，分组密码算法得到的密文长度会大于明文长度。
  流加密算法是指加密和解密双方使用相同伪随机加密数据流作为密钥，明文数据依次与密钥数据流顺次对应加密，得到密文数据流。实践中数据通常是一个位（bit）并用异或（xor）操作加密。流密码算法不需要填充，得到的密文长度等于明文长度。
  图1对称密码算法   
  ![](https://support.huaweicloud.com/bestpractice-dws/figure/zh-cn_image_0000001363309953.png "点击放大") 
 
#### 技术实现
DWS主要提供了哈希函数和对称密码算法来实现对数据列的加解密。哈希函数支持SHA256，SHA384，SHA512和国密SM3。对称密码算法支持AES128，AES192，AES256和国密SM4。
- 哈希函数
  - MD5(string) 将string使用MD5加密，并以16进制数作为返回值。MD5的安全性较低，不建议使用。
    
  
  - gs_hash(hashstr, hashmethod) 以hashmethod算法对hashstr字符串进行信息摘要，返回信息摘要字符串。支持的hashmethod：SHA256，SHA384，SHA512，SM3。
    
   
- 对称密码算法
  - gs_encrypt(encryptstr, keystr, cryptotype, cryptomode, hashmethod) 采用cryptotype和cryptomode组成的加密算法以及hashmethod指定的HMAC算法，以keystr为密钥对encryptstr字符串进行加密，返回加密后的字符串。
    
  
  - gs_decrypt(decryptstr, keystr, cryptotype, cryptomode, hashmethod) 采用cryptotype和cryptomode组成的加密算法以及hashmethod指定的HMAC算法，以keystr为密钥对decryptstr字符串进行解密，返回解密后的字符串。解密使用的keystr必须保证与加密时使用的keystr一致才能正常解密。
    
  
  - gs_encrypt_aes128(encryptstr, keystr) 以keystr为密钥对encryptstr字符串进行加密，返回加密后的字符串。keystr的长度范围为1\~16字节。
    
  
  - gs_decrypt_aes128(decryptstr, keystr) 以keystr为密钥对decryptstr字符串进行解密，返回解密后的字符串。解密使用的keystr必须保证与加密时使用的keystr一致才能正常解密。keystr不得为空。
    
  
  
  有关函数的更多内容，请参见[使用函数加解密](https://support.huaweicloud.com/devg-dws/dws_04_0995.html)。
  
 
#### 应用示例
1. 连接数据库。 
   具体步骤参见[使用命令行工具连接DWS集群](https://support.huaweicloud.com/mgtg-dws/dws_01_0093.html)。
   
   
2. 创建表student，有id、name和score三个字段。使用哈希函数加密保存name，使用对称密码算法保存score。 
   ```
   CREATE TABLE student (id int, name text, score text, subject text);
   INSERT INTO student VALUES (1, gs_hash('alice', 'sha256'), gs_encrypt('95', '12345', 'aes128', 'cbc', 'sha256'),gs_encrypt_aes128('math', '1234'));
   INSERT INTO student VALUES (2, gs_hash('bob', 'sha256'), gs_encrypt('92', '12345', 'aes128', 'cbc', 'sha256'),gs_encrypt_aes128('english', '1234'));
   INSERT INTO student VALUES (3, gs_hash('peter', 'sha256'), gs_encrypt('98', '12345', 'aes128', 'cbc', 'sha256'),gs_encrypt_aes128('science', '1234'));
   ```
   
   
3. 不使用密钥查询表student，通过查询结果可知：没有密钥的用户即使拥有了SELECT权限也无法看到name和score这两列加密数据。 
   ```
   SELECT * FROM student;
    id |                               name                               |                                                          score                                                           |
                                   subject
   ----+------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------+-----------
   -----------------------------------------------------------------------------------
     1 | 2bd806c97f0e00af1a1fc3328fa763a9269723c8db8fac4f93af71db186d6e90 | ****** | ******
     2 | 81b637d8fcd2c6da6359e6963113a1170de795e4b725b84d1e0b4cfd9ec58ce9 | ****** | ******
     3 | 026ad9b14a7453b7488daa0c6acbc258b1506f52c441c7c465474c1a564394ff | ****** | ******
   (3 rows)
   ```
   
   
4. 使用密钥查询表student，通过查询结果可知：拥有密钥的用户通过使用gs_encrypt对应的解密函数gs_decrypt解密后，可以查看加密数据。 
   ```
   SELECT id, gs_decrypt(score, '12345', 'aes128', 'cbc', 'sha256'),gs_decrypt_aes128(subject, '1234') FROM student;
    id | gs_decrypt | gs_decrypt_aes128
   ----+------------+-------------------
     1 | 95         | math
     2 | 92         | english
     3 | 98         | science
   (3 rows)
   ```
   
   
 
