authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2026-01-07 23:02:46+01:00
committergravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2026-01-07 23:02:46+01:00
logcd8f0aa4ca174ae1d43232d20f27120bcd74e71f
tree9dcc966ce483e3561768845514fccf2d822a831b
parent22380c78b1f9fd714ea6c89d2b902846ccf2e4f9

Add signerWithBaseNonce


1 files changed, 22 insertions(+), 9 deletions(-)

lib/std/crypto/25519/ed25519.zig+22-9
......@@ -385,24 +385,23 @@ pub const Ed25519 = struct {
385385 );
386386 }
387387
388 /// Create a Signer, that can be used for incremental signing.
389 /// Note that the signature is not deterministic.
390 pub fn signer(
388 /// Create a signer that can be used for incremental signing, using a custom base nonce.
389 /// `base_nonce` must be unique for each signed message; otherwise, the secret key can
390 /// be trivially recovered by an attacker.
391 /// It can be generated using a cryptographically secure random number generator.
392 pub fn signerWithBaseNonce(
391393 key_pair: KeyPair,
392 /// If set, should be something unique for each message, such as a
393 /// random nonce, or a counter.
394 base_nonce: [32]u8,
395 /// If set, should be something unique for each message, such as a counter.
394396 noise: ?[noise_length]u8,
395 io: std.Io,
396397 ) (IdentityElementError || KeyMismatchError || NonCanonicalError || WeakPublicKeyError)!Signer {
397398 if (!mem.eql(u8, &key_pair.secret_key.publicKeyBytes(), &key_pair.public_key.toBytes())) {
398399 return error.KeyMismatch;
399400 }
400401 const scalar_and_prefix = key_pair.secret_key.scalarAndPrefix();
401 var entropy: [noise_length]u8 = undefined;
402 io.random(&entropy);
403402 var h = Sha512.init(.{});
404403 h.update(&scalar_and_prefix.prefix);
405 h.update(&entropy);
404 h.update(&base_nonce);
406405 if (noise) |*z| {
407406 h.update(z);
408407 }
......@@ -412,6 +411,20 @@ pub const Ed25519 = struct {
412411
413412 return Signer.init(scalar_and_prefix.scalar, nonce, key_pair.public_key);
414413 }
414
415 /// Create a Signer, that can be used for incremental signing.
416 /// Note that the signature is not deterministic.
417 pub fn signer(
418 key_pair: KeyPair,
419 /// If set, should be something unique for each message, such as a
420 /// random nonce, or a counter.
421 noise: ?[noise_length]u8,
422 io: std.Io,
423 ) (IdentityElementError || KeyMismatchError || NonCanonicalError || WeakPublicKeyError)!Signer {
424 var base_nonce: [32]u8 = undefined;
425 io.random(&base_nonce);
426 return key_pair.signerWithBaseNonce(base_nonce, noise);
427 }
415428 };
416429
417430 /// A (signature, message, public_key) tuple for batch verification