密钥管理服务KMS

    控制台操作指南

    配置KMS多用户访问控制

    概述

    多用户访问控制,主要用于帮助用户管理云账户下资源的访问权限,适用于企业内的不同角色,可以对不同的工作人员赋予使用产品的不同权限,当您的企业存在多用户协同操作资源时,推荐您使用多用户访问控制。 适用于下列使用场景:

    • 中大型企业客户:对公司内多个员工授权管理;
    • 偏技术型 vendor 或 SaaS 的平台商:对代理客户进行资源和权限管理;
    • 中小开发者或小企业:添加项目成员或协作者,进行资源管理。

    配置多用户访问控制包含创建用户、配置策略、用户授权及子用户登录共4个步骤。

    创建子用户

    1. 主账号用户登录后在控制台选择“多用户访问控制”进入用户管理页面。

    infoflow 2020-07-30 23-37-44.png

    1. 在左侧导航栏点击“用户管理”,在“用户管理 > 子用户”列表页,点击“创建子用户”。

    infoflow 2020-07-30 23-39-58.png

    1. 在弹出的“创建子用户”对话框中,完成填写“用户名”和确认,返回“子用户管理列表”区可以查看到刚刚创建的子用户。

    infoflow 2020-07-30 23-43-13.png

    配置策略

    KMS支持用户自定义策略。自定义策略是由用户自己创建,更细化的管理资源的权限集,可以针对单个实例配置权限,更加灵活的满足账户对不同用户的差异化权限管理。

    子用户可以通过点击“创建策略”,填写策略名称并选择服务类型为(“密钥管理服务KMS”)添加自定义策略来进行自定义权限添加,用户可以根据具体的权限设置修改策略内容。

    image2020-7-4_16-18-50.png

    策略创建流程

    点击创建策略

    页面左侧选择"策略管理",在新的页面中点击"创建策略",选择"按策略生成器创建.

    infoflow 2020-07-31 12-39-27.png

    填写策略基本信息

    在创建策略的页面中,填写需要创建的策略的名称,并在说明中填写该策略的备注信息,如该策略应用的实例,希望赋予的子用户或者策略的使用场景,以免将该策略和其他策略混淆。

    infoflow 2020-07-31 12-40-58.png

    填写策略权限配置

    填写完策略的基本信息后,您需要填写该策略中包含的使用权限。

    • 您需要进一步该权限对应的效力为允许还是拒绝。若您选择允许,则该策略中选择的权限将允许被授权的用户操作;若您选择拒绝,则该策略中选择的权限将禁止被授权用户操作;
    • 选择权限,您需要选择该策略中包含的权限为仅加密、仅解密、加解密、查看、管理;
    • 您还可以选择该策略针对的资源。在 KMS服务中,您可以指定该策略能够生效的具体密钥。
    • 最后,您可以选择该策略在生效时间上的限制条件。您可以指定该策略在某一时刻后或者某一时刻前生效。

    权限说明

    分类 API
    查看权限 POST /?aciton=ListKeys
    POST /?aciton=ConsoleListKeys
    POST /?aciton=DescribeKey
    加密权限 POST /?aciton=ListKeys
    POST /?aciton=ConsoleListKeys
    POST /?aciton=DescribeKey
    POST /?aciton=Encrypt
    POST /?aciton=GenerateDataKey
    解密权限 POST /?aciton=ListKeys
    POST /?aciton=ConsoleListKeys
    POST /?aciton=DescribeKey
    POST /?aciton=Decrypt
    POST /?aciton=GenerateDataKey
    加解密权限 POST /?aciton=ListKeys
    POST /?aciton=ConsoleListKeys
    POST /?aciton=DescribeKey
    POST /?aciton=Encrypt
    POST /?aciton=Decrypt
    POST /?aciton=GenerateDataKey
    运维权限 POST /?aciton=ListKeys
    POST /?aciton=ConsoleListKeys
    POST /?aciton=DescribeKey
    POST /?action=CreateKey
    POST /?action=EnableKey
    POST /?action=DisableKey
    POST /?aciton=ScheduleKeyDeletion
    POST /?aciton=CancelKeyDeletion
    POST /?action=ImportKey
    POST /?action=ImportAsymmetricKey

    使用BCT记录操作事件

    KMS已经与云审计(BCT)服务进行了集成。您可以在云审计中查看所有用户对您的资源所进行的操作记录。

    image2020-7-4_19-49-19.png

    使用对称密钥

    对称加密是最常用的数据加密保护方式,KMS提供了简单易用的接口,方便您在云上轻松实现数据加解密的功能。KMS支持的对称密钥算法有以下几类:

    BAIDU_AES_256/AES_128/AES_256

    创建KMS生成的对称密码

    首先点击创建密钥,然后选择你想要生成的对称密钥类型,选择影像名称("KMS生成"),并填写对密钥的描述。

    infoflow 2020-07-31 12-57-47.png

    创建外部导入的对称密钥

    首先点击创建密钥,然后选择你想要生成的对称密钥类型,选择影像名称("外部导入"),并填写对密钥的描述

    infoflow 2020-07-31 13-05-01.png

    点击获取密钥参数

    infoflow 2020-07-31 13-07-31.png

    infoflow 2020-07-31 13-08-19.png

    获取加密公钥和令牌后,对需要导入的对称密钥进行加密,通过点击导入密钥进行导入.

    infoflow 2020-07-31 13-09-40.png

    导入 AES_256密钥 过程示例

    1.在控制台或者通过接口创建一个AES_256 的待导入的对称密钥:

    image2020-7-6_11-56-44.png

    1. 创建完毕后点击获取密钥材料或者利用接口(/?action=GetParametersForImport)来获取密钥材料(加密公钥和令牌)
    2. 加密自己的对称密钥 openssl方式
    #以aes256的导入为例
    #使用openssl生成一个256位的对称密钥
    openssl rand -out KeyMaterial.bin 32
    #将加密公钥从16进制转成二进制文本
    cat public_key_xxxxx.txt |xxd -ps -r > PublicKey.bin
    #PKCS#1 v1.5 加密 待导入密钥二进制文本KeyMaterial.bin
    openssl rsautl -encrypt -in KeyMaterial.bin -pkcs -inkey PublicKey.bin  -keyform DER  -pubin -out EncryptedKeyMaterial.bin
    #将加密后的结果进行base64加密
    openssl enc -e -base64 -A -in EncryptedKeyMaterial.bin -out EncryptedKeyMaterial_base64.txt
    #最后将加密后的结果和令牌密钥填入。即可成功导入

    java sdk方式

    import com.baidubce.BceClientException;
    import com.baidubce.BceServiceException;
    import com.baidubce.Protocol;
    import com.baidubce.auth.DefaultBceCredentials;
    import com.baidubce.services.kms.KmsClient;
    import com.baidubce.services.kms.KmsClientConfiguration;
    import com.baidubce.services.kms.model.*;
     
     
    import javax.crypto.Cipher;
    import javax.xml.bind.DatatypeConverter;
    import java.security.KeyFactory;
    import java.security.PublicKey;
    import java.security.spec.X509EncodedKeySpec;
    import java.util.Random;
     
    public class testImportSymmetricKey {
        public static void main(String[] args){
            //String ACCESS_KEY_ID = "<AK>";                // 用户的Access Key ID
            //String SECRET_ACCESS_KEY = "<SK>";        // 用户的Secret Access Key
            String ENDPOINT = "https://bkm.bj.baidubce.com";   // kms域名
            // 初始化一个KmsClient
            KmsClientConfiguration config = new KmsClientConfiguration();
            config.setCredentials(new DefaultBceCredentials(ACCESS_KEY_ID, SECRET_ACCESS_KEY));
            config.setEndpoint(ENDPOINT);
            config.setProtocol(Protocol.HTTPS);          // 设置https协议
            KmsClient client = new KmsClient(config);
            try {
                //产生一个32字节随机数
                byte[] keyMaterial = new byte[32];
                new Random().nextBytes(keyMaterial);
                //创建一个AES_256待导入密钥
                CreateKeyRequest createReq = new CreateKeyRequest();
                createReq.setKeySpec("AES_256");
                createReq.setKeyUsage("ENCRYPT_DECRYPT");
                createReq.setOrigin("EXTERNAL");
                createReq.setProtectedBy("HSM");
                CreateKeyResponse createRes =  client.createKey(createReq);
                String keyId = createRes.getKeyMetadata().getKeyId();
                //获取导入密钥参数
                GetParametersForImportResponse getParametersRes = client
                                                .getParametersForImport(new GetParametersForImportRequest(keyId,"BASE64"));
                String pubKey = getParametersRes.getPublicKey();
                String token = getParametersRes.getImportToken();
                byte[] publicKeyDer = DatatypeConverter.parseBase64Binary(pubKey);
                //解析成RSA的公钥
                KeyFactory keyFact = KeyFactory.getInstance("RSA");
                X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKeyDer);
                PublicKey publicKey = keyFact.generatePublic(spec);
                Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
                cipher.init(Cipher.ENCRYPT_MODE, publicKey);
                byte[] cipherDer = cipher.doFinal(keyMaterial);
                //加密后的密钥材料,需要进行base64编码
                String encryptedKeyMaterial = DatatypeConverter.printBase64Binary(cipherDer);
     
                ImportKeyRequest importReq = new ImportKeyRequest();
                importReq.setEncryptedKey(encryptedKeyMaterial);
                importReq.setImportToken(token);
                importReq.setKeyId(keyId);
                importReq.setKeySpec("AES_256");
                importReq.setKeyUsage("ENCRYPT_DECRYPT");
                KmsResponse importRes = client.importKey(importReq);
                System.out.println(importRes.toString());
            }catch (BceServiceException e) {
                System.out.println(e.getMessage());
            } catch (BceClientException e) {
                System.out.println(e.getMessage());
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
    }

    使用非对称密钥

    相比对称加密,非对称密钥通常用于在信任程度不对等的系统之间,实现数字签名验签或者加密传递敏感信息的目的。KMS支持的非对称密钥算法有以下几类:

    RSA_1024/RSA_2048/RSA_4096

    创建KMS生成的非对称密钥

    该步骤与对称密钥的kms生成过程相似,密钥类型选择您需要创建的非对称密钥类型即可。

    创建外部导入的非对称密钥

    创建过程与对称密钥的外部导入过程相似

    RSA密钥的导入

    您使用正确的加密密钥材料加密您的信封密钥,形成信封密钥密文。并将公钥材料和通过信封密钥加密的私钥材料以及获取的令牌正确填入,点击确认即可导入。

    注意,您需要使用aes128算法ecb加密模式来加密您的私钥各二进制分量。并且填入的信息需要base64加密。

    infoflow 2020-07-31 13-17-29.png

    控制台导入RSA密钥示例

    1. 准备一个aes128的对称密钥(KEK密钥),用来加密非对称密钥

    例:11223344556677881122334455667788 (16进制形式,请注意是128位bytes)

    1. 准备一个待导入的RSA密钥

    例:

    名称 内容(16进制表示)
    公钥(PKCS#1, ASN.1 DER form) 30818902818100b985d0d957e8c17c3d2ed1a0e6d522dbf3a5812429aacaf1a0cc517112d9927d58166bc06ce14481a443d0545751065f4220f2a3d03c553ebb4fd5f7849a2a574d0f92a3518a6ccc96f41092deca64dcf8101edaefdf8597bcb30f74a93f82c203ac3d571a7073101c3b2fc7bd27060ef90245d5fe54356524a72ae13bac91470203010001
    D分量 43b683b3d05233cc94c831daf8657283b53a03189fdca695ea8aa86f0ce23c8563514ba2c01ab856590e274ba15301706342834d2703de593724bc83caf239e1643663fcb5490d623fa8fb325aefb5a6a954625af99ebc05c72c58f613bc0e822d77ee061223bc66d95a0d977a17a60eae8d4520fc8f335b2648f40400540c01
    P分量 dc7dd1239889ca4f702f46563611b4495c643538b5136f064b834e865902513804f90c46903001bf235a1cc847a347609d7dbcb0b6a064a8d7180fe931b3bae1
    Q分量 d766585371b4bf7a717ab2ffa20565d95009a02e00a4d07bd4fec73da1b9a8bd3cec173aa9a78b0f53a019d4bd19eb229411c46995f4b71c439554b5618f3927
    DP分量 653e8ca2e8af14aba75abdd4665d78c85ad954aae652b71f4fdb4a5a5c52b9129d0df2ba10094b34063aa18ec17e530f2522105ba07043e85764202237054d61
    DQ分量 9f8425a9362ddb17bc6e579d44c9a69176da8a0b4762c71acdb418ad25d5ae86e6551926d279475c845bae8583bd6c0ae188fee20ab17de1aa932e765cd78a45
    Qinv分量 25f1e8ea900548e3b9664e5c3719a2ba34155fdafb4b2f70cebcffddc6bcdd4815515694b916b2234314bd6be97edee735afef8e535461b608f6e4427a052381
    1. 在控制台创建一个待导入的RSA1024密钥

    image2020-7-22_11-9-28.png

    选择你需要导入的 RSA密钥类型。选择外部导入,并添加描述,点击确定即可创建一个RSA1024的外部导入密钥,此时密钥的状态处于待导入状态。

    image2020-7-22_11-12-0.png

    1. 获取密钥参数文件 点击获取密钥参数

    image2020-7-22_11-13-1.png

    如果第一次创建,加密公钥和令牌为空,点击确认,获取导入密钥参数。

    image2020-7-22_11-13-58.png

    1. 使用导入密钥参数处理待导入密钥
    • 使用步骤1准备的 KEK密钥 来对 待导入的RSA1024密钥 除公钥以外的各分量二进制 进行加密,并转化为base64加密的字符串
    名称 处理方法
    公钥材料密文 仅对公钥Der编码的二进制进行base64加密
    密钥材料-D密文 使用KEK密钥(aes128 ECB)对D分量二进制进行加密 然后进行base64加密
    密钥材料-P密文 使用KEK密钥(aes128 ECB)对P分量二进制进行加密 然后进行base64加密
    密钥材料-Q密文 使用KEK密钥(aes128 ECB)对Q分量二进制进行加密 然后进行base64加密
    密钥材料-Dp密文 使用KEK密钥(aes128 ECB)对Dp分量二进制进行加密 然后进行base64加密
    密钥材料-Dq密文 使用KEK密钥(aes128 ECB)对Dq分量二进制进行加密 然后进行base64加密
    密钥材料-Qinv密文 使用KEK密钥(aes128 ECB)对Qinv分量二进制进行加密 然后进行base64加密
    • 使用密钥参数中的公钥对步骤一中准备的KEK密钥进行加密。得到信封密钥密文
    echo "11223344556677881122334455667788"|xxd -ps -r > KeyMaterial.bin
    cat public_key_xxxxxxx.txt |xxd -ps -r > PublicKey.bin
    openssl rsautl -encrypt -in KeyMaterial.bin -pkcs -inkey PublicKey.bin  -keyform DER  -pubin -out EncryptedKeyMaterial.bin
    openssl enc -e -base64 -A -in EncryptedKeyMaterial.bin -out EncryptedKeyMaterial_base64.txt
    1. 密钥导入

    image2020-7-22_11-42-18.png

    点击确认,导入密钥即完成

    java sdk方式

    import com.baidubce.BceClientException;
    import com.baidubce.BceServiceException;
    import com.baidubce.Protocol;
    import com.baidubce.auth.DefaultBceCredentials;
    import com.baidubce.services.kms.KmsClient;
    import com.baidubce.services.kms.KmsClientConfiguration;
    import com.baidubce.services.kms.model.*;
     
     
    import javax.crypto.Cipher;
    import javax.crypto.spec.SecretKeySpec;
    import javax.xml.bind.DatatypeConverter;
    import java.security.Key;
    import java.security.KeyFactory;
    import java.security.PublicKey;
    import java.security.spec.X509EncodedKeySpec;
    import java.util.Random;
     
    public class testImportRSA1024 {
        public static void main(String[] args){
            String ACCESS_KEY_ID = "<AK>";
            String SECRET_ACCESS_KEY = "<SK>";
            String ENDPOINT = "https://bkm.bj.baidubce.com";                            // kms域名
            // 初始化一个KmsClient
            KmsClientConfiguration config = new KmsClientConfiguration();
            config.setCredentials(new DefaultBceCredentials(ACCESS_KEY_ID, SECRET_ACCESS_KEY));
            config.setEndpoint(ENDPOINT);
            config.setProtocol(Protocol.HTTPS);                         // 设置https协议
            KmsClient client = new KmsClient(config);
            try {
                //产生一个16字节随机数作为信封密钥
                byte[] keyMaterial = new byte[16];
                new Random().nextBytes(keyMaterial);
                //创建一个RSA_1024待导入密钥
                CreateKeyRequest createReq = new CreateKeyRequest();
                createReq.setKeySpec("RSA_1024");
                createReq.setKeyUsage("ENCRYPT_DECRYPT");
                createReq.setOrigin("EXTERNAL");
                createReq.setProtectedBy("HSM");
                CreateKeyResponse createRes =  client.createKey(createReq);
                String keyId = createRes.getKeyMetadata().getKeyId();
                GetParametersForImportResponse getParametersRes = client
                                                                    .getParametersForImport(new GetParametersForImportRequest(keyId,"BASE64"));
                String pubKey = getParametersRes.getPublicKey();
                String token = getParametersRes.getImportToken();
                byte[] publicKeyDer = DatatypeConverter.parseBase64Binary(pubKey);
                //解析成RSA的公钥
                KeyFactory keyFact = KeyFactory.getInstance("RSA");
                X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKeyDer);
                PublicKey publicKey = keyFact.generatePublic(spec);
                Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
                cipher.init(Cipher.ENCRYPT_MODE, publicKey);
                byte[] cipherDer = cipher.doFinal(keyMaterial);
                //加密后的信封密钥,需要进行base64编码
                String encryptedKeyMaterial = DatatypeConverter.printBase64Binary(cipherDer);
     
                cipher = Cipher.getInstance("AES/ECB/NoPadding");
                Key key = new SecretKeySpec(keyMaterial, "AES");
                cipher.init(Cipher.ENCRYPT_MODE, key);
     
                //待导入的RSA密钥各分量(16进制表示)
                String publickDerHex = "30818902818100b985d0d957e8c17c3d2ed1a0e6d522dbf3a5812429aacaf1a0cc5171"
    +"12d9927d58166bc06ce14481a443d0545751065f4220f2a3d03c553ebb4fd5f7849a2a574d0f92a3518a6ccc96f41092deca64dcf"
    +"8101edaefdf8597bcb30f74a93f82c203ac3d571a7073101c3b2fc7bd27060ef90245d5fe54356524a72ae13bac91470203010001";
                String D = "43b683b3d05233cc94c831daf8657283b53a03189fdca695ea8aa86f0ce23c8563514ba2c01ab856590e274ba15301706342834d2"
    +"703de593724bc83caf239e1643663fcb5490d623fa8fb325aefb5a6a954625af99ebc05c72c58f613bc0e822d77ee061223bc66d95a0d977a17a60eae8d4520f"
    +"c8f335b2648f40400540c01";
                String P = "dc7dd1239889ca4f702f46563611b4495c643538b5136f064b834e865902513804f90c46903001bf23"
    +"5a1cc847a347609d7dbcb0b6a064a8d7180fe931b3bae1";
                String Q = "d766585371b4bf7a717ab2ffa20565d95009a02e00a4d07bd4fec73da1b9a8bd3cec173aa9a78b0f53a"
    +"019d4bd19eb229411c46995f4b71c439554b5618f3927";
                String DP = "653e8ca2e8af14aba75abdd4665d78c85ad954aae652b71f4fdb4a5a5c52b9129d0df2ba10094b3406"
    +"3aa18ec17e530f2522105ba07043e85764202237054d61";
                String DQ = "9f8425a9362ddb17bc6e579d44c9a69176da8a0b4762c71acdb418ad25d5ae86e6551926d279475c845"
    +"bae8583bd6c0ae188fee20ab17de1aa932e765cd78a45";
                String Qinv = "25f1e8ea900548e3b9664e5c3719a2ba34155fdafb4b2f70cebcffddc6bcdd4815515694b916b2234"
    +"314bd6be97edee735afef8e535461b608f6e4427a052381";
     
     
     
                String publicDerBase64 = DatatypeConverter.printBase64Binary(DatatypeConverter.parseHexBinary(publickDerHex));
                System.out.println("publicDerBase64:"+publicDerBase64);
                String DBase64 = DatatypeConverter.printBase64Binary(cipher.doFinal(DatatypeConverter.parseHexBinary(D)));
                System.out.println("DBase64:"+DBase64);
                String PBase64 = DatatypeConverter.printBase64Binary(cipher.doFinal(DatatypeConverter.parseHexBinary(P)));
                System.out.println("DBase64:"+DBase64);
                String QBase64 = DatatypeConverter.printBase64Binary(cipher.doFinal(DatatypeConverter.parseHexBinary(Q)));
                System.out.println("DBase64:"+QBase64);
                String DPBase64 = DatatypeConverter.printBase64Binary(cipher.doFinal(DatatypeConverter.parseHexBinary(DP)));
                System.out.println("DBase64:"+DPBase64);
                String DQBase64 = DatatypeConverter.printBase64Binary(cipher.doFinal(DatatypeConverter.parseHexBinary(DQ)));
                System.out.println("DBase64:"+DQBase64);
                String QinvBase64 = DatatypeConverter.printBase64Binary(cipher.doFinal(DatatypeConverter.parseHexBinary(Qinv)));
                System.out.println("DBase64:"+QinvBase64);
                //初始化RSA导入密钥请求
                ImportAsymmetricKeyRequest importReq = new ImportAsymmetricKeyRequest();
                importReq.setKeyId(keyId);
                importReq.setImportToken(token);
                importReq.setAsymmetricKeySpec("RSA_1024");
                importReq.setEncryptedKeyEncryptionKey(encryptedKeyMaterial);
                importReq.setAsymmetricKeyUsage("ENCRYPT_DECRYPT");
                EncryptedRsaKey rsaKey = new EncryptedRsaKey();
                rsaKey.setPublicKeyDer(publicDerBase64);
                rsaKey.setEncryptedD(DBase64);
                rsaKey.setEncryptedP(PBase64);
                rsaKey.setEncryptedQ(QBase64);
                rsaKey.setEncryptedDp(DPBase64);
                rsaKey.setEncryptedDq(DQBase64);
                rsaKey.setEncryptedQinv(QinvBase64);
                importReq.setEncryptedRsaKey(rsaKey);
                //导入RSA密钥
                KmsResponse res = client.importAsymmetricKey(importReq);
            }catch (BceServiceException e) {
                System.out.println(e.getMessage());
            } catch (BceClientException e) {
                System.out.println(e.getMessage());
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
    }
    上一篇
    计划删除密钥
    下一篇
    API参考