Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support "pure" ML-DSA #422

Merged
merged 8 commits into from
Jan 30, 2025
Merged

Conversation

WillChilds-Klein
Copy link
Contributor

@WillChilds-Klein WillChilds-Klein commented Jan 28, 2025

Issue #, if available: i/ACCP-100

Description of changes:

Overview

This PR exposes ML-DSA functionality through the Signature, KeyPairGenerator, and KeyFactory JCA interfaces. The implementation closely follows our Ed25519 implementation, as both algorithms are currently used through AWS-LC's EVP_DigestSign API initialized with a NULL message digest (these newer algorithms use a fixed, non-parameterizable digest function per spec).

We also provide benchmarks for key generation, signing, and verifying.

Interoperability

This change has been written to be interoperable and forwards-compatible with other JCA provider ML-DSA implementations, such as BouncyCastle's and OpenJDK's JEP 497.

This means that ACCP callers cannot use JDK's NamedParameterSpec classes or BouncyCastle's MLDSAParameterSpec, but allows ACCP to provide ML-DSA on supported LTS JDK versions, independent of other providers. Instead of using ParameterSpec classes, callers can request a specific security level via the algorithm name passed into KeyPairGenerator.getInstance (if no level is specified, "ML-DSA-44" is the default, conforming to JEP 497):

KeyPairGenerator g = KeyPairGenerator.getInstance("ML-DSA-87");
KeyPair kp = g.generateKeyPair(); // an ML-DSA-87 key pair

g = KeyPairGenerator.getInstance("ML-DSA");
kp = g.generateKeyPair(); // an ML-DSA-44 key pair

We also update our BouncyCastle test dependency to 1.80, allowing us to pefrorm interoperability tests with BouncyCastle's ML-DSA implementation.

Limitations

As mentioned above, ACCP does not currently support ParameterSpec-based initialization on KeyPairGenerator instances. We also don't support keysize-based initialization as it is somewhat ambiguous for ML-DSA. These limitations may change in the future.

ACCP's ML-DSA keys cannot be used directly with BouncyCastle KeyFactory or Signature instances, as BouncyCastle only supports its own keys today. To use ACCP keys with BouncyCastle, callers will need to serialize them into X509EncodedKeySpec or PKCS8EncodedKeySpec instances and pass those to BouncyCastle's KeyFactory for conversion.

Finally, ACCP cannot yet deserialize ML-DSA private keys serialized by BouncyCastle. BouncyCastle currently encodes the private key's 32 byte seed upon serialization, while ACCP expects the fully expanded private key material.

Future Work

  • Migrate to streaming APIs in AWS-LC (we currently buffer entire message in memory)
  • Support deserializing private key seeds (e.g. from BouncyCastle) and expanding them (this will require AWS-LC supporting ibid., we're actively working on this)
  • Add ML-DSA to EvpSignatureTest suite (unblocked once we can parse BouncyCastle keys per above)
  • Interoperability tests with JDK 24 (once we support that version)

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@WillChilds-Klein WillChilds-Klein force-pushed the mldsa-pure branch 2 times, most recently from 4def8b6 to 152c285 Compare January 28, 2025 19:27
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked through EVP logic - lgtm

@WillChilds-Klein WillChilds-Klein changed the title [DRAFT] Support "pure" ML-DSA Support "pure" ML-DSA Jan 30, 2025
@WillChilds-Klein WillChilds-Klein marked this pull request as ready for review January 30, 2025 15:07
@WillChilds-Klein WillChilds-Klein requested a review from a team as a code owner January 30, 2025 15:07
Copy link
Contributor

@geedo0 geedo0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor comments, but would like to get those cleaned up before a merge.

Not that I necessarily agree with the stance, but lately we've been including complete KAT suites for every new algorithm to the library.

geedo0
geedo0 previously approved these changes Jan 30, 2025
src/com/amazon/corretto/crypto/provider/MlDsaGen.java Outdated Show resolved Hide resolved
geedo0
geedo0 previously approved these changes Jan 30, 2025
geedo0
geedo0 previously approved these changes Jan 30, 2025
@WillChilds-Klein
Copy link
Contributor Author

WillChilds-Klein commented Jan 30, 2025

@geedo0

lately we've been including complete KAT suites for every new algorithm to the library.

I would've included some KATs if it were straightforward. However, because ML-DSA introduces distinct randomness into each signature, signatures produced with identical parameters are unique. Since ACCP/JCA doesn't have a clean way of exposing AWS-LC's ML-DSA derandomization APIs, KATs for this PR are currently infeasible.

@WillChilds-Klein WillChilds-Klein enabled auto-merge (squash) January 30, 2025 20:10
alexw91
alexw91 previously approved these changes Jan 30, 2025
@WillChilds-Klein WillChilds-Klein dismissed stale reviews from alexw91 and geedo0 via 62ec16c January 30, 2025 21:14
@WillChilds-Klein WillChilds-Klein merged commit b2472a5 into corretto:main Jan 30, 2025
11 checks passed
@WillChilds-Klein WillChilds-Klein deleted the mldsa-pure branch January 30, 2025 23:39
WillChilds-Klein added a commit that referenced this pull request Feb 3, 2025
A [recent AWS-LC change][1], coupled with [ACCP's recent ML-DSA
support][2],
induces [failures][3] in AWS-LC's tip-of-ACCP-main integration test.

This is ultimately due to ACCP's current lack of support for
deserializing
BouncyCastle's ML-DSA private key encoding; ACCP expects the full key
while
BouncyCastle encodes only the 32 bytes seed. We're actively working on
supporting both formats, but until that lands we modify
`EvpKeyFactoryTest` to
use ACCP for all ML-DSA keypairs.

This was caught upstream in AWS-LC instead of ACCP's CI because:

1. ACCP pins AWS-LC version and doesn't currently test against AWS-LC
   tip-of-main
2. ACCP's EvpKeyFactoryTest cases for ML-DSA previously succeeded only
because
the de/serialized keys were never used. We were "successfully"
deserializing
BouncyCastle "keys" represented as a 32-byte seed, but never used them
cryptographically in EvpKeyFactoryTest. Doing so results in verification
failures as documented [here][4]. With AWS-LC's [recent change][1], the
cryptographic properties of raw private key material are exercised and
thus
   deserialization of seeds fails.

We also bump AWS-LC tracking version to include above in tests.

[1]:
aws/aws-lc@695c3a0
[2]:
#422
[3]:
https://github.com/aws/aws-lc/actions/runs/13084244974/job/36513185053
[4]:
https://github.com/corretto/amazon-corretto-crypto-provider/blob/aa9bfd2acc1c3539e2fe21630685b704930b9f74/tst/com/amazon/corretto/crypto/provider/test/MLDSATest.java#L239-L245
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants