AWS Security Blog
How to create post-quantum signatures using AWS KMS and ML-DSA
As the capabilities of quantum computing evolve, AWS is committed to helping our customers stay ahead of emerging threats to public-key cryptography. Today, we’re announcing the integration of FIPS 204: Module-Lattice-Based Digital Signature Standard (ML-DSA) into AWS Key Management Service (AWS KMS). Customers can now create and use ML-DSA keys through the same familiar AWS KMS APIs they use today for digital signatures, including CreateKey
, Sign
, and Verify
operations. This new feature is generally available and you can use ML-DSA in the following AWS Regions: US West (N. California), and Europe (Milan) with the remaining commercial Regions to follow in the coming days. This launch is part of our broader AWS post-quantum cryptography migration plan, which we covered in our recent blog post. In this post, we guide you through creating ML-DSA keys and post-quantum signatures with AWS KMS.
Many organizations use AWS KMS to cryptographically sign firmware, operating systems, applications, or other artifacts. With ML-DSA support in AWS KMS, you can now generate and use post-quantum keys for signing operations within FIPS-140-3 Level 3 certified HSMs. By implementing ML-DSA signatures now, you can help make sure that your systems remain secure throughout their operational lifetime, even if cryptographically relevant quantum computers become available. This is especially important for manufacturers who install long-lived roots of trust during production—whether embedded directly in hardware or in devices that might remain offline for extended periods. In both cases, cryptographic signatures cannot be easily updated after deployment, making post-quantum readiness critical for the entire operational lifetime of these systems.
What’s new
AWS KMS offers three new AWS KMS key specs: ML_DSA_44
, ML_DSA_65
, and ML_DSA_87
, which you can use with the new post-quantum SigningAlgorithm ML_DSA_SHAKE_256
. Like our other signing algorithms, this name includes the hash function that’s used within the signature scheme to digest messages before signing or verification. In this case, the hash function used is SHAKE256—part of the SHA-3 family of hash functions standardized by NIST in FIPS 202.
Table 1 shows the details for each key spec, including their NIST security categories and corresponding key sizes in bytes. Each ML-DSA key spec represents a balance between security strength and resource requirements. ML-DSA-44 is suitable for applications requiring security comparable to classical 128-bit encryption, while ML-DSA-65 and ML-DSA-87 provide progressively stronger security levels equivalent to classical 192-bit and 256-bit encryption, respectively. As you move up in security levels, you’ll notice corresponding increases in key and signature sizes, enabling you to choose the key spec that best matches your security needs and engineering constraints.
Key spec | NIST security Level | Public key (B) | Private key (B) | Signature (B) |
ML_DSA_44 | 1 (equivalent to 128-bit security) | 1312 | 2560 | 2420 |
ML_DSA_65 | 3 (equivalent to 192-bit security) | 1952 | 4032 | 3309 |
ML_DSA_87 | 5 (equivalent to 256-bit security) | 2592 | 4896 | 4627 |
When using the AWS KMS Sign API with a RAW MessageType, the message to be signed is limited to 4096 bytes. For messages larger than 4096 bytes, pre-processing the message outside of AWS KMS to create what’s known as µ (mu) is required to generate a smaller-sized message input to the KMS Sign API. This external mu process pre-digests the message using the public key of the ML-DSA signing key pair to create a message size of 64 bytes. To support this launch, we’ve added a new message type in the KMS Sign API—EXTERNAL_MU
—that can be used with ML-DSA signing or verification calls to indicate when a message has been pre-processed using µ (mu) before submitted to AWS KMS.
In the following sections, we include more information about constructing external mu and demonstrate basic AWS KMS operations with ML-DSA. We cover key creation, signature generation and verification, and both RAW
and EXTERNAL_MU
signing modes. Note that the produced RAW
or EXTERNAL_MU
ML-DSA signatures are identical when the same message and signing key are used.
Creating ML-DSA keys
To start, create an asymmetric AWS KMS key using the AWS Command Line Interface (AWS CLI) example command:
This command will return a response similar to the following:
Make note of the KeyId
or Arn
value from the response; you’ll need this to reference your key in subsequent signing operations. The response confirms that the creation of an ML_DSA_65
key configured for SIGN_VERIFY
operations, which will use the ML_DSA_SHAKE_256
signing algorithm for signature operations.
Signing
In this section, we include some examples of ML-DSA signing and verifying a JSON Web Token (JWT) commonly used to transfer claims between parties for web authorization. In 2021, we described how to sign and verify JWTs with Elliptic Curve Digital Signature Algorithm (ECDSA), a classic asymmetric cryptographic algorithm (see How to verify AWS KMS signatures in decoupled architectures at scale). In the following examples, the token is instead signed with an ML-DSA private key managed by AWS KMS and verified either within AWS KMS or externally using OpenSSL.
The JWT content to be signed is from section 3.1 of RFC7519. More specifically, the JWT header is:
And the JWT claim set is:
You can produce the JWT message to be signed by using the Base64URL encoding of the header and payload as:
This command will output the following Base64 to be signed with ML-DSA:
Note that the following examples output the ML-DSA signature produced on the message by using the ML-DSA private key managed by AWS KMS in a binary format. You need to convert them to Base64URL to use them in JWT, but various data encryption and signing formats can use these signatures. These include Cryptographic Message Syntax (CMS), CBOR Object Signing and Encryption (COSE), or image signing encodings for UEFI and Open Titan. While converting between binary and these formats is straightforward, support for the new algorithms might not be available in common cryptographic implementations of these signing formats at the time of this writing.
RAW ML-DSA signing (no external mu)
To sign a message of less than 4096 bytes in AWS KMS with ML-DSA, you can use the AWS CLI:aws kms sign \
Make sure to replace the target-key-id
value of <1234abcd-12ab-34cd-56ef-1234567890ab>
with your KeyId
. This command will produce a signature and write it to disk as ExampleSignature.bin
.
After producing the signature, you can create the complete JWT (consisting of header, payload, and signature) with a single command:
This command will output a ready-to-use JWT in the format required by RFC 7519 and signed using AWS KMS:
External mu ML-DSA signing
Note that AWS KMS imposes a 4096-byte limit on the size of the raw message when using the Sign API to minimize the latency of the response. In cases where the message to be signed is larger than 4096 bytes or if pre-digesting the external mu has performance advantages you need, you must use the EXTERNAL_MU
message type instead of RAW
in AWS KMS.
Before using the EXTERNAL_MU
message type with the AWS KMS Sign API, you must locally perform a pre-hash calculation on your message. So, first, retrieve the public key from AWS KMS, and convert it to DER format using the following command (replace the example key ID with a valid key ID from your AWS account):
To construct the external mu digest:
- Construct a message prefix
(M`)
:M` = (domain separator || context length || context || Message)
.In this example, set the domain separator value and context length as zero; this sets the context used in the signature as the empty string, which is the default.
- Hash the public key then prepend it to the message prefix:
(SHAKE256(pk) || M’)
. - Hash to produce a 64-byte mu:
Mu = SHAKE256(SHAKE256(pk) || M’)
You can use a single OpenSSL 3.5 command to construct the digest:
Now you can call AWS KMS to sign the 64-byte digest to produce the ML-DSA signature in file ExampleSignature.bin
, making sure to set the MessageType
to EXTERNAL_MU
:
The final signed JWT token is identical to the one produced previously in RAW mode.
Signature verification using AWS KMS
In this section, we show you how to verify ML-DSA signatures using AWS KMS or locally in your own environment. We assume that you have an ML-DSA signature in ExampleSignature.bin
, produced on the JWT content with the private key in AWS KMS and identified with KEY_ARN
.
Note that, although the following examples demonstrate signature verification using public keys directly from AWS KMS, these same principles extend to certificate-based systems, such as a private PKI, in which public keys are embedded in end-entity certificates (of the signer). In such scenarios, verifiers would first verify the identity of the signer by validating the certificate chain ties to a trusted root, then use the public key of the end-entity certificate to verify the ML-DSA signature of the content. The IETF is standardizing ML-DSA for use in X.509 certificates through RFC draft draft-ietf-lamps-dilithium-certificates.
RAW ML-DSA verification
To verify the signature using AWS KMS, you can call the following command, replacing the example key-id
with the same one you used to sign.
The response will return:
The verification result is stored in the SignatureValid
field.
External mu ML-DSA verification
If you have the external mu digest of the JWT content in mu.bin
along with the signature and the corresponding keypair in AWS KMS, you can use the digest without having access to the entire message or calculating the digest again.
To regenerate the external mu mu.bin
from the message and the public key, see the External mu ML DSA signing section above.
Local signature verification using OpenSSL 3.5
If you want to reduce AWS KMS API consumption costs and better control the use of API quotas while keeping the security of AWS KMS-generated and stored keys for ML-DSA signature generation, you can verify ML-DSA signatures locally, outside of AWS KMS.
In this example, you use OpenSSL 3.5 to verify the signature in ExampleSignature.bin
. You first must fetch the DER-encoded public key from AWS KMS in file public_key.der
as shown in the External mu ML DSA signing section. OpenSSL 3.5 can then verify the signature on the message by using the public key.
Successful verification will output: Verified OK
Conclusion
Today’s launch of ML-DSA support in AWS KMS marks an important milestone in our commitment to post-quantum cryptography. With three different security levels of ML-DSA in both raw and external digest modes, you have flexible options to meet your security requirements while preparing for the quantum computing era. The seamless integration with existing AWS KMS APIs makes it straightforward to incorporate quantum-resistant signatures into your applications today. This implementation is particularly valuable if you need to:
- Meet FIPS 140-3 compliance requirements when using post-quantum cryptography.
- Sign code, artifacts, documents or other data that need to remain trusted and verifiable for many years into the future, including the period after cryptographically relevant quantum computers exist.
- Start post-quantum cryptography testing as part of your application development process using a cryptographic service such as AWS KMS that has previously been approved for use.
Learn more about post-quantum cryptography in general and the overall AWS plan to migrate to post-quantum cryptography.