如何在不使用 awssdk 的情况下使用普通 java 中的公钥来加密 AWS KMS 的数据

问题描述 投票:0回答:1

您好,我正在尝试使用纯 java 中 AWS KMS 中生成的 cmk 公钥来加密文本,而不使用 awssdk:

我生成的密钥的规格如下 -

在此输入图片描述

Key type:Asymmetric
Origin:AWS KMS
Key spec:RSA_2048
Key usage:Encrypt and decrypt
Encryption algorithms:RSAES_OAEP_SHA_1,RSAES_OAEP_SHA_256

这是我写的java代码-

    // Convert a Base64-encoded public key string into a PublicKey object
    public static PublicKey getPublicKeyFromString(String base64PublicKey) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(base64PublicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(keySpec);
    }

    // Encrypt the plaintext using the public key
    public static String encryptData(PublicKey publicKey, String plaintext) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        OAEPParameterSpec oaepParams = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey, oaepParams);

        byte[] ciphertext = cipher.doFinal(plaintext.getBytes());
        return Base64.getEncoder().encodeToString(ciphertext);
    }

    public static void main(String[] args) throws Exception {
        String base64PublicKey = "my_public_key";

        PublicKey publicKey = getPublicKeyFromString(base64PublicKey);

        String plaintext = "Sensitive Data";
        String encryptedData = encryptData(publicKey, plaintext);

        System.out.println(encryptedData);
    }

它工作正常并生成 Base64 格式的密文输出。

但问题是当我尝试使用 aws kms 服务解密它时,它抛出

InvalidCiphertextException('An error occurred (InvalidCiphertextException) when calling the Decrypt operation: ')

Python中的解密块如下所示:

def decrypt_kms(cipher_text: str, key_id: str) -> str:
    session = boto3.session.Session()
    kms_client = session.client(service_name="kms", region_name=AWS_REGION_NAME)

    try:
        encrypted_data = base64.b64decode(cipher_text)

        response = kms_client.decrypt(
            CiphertextBlob=encrypted_data,
            KeyId=key_id,
            EncryptionAlgorithm="RSAES_OAEP_SHA_256",
        )

        # The decrypted plaintext (as bytes)
        decrypted_data = response["Plaintext"]

        # Convert decrypted data to string (assuming UTF-8 encoding)
        return decrypted_data.decode("utf-8")
    except (BotoCoreError, ClientError) as error:
        rep = repr(error)
        logger.error(rep)
        return None

任何关于我做错的事情的帮助都会非常有用,谢谢!

Java端加密工作正常,并生成base64格式的密文输出。但生成的输出无法使用 python 端的 kms 服务成功加密。

当我尝试在 python 端使用 aws kms 服务解密它时,它抛出:

InvalidCiphertextException('An error occurred (InvalidCiphertextException) when calling the Decrypt operation: ')

在python中,当我使用kms服务本身进行加密时,上面的解密方法可以很好地解密。这让我觉得我在 java 端放入的加密配置存在一些问题。

编辑:我无法使用 awssdk,因为我添加加密部分的服务不允许添加外部依赖项。

python java encryption rsa amazon-kms
1个回答
0
投票

以防万一其他人将来偶然发现这一点,这就是最终对我有用的 -

Java端加密方法(无awssdk或外部库)-

public static byte[] encryptData(String plainText, PublicKey publicKey) throws GeneralSecurityException {
    AlgorithmParameters parameters = AlgorithmParameters.getInstance("OAEP");
    AlgorithmParameterSpec specification = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
    parameters.init(specification);
    Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
    cipher.init(Cipher.ENCRYPT_MODE, publicKey, parameters);
    return cipher.doFinal(plainText.getBytes());
}

使用aws库boto3的Python端解密方法 -

def decrypt_kms(cipher_text: str, key_id: str) -> str:
    session = boto3.session.Session()
    kms_client = session.client(service_name="kms", region_name=AWS_REGION_NAME)

    try:
        encrypted_data = base64.b64decode(cipher_text)

        response = kms_client.decrypt(
            CiphertextBlob=encrypted_data,
            KeyId=key_id,
            EncryptionAlgorithm="RSAES_OAEP_SHA_256",
        )

        decrypted_data = response["Plaintext"]

        return decrypted_data.decode("utf-8")
    except (BotoCoreError, ClientError) as error:
        rep = repr(error)
        logger.error(rep)
        return None

使用上面的代码,在java端加密的数据在python端解密成功。

© www.soinside.com 2019 - 2024. All rights reserved.