How do I verify signatures generated by AWS KMS asymmetric keys?

3 minute read
1

I want to use AWS Key Management Service (AWS KMS) to sign a file. Then, I want to share the file, its signature, and the public key for verification that the signature is valid. I don't want to provide API access for users to access my AWS KMS key.

Resolution

The following example uses AWS KMS with an ECC_NIST_P256 (secp256r1) asymmetric key pair. When AWS KMS uses this key pair to generate a signature file, the file is created according to NIST FIPS 168-4. An ECDSA digital signature that contains (r, s) values is generated as specified in ANS X9.62. Because of the open standard, you can use OpenSSL to verify the signature.

To get the signature format for RSA key pairs, see RSA key specs for signing and verification.

Note: If you receive errors when you run AWS Command Line Interface (AWS CLI) commands, then see Troubleshooting errors for the AWS CLI. Also, make sure that you're using the most recent AWS CLI version.

Sign a local file

After you create the AWS KMS asymmetric key in your AWS account, use the AWS CLI to refer to the key when you sign a file. The response you receive from the AWS KMS API is encoded in base64. The following example uses the --query parameter to get the signature value from the response and place it in the sign.b64 file:

[ec2-user@ip-172-31-23-22 ~]$ aws kms sign --key-id arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab --message fileb://message.txt --signing-algorithm ECDSA_SHA_256 --query 'Signature' --output text > sign.b64

Note: You can submit messages up to 4096 B. To sign a larger message, generate a hash digest of the message. Then, provide the hash digest in the message parameter. To show whether the message is a full message or a digest, use the MessageType parameter. Note the signing algorithm to verify the signature later.

Because the signature is in base64 format, run the following Linux base64 encoding command to convert the format to binary:

[ec2-user@ip-172-31-23-22 ~]$ base64 -d sign.b64 > sign.bin

Run the following command to decode base64 files for Windows operating system (OS):

certutil -decode C:\Temp\sign.b64 C:\Temp\sign.bin

You can now share the sign.b64 signature file.

Verify the AWS KMS signature

To verify the signature file, you must have the public key. To get the public key, run the get-public-key AWS CLI command:

[ec2-user@ip-172-31-23-22 ~]$ aws kms get-public-key --key-id arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab --output text --query 'PublicKey' > KMSPublic.b64

Run the following command to convert the base64 file to a DER-encoded file that's named KMSPublic.key:

[ec2-user@ip-172-31-23-22 ~]$ base64 -d KMSPublic.b64 > KMSPublic.key

You now have the public key and signature in binary format with the message.txt file.

To verify the signature, run the dgst OpenSSL command:

[ec2-user@ip-172-31-23-22 ~]$ openssl dgst -sha256 -verify KMSPublic.key -keyform DER -signature sign.bin message.txtVerified OK

The verification is successful when the output shows "Verified OK".

If you don't receive a verification response, then check the following:

  • The OpenSSL signature algorithm is the same one that you used to sign the file.
  • Your files aren't base64 encoded.

Related information

Cryptographic primitives

AWS KMS concepts

AWS OFFICIAL
AWS OFFICIALUpdated 2 months ago
1 Comment

I tried this and the openssl response is

Could not find private key of public key from MyPublicKey_ECC_NIST_P256.bin

which makes sense to me, since the private key is meant to stay within AWS KMS.

I used this version of openssl:

OpenSSL 3.3.1 4 Jun 2024 (Library: OpenSSL 3.3.1 4 Jun 2024)

Nonetheless I would like to be able to verify a signature using non-aws tools, so if there is a slight change to the OPENSSL syntax which would let this work, I would be very interested.

replied 4 months ago