AWS KMS入门教程

2,656 阅读3分钟

一、KMS介绍

密钥管理服务(Key Management Service)是针对云上数据加密需求精心设计的密码应用服务,可以为应用提供符合国密要求的密钥服务及极简应用加解密服务,可以帮助我们轻松使用密钥来加密保护敏感的数据资产。

1. 适用场景

  • 加密和解密数据,使用 AWS Encryption SDK 安全地处理应用程序中的加密操作。
  • 签名并验证数字签名,使用非对称 KMS 密钥保护通过 AWS KMS 执行的签名操作。
  • 使用 HMAC 验证 JSON Web 令牌,使用 AWS KMS 生成 HMAC,以验证消息的完整性和身份验证。
  • 与其他AWS服务集成使用,比如:可选择使用 AWS KMS 中的 KMS 密钥为 Amazon RDS实例上存储的数据加密。

2. 优势

  • 完全托管,具有可扩展性、持久性和高可用性;
  • 提供了单一控制点,集中式管理密钥,可以随时创建新密钥,以及对密钥的生命周期和权限进行集中控制;
  • KMS与AWS服务集成,可简化密钥使用以加密AWS工作负载中的数据;
  • 成本低廉,使用KMS服务不需要事先承诺用量,也没有预付费用。

3. 费用

  • 每 10000 个请求0.03 USD
  • 每 10000 个涉及 RSA 2048 密钥的请求0.03 USD
  • 每 10000 个 ECC GenerateDataKeyPair 请求0.10 USD
  • 每 10000 个非对称请求0.15 USD, RSA 2048 除外
  • 每 10,000 个 RSA GenerateDataKeyPair 请求12.00 USD

二、如何使用创建密钥

1. 配置密钥

image.png

2. 添加标签

image.png

3. 定义密钥管理权限

在创建页面定义密钥管理权限。

4. 定义密钥使用权限

在创建页面定义密钥使用权限。

三、Java Api

1. 引入pom

<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-java-sdk-kms</artifactId>
    <version>1.12.405</version>
</dependency>

2. 测试代码

注意:所有api中的algorithm参数都要和创建密钥所选匹配,代码中的keyId要替换为自己创建的。

2.1 使用非对称加密算法RSA加密数据。

/**
 * 数据加解密 公钥加密 私钥解密
 *
 * https://docs.aws.amazon.com/zh_cn/kms/latest/APIReference/API_Encrypt.html
 * https://docs.aws.amazon.com/zh_cn/kms/latest/APIReference/API_Decrypt.html
 **/
public class RSA {
    private static final String algorithm = "RSAES_OAEP_SHA_256";

    private static final String keyId = "your-keyId";

    public static void main(String[] args) {
        AWSKMS kmsClient = AWSKMSClientBuilder.standard()
                .withRegion(Regions.US_EAST_1)
                .build();

        String originalText = "hello world !!!";
        ByteBuffer plaintext = ByteBuffer.wrap(originalText.getBytes(StandardCharsets.UTF_8));

        // 加密
        EncryptRequest encryptRequest = new EncryptRequest()
                .withEncryptionAlgorithm(algorithm)
                .withKeyId(keyId)
                .withPlaintext(plaintext);
        ByteBuffer cipherText = kmsClient.encrypt(encryptRequest).getCiphertextBlob();
        System.out.println("加密前: " + originalText);
        System.out.println("加密后: " + StringUtils.fromByteBuffer(cipherText));

        // 解密
        DecryptRequest decryptRequest = new DecryptRequest()
                .withEncryptionAlgorithm(algorithm)
                .withKeyId(keyId)
                .withCiphertextBlob(cipherText);
        ByteBuffer plainText = kmsClient.decrypt(decryptRequest).getPlaintext();
        String str = StandardCharsets.UTF_8.decode(plainText).toString();
        System.out.println("解密后: " + str);
    }
}

2.2 使用 HMAC 验证 JSON Web 令牌

/**
 * https://docs.aws.amazon.com/zh_cn/kms/latest/APIReference/API_GenerateMac.html
 * https://docs.aws.amazon.com/zh_cn/kms/latest/APIReference/API_VerifyMac.html
 */
public class HMAC {
    private static final String algorithm = "HMAC_SHA_224";

    private static final String keyId = "your-keyId";

    public static void main(String[] args) {
        AWSKMS kmsClient = AWSKMSClientBuilder.standard()
                .withRegion(Regions.US_EAST_1)
                .build();

        String originalText = "hello world !!!";
        ByteBuffer plaintext = ByteBuffer.wrap(originalText.getBytes(StandardCharsets.UTF_8));

        // 计算hmac
        GenerateMacRequest generateMacRequest = new GenerateMacRequest()
                .withMacAlgorithm(algorithm)
                .withMessage(plaintext)
                .withKeyId(keyId);
        ByteBuffer mac = kmsClient.generateMac(generateMacRequest).getMac();
        String str = String.valueOf(Base64Decoder.decode(mac.array()));
        System.out.println("生成的mac为:" + str);

        // 验证hmac
        VerifyMacRequest verifyMacRequest = new VerifyMacRequest()
                .withMac(mac)
                .withMacAlgorithm(algorithm)
                .withMessage(plaintext)
                .withKeyId(keyId);
        Boolean macValid = kmsClient.verifyMac(verifyMacRequest).getMacValid();
        System.out.println("验证mac结果: " + macValid);
    }
}

2.3 签名认证

/**
 * 私钥加签 公钥验签 用于身份认证
 * <p>
 * https://docs.aws.amazon.com/zh_cn/kms/latest/APIReference/API_Sign.html
 * https://docs.aws.amazon.com/zh_cn/kms/latest/APIReference/API_Verify.html
 **/
public class VerifySign {
    private static final String algorithm = "RSASSA_PSS_SHA_256";

    private static final String keyId = "your-keyId";

    public static void main(String[] args) {
        AWSKMS kmsClient = AWSKMSClientBuilder.standard()
                .withRegion(Regions.US_EAST_1)
                .build();

        String originalText = "hello world !!!";
        ByteBuffer plaintext = ByteBuffer.wrap(originalText.getBytes(StandardCharsets.UTF_8));

        // 私钥加密
        SignRequest signRequest = new SignRequest()
                .withSigningAlgorithm(algorithm)
                .withKeyId(keyId)
                .withMessage(plaintext);
        ByteBuffer signature = kmsClient.sign(signRequest).getSignature();
        System.out.println("签名前: " + originalText);
        System.out.println("签名后: " + StringUtils.fromByteBuffer(signature));

        // 公钥验证
        VerifyRequest verifyRequest = new VerifyRequest()
                .withMessage(plaintext)
                .withSignature(signature)
                .withSigningAlgorithm(algorithm)
                .withKeyId(keyId);

        VerifyResult verifyResult = kmsClient.verify(verifyRequest);
        System.out.println("验证结果: " + verifyResult.getSignatureValid());
    }
}

四、总结

我们平时自己写代码去完成RSA加解密、HMAC验证等算法,不可避免要将私钥给前端或者对接方,可能会有密钥暴露给别人的风险。而kms只需要使用keyId就可以完成加解密,而且kms由aws iam做权限控制,可以做到对密钥使用方的精细权限控制,安全性比较高。

五、参考资料

docs.aws.amazon.com/zh_cn/kms/l…