详情页标题前

腾讯云对象存储使用 KMS 白盒密钥保护 COS SecretKey 最佳实践

详情页1

KMS 白盒密钥简介

KMS 白盒密钥用于保护端上的敏感根密钥信息,例如 API SecretKey、用户内部系统使用的鉴权密钥或 token、其它本地敏感根密钥信息等,实现全链路无敏感密钥信息明文。将算法与密钥进行混淆融合,以查找表的形式有效保护密钥信息,在不暴露任何密钥的情况下实现加密与解密,并通过设备绑定的方式进一步确保密钥的安全

腾讯云对象存储使用 KMS 白盒密钥保护 COS SecretKey 最佳实践


本文为您介绍使用密钥管理系统(Key Management Service,KMS)白盒密钥对 COS 产品 SecretKey 加解密的操作示例,通过白盒密钥对 SecretKey 进行保护和安全使用,详情步骤请参见:密钥的管理和分发通过对象存储 SDK 工具访问 COS

使用 KMS 白盒密钥优势

高安全性基于高强度混淆加固算法及多重安全防护技术,杜绝 API SecretKey 的明文暴露在源代码中。动态白盒支持在白盒库不变的情况下实现灵活的密钥的动态轮换。设备绑定绑定设备指纹信息,实现对解密密钥的加固保护。算法支持支持国际算法 AES、国密算法 SM4 算法,满足合规要求。

密钥的管理和分发

步骤1:创建白盒密钥

注意白盒密钥为 KMS 收费项,详情请参见 KMS 计费概述KMS 购买方式创建白盒密钥对是通过调用白盒服务来实现的,支持控制台方式和 API 方式,本文示例采用控制台方式。1. 登录 密钥管理系统(合规)控制台,在左侧菜单栏选择白盒密钥管理 > 用户密钥管理页面,根据业务需求切换“地域” ,单击新建

腾讯云对象存储使用 KMS 白盒密钥保护 COS SecretKey 最佳实践

2. 在弹出的对话框,填写白盒密钥名称,选择加密算法,描述信息及标签(两者选填),单击确定,即可完成白盒密钥的创建。

腾讯云对象存储使用 KMS 白盒密钥保护 COS SecretKey 最佳实践



步骤2:控制台获取 API SecretKey

1. 使用主账号登录 API 密钥管理控制台,查看您的 API 密钥 。2. 在密钥操作列中,单击显示,完成身份验证,获取并复制 SecretKey。

腾讯云对象存储使用 KMS 白盒密钥保护 COS SecretKey 最佳实践



步骤3:对 SecretKey 明文进行 base64 编码

将步骤2中获取的 SecretKey 内容进行 base64 编码。 例如,要加密的 SecretKey 明文是:lY9Ynrabcdj05YH1234LE37xxxx,使用 openssl 命令生成 base64 编码后的结果为:bFk5WW5yYWJjZGowNVlIMTIzNExFMzcwSE9Nxxxx

echo lY9Ynrabcdj05YH1234LE37xxxx | openssl base64

步骤4:使用白盒密钥加密 API SecretKey

1. 登录 密钥管理系统(合规)控制台,在白盒密钥列表,单击“白盒密钥ID/名称”或“操作”列的加密

腾讯云对象存储使用 KMS 白盒密钥保护 COS SecretKey 最佳实践

2. 在弹出的对话框,将步骤3中获取的编码内容填充至明文(base64)文本框中,单击白盒加密

腾讯云对象存储使用 KMS 白盒密钥保护 COS SecretKey 最佳实践

加密成功后,会返回随机生成的初始化向量(简称 IV)和加密后的密文,单击下载IV下载密文,即可完成内容的下载。说明其中初始化向量(简称 IV)和加密后的密文均已进行 base64 编码。

腾讯云对象存储使用 KMS 白盒密钥保护 COS SecretKey 最佳实践


3. (可选步骤)白盒密钥支持将解密密钥与解密运行的物理环境进行绑定。操作方式为:在白盒密钥控制台中下载对应环境的指纹采集工具,并在指定的环境中运行指纹采集工具,获得该环境的指纹字符串。在白盒密钥控制台中,选择指定的白盒密钥,单击“新增设备指纹”,输入对应环境的指纹字符串,将该指纹与该密钥进行绑定。指纹环境变量被绑定到该密钥后,解密密钥会被更新,后续使用该白盒密钥加密的数据只能使用更新后的解密密钥在已绑定的物理环境中进行解密。下载指纹采集工具:

