GaussDB-使用third_kms三方厂商加解密库

GaussDB-使用third_kms三方厂商加解密库

全密态等值查询与透明加密功能选择密钥管理工具时,可以选择third_kms作为密钥管理工具及加解密库。在该功能打开后,数据库进程会把动态库文件载入到内存。加解密接口的正确性和安全性由第三方厂商保证,上线前需经过充分测试,避免影响数据库正常业务。

规格约束

当使用third_kms时,不支持密钥轮转语句轮转密钥。

操作步骤

在使用third_kms三方厂商加解密库前需要按照以下操作步骤进行配置:

  1. 向第三方厂商获取名字为libthird_crypto.so的加解密文件及其使用说明。
  2. 将加解密库文件放置在LD_LIBRARY_PATH下的目录中。

     

    建议与数据库客户端其他库放在同一目录下,比如libpq_ce.so。

     

  3. 使用crypto_module_info设置动态库加载信息以及设置key_info,不同客户端的设置内容一致。

     

    其中module_third_msg为加密库加载时的必要信息,keyThirdMsg为加密库创建会话时的登录信息,这两项信息的格式和内容由第三方厂商定义,数据库仅通过crypto_module_init接口对该参数的合法性进行校验,建议第三方厂商通过该参数校验对应版本号的前后向兼容性。

    • gsql:
      gaussdb=#  \crypto_module_info enable_crypto_module=on,module_third_msg=aaa
      load crypto module success
      gaussdb=#  \key_info keyType=third_kms,keyThirdMsg=aaa
       
    • JDBC:JDBC客户端可以通过连接参数或Connection类中的setClientInfo方法设置。
      • 通过连接参数设置
        String sourceURL = "jdbc:gaussdb://127.0.0.1:8000/postgres?enable_ce=1&crypto_module_info='enable_crypto_module=on,module_third_msg=aaa'&key_info='keyType=third_kms, keyThirdMsg=aaa'";
        // 获取数据库连接池句柄
        Connection conn = DriverManager.getConnection(sourceURL, username, passwd);
         
      • 通过Connection类设置
        //此示例前已成功创建连接获得Connection类的实例conn
        conn.setClientInfo("crypto_module_info", "enable_crypto_module=on,module_third_msg=aaa" );
        conn.setClientInfo("key_info", "keyType=third_kms,keyThirdMsg=aaa" );
         
    • go:go客户端通过连接参数的方式设置。
      str := "host=xxx.xxx.xxx.x port=xxx user=xxx password=******** dbname=xxx enable_ce=1 crypto_module_info='enable_crypto_module=on,module_third_msg=aaa' key_info='keyType=third_kms, keyThirdMsg=aaa'"
      // 获取数据库连接池句柄
      db, err := sql.Open("opengauss", str)
       

     

  4. 创建主密钥、列密钥以及创建加密表。

     

    gaussdb=# CREATE CLIENT MASTER KEY cmk1 WITH (KEY_STORE = third_kms);
    CREATE CLIENT MASTER KEY
    -- CREATE COLUMN ENCRYPTION KEY语法中ENCRYPTED_VALUE为可选入参,可以用以传入列密钥ID(hex格式)。不填则通过三方库密钥生成接口自动生成随机密钥。
    gaussdb=# CREATE COLUMN ENCRYPTION KEY cek1 WITH VALUES (CLIENT_MASTER_KEY = cmk1, ENCRYPTED_VALUE='13481754638');
    CREATE COLUMN ENCRYPTION KEY
    gaussdb=# CREATE TABLE t16 (c1 INT, c2 TEXT ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = cek1 , ENCRYPTION_TYPE = DETERMINISTIC));
    CREATE TABLE
    gaussdb=# INSERT INTO t16 VALUES(1, 'Gauss');
    INSERT 0 1
     

     

第三方厂商实现加解密接口注意事项

  • 三方厂商需按照第三方厂商实现加解密接口头文件对接口进行实现并编译成以libthird_crypto.so命名的文件。
  • 加密库链接时,仅可使用与数据库进程中相同版本的依赖库,不允许引入外部依赖库。
  • 厂商提供加密库给客户时需保证编译环境与客户环境一致(例如:x86 or ARM,os-release版本等)。
  • 第三方厂商实现加解密接口头文件中,crypto_module_init的返回值SupportedFeature需要支持除MODULE_DETERMINISTIC_KEY外的所有算法,需要实现除my_cipher_deterministic_enc_dec外所有接口。(不实现确定性算法及其接口仅导致全密态等值查询不可使用该库,仍可供透明加密功能使用)
  • 为保证兼容性,若涉及接口头文件升级,厂商需要基于升级后的头文件重新编译C函数共享库。
  • 如果实现语言为C++,则需要为实现的函数加上extern "C",以保证数据库加载时能正确找到函数。
  • 编译选项需要带上安全编译选项和优化选项,如trapv, Wl, relro, z, now, noexecstack, pie, PIC, stack-protector, O3等。

厂商应充分了解要实现的接口功能及入参范围,在调用前应检查参数合法性,避免出现空指针等可能导致程序crash的问题。厂商应避免接口调用过程中产生内存泄漏。

第三方厂商实现加解密接口头文件

#define CRYPT_MOD_OK 1
#define CRYPT_MOD_ERR 0
typedef enum {
    MODULE_AES_128_CBC = 0,
    MODULE_AES_128_CTR,
    MODULE_AES_128_GCM,
    MODULE_AES_256_CBC,
    MODULE_AES_256_CTR,
    MODULE_AES_256_GCM,
    MODULE_SM4_CBC,
    MODULE_SM4_CTR,
    MODULE_HMAC_SHA256,
    MODULE_HMAC_SM3,
    MODULE_DETERMINISTIC_KEY,
    MODULE_ALGO_MAX = 1024
} ModuleSymmKeyAlgo;
typedef enum {
    MODULE_SHA256 = 0,
    MODULE_SM3,
    MODULE_DIGEST_MAX = 1024
} ModuleDigestAlgo;
typedef enum {
    KEY_TYPE_INVALID,
    KEY_TYPE_PLAINTEXT,
    KEY_TYPE_CIPHERTEXT,
    KEY_TYPE_NAMEORIDX,
    KEY_TYPE_MAX
} KeyType;
typedef struct {
    KeyType key_type;
    int supported_symm[MODULE_ALGO_MAX]; // 不支持算法填入0或者支持算法填入1
    int supported_digest[MODULE_DIGEST_MAX]; // 不支持算法填入0或者支持算法填入1
} SupportedFeature;
/** 初始化密码模块 
 *
 * @param[in]    
 *    load_info            密码模块相关信息(硬件设备密码,硬件设备、硬件库路径等),通过kv方式传入
 *
 * @param[out]   
 *    supported_feature    返回当前密码模块支持的加密方式,参考上述结构体
 * @return    成功返回CRYPT_MOD_OK,失败返回错误码
 *
 */
int crypto_module_init(char *load_info, SupportedFeature *supported_feature);
/** 会话中连接密码模块 
 *
 * @param[in]    
 *    key_info        密码相关信息(用户密码等信息),通过kv方式传入
 *
 * @param[out]   
 *    sess            会话信息
 * @return    成功返回CRYPT_MOD_OK,失败返回错误码
 *
 */
int crypto_module_sess_init(char *key_info, void **sess);
/** 会话中断开连接密码模块 
 *
 * @param[in]    
 *    sess            会话信息
 *
 * @param[out]   
 *    
 * @return    成功返回CRYPT_MOD_OK,失败返回错误码
 *
 */
void crypto_module_sess_exit(void *sess);
/** 创建密钥 
 *
 * @param[in]    
 *    sess            会话信息
 *    algo            密钥使用场景的算法
 *
 * @param[out]   
 *    key_id          返回生成密钥/密钥ID/密钥密文
 *    key_id_size     返回生成内容长度 
 * @return    成功返回CRYPT_MOD_OK,失败返回错误码
 *
 */
int crypto_create_symm_key(void *sess, ModuleSymmKeyAlgo algo, unsigned char *key_id, size_t *key_id_size);
/** 密钥上下文初始化,后续进行加解密可直接使用上下文 
 *
 * @param[in]    
 *    sess            会话信息
 *    algo            加密算法
 *    enc             加密1、解密0
 *    key_id          密码信息
 *    key_id_size     密码信息长度
 * @param[out]   
 *    ctx             返回使用密钥信息  
 * @return    成功返回CRYPT_MOD_OK,失败返回错误码
 *
 */
int crypto_ctx_init(void *sess, void **ctx, ModuleSymmKeyAlgo algo, int enc, unsigned char *key_id, size_t key_id_size);
/** 获取数据加解密后的数据长度
 *
 * @param[in]    
 *    ctx             加解密上下文信息
 *    enc             加密1、解密0
 * @param[out]   
 *    data_size       返回加解密结果长度  
 * @return    成功返回数据长度,失败返回-1
 *
 */
int crypto_result_size(void *ctx, int enc, size_t data_size);
/** 密钥上下文清理 
 *
 * @param[in]    
 *    ctx             加解密上下文信息
 * @param[out]   
 *    
 * @return    成功返回CRYPT_MOD_OK,失败返回错误码
 *
 */
void crypto_ctx_clean(void *ctx);
/** 执行加解密 
 *
 * @param[in]    
 *    ctx             加解密上下文信息
 *    enc             加密1、解密0
 *    data            原数据信息
 *    data_size       原数据长度
 *    iv              iv信息
 *    iv_size         iv信息长度
 *    tag             GCM模式的校验值
 * @param[out]   
 *    result          返回结果信息  
 *    result_size     返回结果信息长度 
 *    
 * @return    成功返回CRYPT_MOD_OK,失败返回错误码
 *
 */
int crypto_encrypt_decrypt(void *ctx, int enc, unsigned char *data, size_t data_size, unsigned char *iv, size_t iv_size, unsigned char *result, size_t result_size, unsigned char *tag);
/** 计算摘要 
 *
 * @param[in]    
 *    sess            会话信息
 *    algo            摘要算法
 *    data            原数据信息
 *    data_size       原数据长度
 * @param[out]   
 *    result          返回结果信息  
 *    result_size     返回结果信息长度 
 *    
 * @return    成功返回CRYPT_MOD_OK,失败返回错误码
 *
 */
int crypto_digest(void *sess, ModuleDigestAlgo algo, unsigned char * data, size_t data_size,unsigned char *result, size_t *result_size);
/** hmac初始化 
 *
 * @param[in]    
 *    sess            会话信息
 *    algo            摘要算法
 *    key_id          密码信息
 *    key_id_size     密码信息长度
 * @param[out]   
 *    ctx             返回密钥上下文 
 *    
 * @return    成功返回CRYPT_MOD_OK,失败返回错误码
 *
 */
int crypto_hmac_init(void *sess, void **ctx, ModuleDigestAlgo algo, unsigned char *key_id, size_t key_id_size);
/** hmac清理 
 *
 * @param[in]    
 *    ctx             密钥上下文信息
 *    
 * @param[out]   
 *    
 * @return    成功返回CRYPT_MOD_OK,失败返回错误码
 *
 */
void crypto_hmac_clean(void *ctx);
/** 执行hmac计算 
 *
 * @param[in]    
 *    ctx             密钥上下文信息
 *    data            原数据信息
 *    data_size       原数据长度
 * @param[out]   
 *    result          返回结果信息  
 *    result_size     返回结果信息长度 
 *    
 * @return    成功返回CRYPT_MOD_OK,失败返回错误码
 *
 */
int crypto_hmac(void *ctx, unsigned char * data, size_t data_size, unsigned char *result, size_t *result_size);
/** 生成随机数
 *
 * @param[in]    
 *    sess            会话信息
 *    size            申请的随机信息长度 
 * 
 * @param[out]   
 *    buffer          返回随机信息  
 *    
 * @return    成功返回CRYPT_MOD_OK,失败返回错误码
 *
 */
int crypto_gen_random(void *sess, char *buffer, size_t size);
/** 执行确定性加解密 
 *
 * @param[in]    
 *    sess            会话信息
 *    enc             加密1、解密0
 *    data            原数据信息
 *    data_size       原数据长度
 *    key_id          密钥信息
 *    key_id_size     密钥信息长度
 * @param[out]   
 *    result          返回结果信息  
 *    result_size     返回结果信息长度 
 *    
 * @return    成功返回CRYPT_MOD_OK,失败返回错误码
 *
 */
int crypto_deterministic_enc_dec(void *sess, int enc, unsigned char *data, unsigned char *key_id,
    size_t key_id_size, size_t data_size, unsigned char *result, size_t *result_size);
/** 获取报错信息 
 *
 * @param[in]    
 *    sess            会话信息
 * @param[out]   
 *    errmsg          返回结果信息,最长256字节
 *    
 * @return    成功返回CRYPT_MOD_OK,失败返回错误码
 *
 */
int crypto_get_errmsg(void *sess, char *errmsg);
 
 
posted @ 2024-12-27 18:14  jerrywang1983  阅读(29)  评论(0)    收藏  举报