Add ML-DSA post-quantum signatures (#25862)

ML-DSA is a post-quantum signature scheme that was recently
standardized by NIST.

Keys and signatures are pretty large, not making it a drop-in
replacement for classical signature schemes.

But if you are shipping keys that may still be used in 10 years
or whenever large quantum computers able to break ECC arrive,
it that ever happens, and you don't have the ability to replace
these keys, ML-DSA is for you.

Performance is great, verification is faster than Ed25519 / ECDSA.

I tried manual vectorization, but it wasn't worth it, the compiler
does at good job at auto-vectorization already.
This commit is contained in:
Frank Denis 2025-11-10 14:11:30 +01:00 committed by GitHub
parent cde865e06a
commit ce355e0ba5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 3612 additions and 2 deletions

View File

@ -197,6 +197,7 @@ pub const pwhash = struct {
pub const sign = struct { pub const sign = struct {
pub const Ed25519 = @import("crypto/25519/ed25519.zig").Ed25519; pub const Ed25519 = @import("crypto/25519/ed25519.zig").Ed25519;
pub const ecdsa = @import("crypto/ecdsa.zig"); pub const ecdsa = @import("crypto/ecdsa.zig");
pub const mldsa = @import("crypto/ml_dsa.zig");
}; };
/// Stream ciphers. These do not provide any kind of authentication. /// Stream ciphers. These do not provide any kind of authentication.

View File

@ -166,6 +166,9 @@ const signatures = [_]Crypto{
Crypto{ .ty = crypto.sign.ecdsa.EcdsaP256Sha256, .name = "ecdsa-p256" }, Crypto{ .ty = crypto.sign.ecdsa.EcdsaP256Sha256, .name = "ecdsa-p256" },
Crypto{ .ty = crypto.sign.ecdsa.EcdsaP384Sha384, .name = "ecdsa-p384" }, Crypto{ .ty = crypto.sign.ecdsa.EcdsaP384Sha384, .name = "ecdsa-p384" },
Crypto{ .ty = crypto.sign.ecdsa.EcdsaSecp256k1Sha256, .name = "ecdsa-secp256k1" }, Crypto{ .ty = crypto.sign.ecdsa.EcdsaSecp256k1Sha256, .name = "ecdsa-secp256k1" },
Crypto{ .ty = crypto.sign.mldsa.MLDSA44, .name = "ml-dsa-44" },
Crypto{ .ty = crypto.sign.mldsa.MLDSA65, .name = "ml-dsa-65" },
Crypto{ .ty = crypto.sign.mldsa.MLDSA87, .name = "ml-dsa-87" },
}; };
pub fn benchmarkSignature(comptime Signature: anytype, comptime signatures_count: comptime_int) !u64 { pub fn benchmarkSignature(comptime Signature: anytype, comptime signatures_count: comptime_int) !u64 {
@ -189,7 +192,12 @@ pub fn benchmarkSignature(comptime Signature: anytype, comptime signatures_count
return throughput; return throughput;
} }
const signature_verifications = [_]Crypto{Crypto{ .ty = crypto.sign.Ed25519, .name = "ed25519" }}; const signature_verifications = [_]Crypto{
Crypto{ .ty = crypto.sign.Ed25519, .name = "ed25519" },
Crypto{ .ty = crypto.sign.mldsa.MLDSA44, .name = "ml-dsa-44" },
Crypto{ .ty = crypto.sign.mldsa.MLDSA65, .name = "ml-dsa-65" },
Crypto{ .ty = crypto.sign.mldsa.MLDSA87, .name = "ml-dsa-87" },
};
pub fn benchmarkSignatureVerification(comptime Signature: anytype, comptime signatures_count: comptime_int) !u64 { pub fn benchmarkSignatureVerification(comptime Signature: anytype, comptime signatures_count: comptime_int) !u64 {
const msg = [_]u8{0} ** 64; const msg = [_]u8{0} ** 64;

View File

@ -34,5 +34,8 @@ pub const WeakPublicKeyError = error{WeakPublicKey};
/// Point is not in the prime order group /// Point is not in the prime order group
pub const UnexpectedSubgroupError = error{UnexpectedSubgroup}; pub const UnexpectedSubgroupError = error{UnexpectedSubgroup};
/// Context string is too long
pub const ContextTooLongError = error{ContextTooLong};
/// Any error related to cryptography operations /// Any error related to cryptography operations
pub const Error = AuthenticationError || OutputTooLongError || IdentityElementError || EncodingError || SignatureVerificationError || KeyMismatchError || NonCanonicalError || NotSquareError || PasswordVerificationError || WeakParametersError || WeakPublicKeyError || UnexpectedSubgroupError; pub const Error = AuthenticationError || OutputTooLongError || IdentityElementError || EncodingError || SignatureVerificationError || KeyMismatchError || NonCanonicalError || NotSquareError || PasswordVerificationError || WeakParametersError || WeakPublicKeyError || UnexpectedSubgroupError || ContextTooLongError;

3598
lib/std/crypto/ml_dsa.zig Normal file

File diff suppressed because it is too large Load Diff