腾讯云对象存储使用 KMS 白盒密钥保护 COS SecretKey 最佳实践


将指纹字符串与指定的白盒密钥进行绑定:

腾讯云对象存储使用 KMS 白盒密钥保护 COS SecretKey 最佳实践



步骤5:下载解密密钥

1. 登录 密钥管理系统(合规)控制台,在白盒密钥列表,单击“白盒密钥ID/名称”,进入密钥基本信息页面。2. 在密钥基本信息页面,单击下载解密密钥,并命名为 decrypt_key_sm4.bin。

腾讯云对象存储使用 KMS 白盒密钥保护 COS SecretKey 最佳实践



步骤6:下载解密 SDK 文件

1. 登录 密钥管理系统(合规)控制台,在白盒密钥列表,单击右侧的下载解密 SDK 文件

腾讯云对象存储使用 KMS 白盒密钥保护 COS SecretKey 最佳实践

2. 在弹出的对话框,根据各业务系统自身的编程语言,选择下载相应编程语言的解密 SDK,并将解密 SDK 集成到业务系统中。

腾讯云对象存储使用 KMS 白盒密钥保护 COS SecretKey 最佳实践



步骤7:白盒解密密钥和 API SecretKey 密文分发

管理员将上述步骤中下载的解密密钥、IV 和密文三个文件,分发给各业务系统的开发或运维人员。其中,解密密钥部署到相应业务系统的文件中,而初始化向量 IV 和密文会作为解密 SDK 的传参。注意下载的解密密钥是一个二进制 bin 文件,需要将该文件和可执行文件(已经集成了解密 SDK)放在相同的服务器上,文件路径将作为解密 SDK 的解密参数。

通过对象存储 SDK 工具访问 COS

步骤1:通过永久密钥初始化身份信息

安装对象存储 SDK 工具后,在客户端代码中引入下载的白盒 SDK,并按照如下步骤获取解密后的 Secret Key:1. 在代码中引入预先下载的白盒 SDK。2. 调用白盒密钥解密 SDK 的解密函数对加密后的 Secret Key 进行解密。传入如下参数,从而获得解密后的明文。decrypt_key_bin_dir:步骤7中解密密钥存放的目录。decrypt_key_sm4.bin:步骤5中下载的解密密钥,其对应的文件名。InitializationVector:步骤4中下载的 IV。CipherText:步骤4中用白盒加密后的 SecretKey 密文。algorithmType:是生成密钥时使用的算法类型,取值为0或1。0表示 AES_256,1表示 SM4。3. 使用解密后的 Secret Key 以及 Secret ID(若 Secret ID 也被加密,则同样需要解密)对 COS SDK 进行初始化。后续针对 COS 的服务调用可参考 COS SDK 的相关文档白盒密钥解密 SDK 基于 C 语言实现,并提供了基于其他高级语言的适配,例如 Golang、Python、Java 等。具体使用方法可参考指定语言的解密 SDK 中的代码示例。Golang 示例代码如下(基于 CGO):由于白盒解密 SDK 底层功能由 C lib 库实现,因此示例代码采用 CGO 注解的方式将解密 SDK 头文件目录#cgo CFLAGS: -I${header_file_dir_path}以及 lib 库文件#cgo LDFlags: -L${lib_dir_path} -l${library_name}引入到代码中。头文件目录以及 lib 库通常位于所下载的白盒解密 SDK 的根目录下,应用集成时可根据项目结构自主调整。

