commit cd8f0aa4ca174ae1d43232d20f27120bcd74e71f (tree)
parent 22380c78b1f9fd714ea6c89d2b902846ccf2e4f9
Author: Frank Denis <github@pureftpd.org>
Date: Wed, 7 Jan 2026 23:02:46 +0100
Add signerWithBaseNonce
Diffstat:
1 file changed, 22 insertions(+), 9 deletions(-)
diff --git a/lib/std/crypto/25519/ed25519.zig b/lib/std/crypto/25519/ed25519.zig
@@ -385,24 +385,23 @@ pub const Ed25519 = struct {
);
}
- /// Create a Signer, that can be used for incremental signing.
- /// Note that the signature is not deterministic.
- pub fn signer(
+ /// Create a signer that can be used for incremental signing, using a custom base nonce.
+ /// `base_nonce` must be unique for each signed message; otherwise, the secret key can
+ /// be trivially recovered by an attacker.
+ /// It can be generated using a cryptographically secure random number generator.
+ pub fn signerWithBaseNonce(
key_pair: KeyPair,
- /// If set, should be something unique for each message, such as a
- /// random nonce, or a counter.
+ base_nonce: [32]u8,
+ /// If set, should be something unique for each message, such as a counter.
noise: ?[noise_length]u8,
- io: std.Io,
) (IdentityElementError || KeyMismatchError || NonCanonicalError || WeakPublicKeyError)!Signer {
if (!mem.eql(u8, &key_pair.secret_key.publicKeyBytes(), &key_pair.public_key.toBytes())) {
return error.KeyMismatch;
}
const scalar_and_prefix = key_pair.secret_key.scalarAndPrefix();
- var entropy: [noise_length]u8 = undefined;
- io.random(&entropy);
var h = Sha512.init(.{});
h.update(&scalar_and_prefix.prefix);
- h.update(&entropy);
+ h.update(&base_nonce);
if (noise) |*z| {
h.update(z);
}
@@ -412,6 +411,20 @@ pub const Ed25519 = struct {
return Signer.init(scalar_and_prefix.scalar, nonce, key_pair.public_key);
}
+
+ /// Create a Signer, that can be used for incremental signing.
+ /// Note that the signature is not deterministic.
+ pub fn signer(
+ key_pair: KeyPair,
+ /// If set, should be something unique for each message, such as a
+ /// random nonce, or a counter.
+ noise: ?[noise_length]u8,
+ io: std.Io,
+ ) (IdentityElementError || KeyMismatchError || NonCanonicalError || WeakPublicKeyError)!Signer {
+ var base_nonce: [32]u8 = undefined;
+ io.random(&base_nonce);
+ return key_pair.signerWithBaseNonce(base_nonce, noise);
+ }
};
/// A (signature, message, public_key) tuple for batch verification