/*#cgo CFLAGS: -I${SRCDIR}/include#cgo LDFLAGS: -L${SRCDIR}/lib -lydwbcrypto
#include #include #include #include "wrp.h"
static int clt_load_key(WRP_KEY_CTX *key_ctx, char *decrypt_key_path, const char *file_name, uint32_t mode, uint32_t algoType) { printf("begin to load key in dir: %s\n", decrypt_key_path); printf("begin to load key: %s\n", file_name); int err; const WRP_KEY* keyalg = WRP_KEY_wbaes(); if (algoType == 1) { keyalg = WRP_KEY_wbsm4(); }
err = WRP_KEY_init(key_ctx, keyalg, 0); if (err) { printf("Err: orig_byte init\n"); goto end; }
err = WRP_KEY_ctrl(key_ctx, WRP_KEY_CTRL_WB_SET_PATH, decrypt_key_path, strlen(decrypt_key_path)); if (err) { printf("Err: set path\n"); goto end; }
err = WRP_KEY_import(key_ctx, file_name, mode); if (err) { printf("Err: WRP_KEY_import error: %d, \n", err); goto end; }
end: return err;}

int clt_cbc_dec(char * file_dir, const char * file_name, uint8_t* ciph, uint32_t ciphlen, char* iv, uint32_t algoType, uint8_t* out, uint32_t* outlen) { WRP_KEY_CTX *mykey; WRP_CIPHER_CTX *myaes = NULL;
uint32_t bits; ERRNO err = ERRNO_OK;
const WRP_CIPHER* alg = WRP_wbaes_cbc(); if (algoType == 1) { alg = WRP_wbsm4_cbc(); }
// IO: load wbkey mykey = WRP_KEY_CTX_new(); err = clt_load_key(mykey, file_dir, file_name, KEYMODE_DECRYPT, algoType); if (err) { printf("load whitebox key error: %d\n", err); goto cleanup; }
printf("load key success\n"); bits = WRP_KEY_key_len(mykey, KEYLEN_TYPE_BITS); printf("key len=%u\n", bits);
if (bits == 0) { printf("get whitebox key length error\n"); err=-1; goto cleanup; }
// crypto myaes = WRP_CIPHER_CTX_new();
err = WRP_CIPHER_Decrypt_init(myaes, alg, mykey, (uint8_t *)iv); if (err) { printf("Dec: init Err**\n"); goto cleanup; } printf("decrypt init success, begin to decrypt cipher\n");
err = WRP_CIPHER_Decrypt_doCipher(myaes, ciph, ciphlen, out, outlen); if (err) { printf("decrypt error: %.8X\n", err); goto cleanup; } //printf("decrypt success\n"); //printf("output: %s\n", deout); //printf("\n");
cleanup: WRP_KEY_CTX_free(mykey); WRP_CIPHER_CTX_free(myaes); return err;}
void set_fingerprint_env_name(char *fingerprint_env_name) { WRP_getENV_KEY((uint8_t *)fingerprint_env_name, strlen(fingerprint_env_name));}
*/import “C”
// Decrypt ...func Decrypt(input DecryptionInput) ([]byte, error) { if input.KeyDir == "" || input.KeyFileName == "" || input.CipherText == "" || input.InitializationVector == "" { return nil, errors.New("invalid white-box decryption input") } cipher, err := base64.StdEncoding.DecodeString(input.CipherText) if err != nil { return nil, fmt.Errorf("failed to decode cipher text: %w", err) } iv, err := base64.StdEncoding.DecodeString(input.InitializationVector) if err != nil { return nil, fmt.Errorf("failed to decode initialization vector: %w", err) }
decryptionKeyDir := C.CString(input.KeyDir) defer C.free(unsafe.Pointer(decryptionKeyDir))
decryptionKeyFileName := C.CString(input.KeyFileName) defer C.free(unsafe.Pointer(decryptionKeyFileName))
// malloc a buffer which size is a little greater than your plaintext outLen := len(input.CipherText) + 1024 outBuf := C.malloc(C.size_t(outLen)) defer C.free(unsafe.Pointer(outBuf))
errC := C.clt_cbc_dec( decryptionKeyDir, decryptionKeyFileName, (*C.uchar)(unsafe.Pointer(&cipher[0])), C.uint(len(cipher)), (*C.char)(unsafe.Pointer(&iv[0])), C.uint(input.AlgorithmType), (*C.uchar)(outBuf), (*C.uint)(unsafe.Pointer(&outLen)), ) if errC != 0 { return nil, fmt.Errorf("whitebox decryption failed with code %d", int(errC)) } plain := C.GoBytes(outBuf, C.int(outLen)) return plain, nil}
func main() { //将和修改为真实的信息 //bucket的命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 u, _ := url.Parse("https://.cos..myqcloud.com") // 使用环境变量指定白盒密钥相关信息,以及加密后的 secret ID 以及 secret key。 encryptionAlgorithm, _ := strconv.Atoi(os.Getenv("EncryptionAlgorithm")) whiteboxDecryptInput := DecryptionInput{ KeyDir: os.Getenv("WhiteboxKeyDir"), // e.g.: /usr/local/ KeyFileName: os.Getenv("WhiteboxKeyFileName"), // e.g.: whitebox_key.bin InitializationVector: os.Getenv("WhiteboxDecryptionIV"), AlgorithmType: uint(encryptionAlgorithm), } // 使用白盒 sdk 解密 secret ID whiteboxDecryptInput.CipherText = os.Getenv("COS_Encrypted_Secret_ID") secretID, err := Decrypt(whiteboxDecryptInput) if err != nil { panic(err) } // 使用白盒 sdk 解密 secret key whiteboxDecryptInput.CipherText = os.Getenv("COS_Encrypted_Secret_Key") secretKey, err := Decrypt(whiteboxDecryptInput) if err != nil { panic(err) }
b := &cos.BaseURL{BucketURL: u} c := cos.NewClient(b, &http.Client{ //设置超时时间 Timeout: 100 * time.Second, Transport: &cos.AuthorizationTransport{ //如实填写账号和密钥,也可以设置为环境变量 SecretID: string(secretID), SecretKey: string(secretKey), }, })
name := "test/hello.txt" resp, err := c.Object.Get(context.Background(), name, nil) if err != nil { panic(err) } bs, _ := ioutil.ReadAll(resp.Body) _ = resp.Body.Close() fmt.Printf("%s\n", string(bs))}
type DecryptionInput struct { KeyDir string KeyFileName string InitializationVector string // Base64 encoded. CipherText string // Base64 encoded. AlgorithmType uint // 0: AES_256, 1: SM4.}

步骤2:直接使用 COS SDK 请求 COS 服务

初始化之后,您可以直接使用 COS SDK 工具进行上传、下载等基本操作,而无需像 API 请求一样自行生成签名,因为 SDK 工具代替您通过密钥生成了签名,向 COS 发起请求。
对象存储官网1折活动,限时活动,即将结束,速速收藏
同尘科技腾讯云授权服务中心。
购买腾讯云产品享受折上折,更有现金返利。同意关联立享优惠

转转请注明出处:https://www.yunxiaoer.com/144511.html

(0)
上一篇 2023年12月9日 上午1:47
下一篇 2023年12月9日 上午1:48
详情页2

相关推荐

  • 腾讯云内容分发网络CDN计费说明

    按小时结算 计费规则 计费项:请求次数 + 超额流量。付费方式:后付费。计费周期:小时结计费,前1小时产生的总消耗,会在2-4小时内计算并扣费,具体扣费结算时间以系统为准。注意CDN 流量包暂不支持抵扣 ECDN 域名的使用流量。 计费价格 请求次数阶梯价格 ECDN 请求次数按照阶梯价格计费,计费阶梯按照自然月用量累积方式计算,价格阶梯如下: 计费模式 月…

    2023年12月9日
  • DataWorks在使用数据集成中的同步任务从mysql同步表到oss,这个属性可以在哪里配置么?-云小二-阿里云

    DataWorks在使用数据集成中的同步任务从mysql同步表到oss,存储为csv时,最终生成的文件中没有表头,这个属性可以在哪里配置么?我暂时没发现可以在哪配置,路径是可以自定义规则?

    阿里云 2023年12月23日
  • 阿里云日志服务SLS资源列表-云淘科技

    日志服务支持通过主账号为子账号授予相关资源权限,方便子账号对部分资源进行操作。本文档主要介绍为子账号授权的资源类型。 目前可以授予RAM用户的资源类型及其描述方式如下: 资源类型 授权策略中的资源描述方式 Project、Logstore acs:log:${regionName}:${projectOwnerAliUid}:project/${projec…

    阿里云日志服务SLS 2023年12月10日
  • 信息流广告,信息流部分建议宽度830px,只针对默认列表样式,顺序随机
  • 腾讯云轻量应用服务器产品定价云小二

     按量计费定价 您在开始使用轻量对象存储(Lighthouse-COS)服务后,默认采用按量计费。了解更多,请参见 计费概述。您在了解轻量对象存储的计费项说明和费用组成后,可根据自身业务需求评估所需的用量(例如每月的存储容量、流量)。说明:关于轻量对象存储费用的整体概括,包括计费方式、计费周期等,请参见 计费概述。轻量对象存储当前仅支持公有云地域北京、上海…

    腾讯云 2023年12月9日
  • 腾讯云轻量应用服务器重装系统云小二

    操作场景 重装系统相当于重新安装轻量应用服务器的操作系统(或操作系统加预置应用),达到将实例恢复至初始状态或全新安装的目的,是实例遭遇系统故障时的一种重要恢复手段。说明目前轻量应用服务器已支持敏感操作保护功能,可有效保障账号资源安全。重装系统属于敏感操作,您可前往 安全设置 开启操作保护,详细操作可参考 操作保护。 注意事项 跨平台重装:目前仅支持中国内地区…

    2023年12月9日

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信
本站为广大会员提供阿里云、腾讯云、华为云、百度云等一线大厂的购买,续费优惠,保证底价,买贵退差。