| ... | ... | @@ -385,15 +385,15 @@ pub const Ed25519 = struct { |
| 385 | 385 | ); |
| 386 | 386 | } |
| 387 | 387 | |
| 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( |
| 391 | 393 | 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. |
| 394 | 396 | noise: ?[noise_length]u8, |
| 395 | | /// Filled with cryptographically secure randomness. |
| 396 | | entropy: *const [noise_length]u8, |
| 397 | 397 | ) (IdentityElementError || KeyMismatchError || NonCanonicalError || WeakPublicKeyError)!Signer { |
| 398 | 398 | if (!mem.eql(u8, &key_pair.secret_key.publicKeyBytes(), &key_pair.public_key.toBytes())) { |
| 399 | 399 | return error.KeyMismatch; |
| ... | ... | @@ -401,7 +401,7 @@ pub const Ed25519 = struct { |
| 401 | 401 | const scalar_and_prefix = key_pair.secret_key.scalarAndPrefix(); |
| 402 | 402 | var h = Sha512.init(.{}); |
| 403 | 403 | h.update(&scalar_and_prefix.prefix); |
| 404 | | h.update(entropy); |
| 404 | h.update(&base_nonce); |
| 405 | 405 | if (noise) |*z| { |
| 406 | 406 | h.update(z); |
| 407 | 407 | } |
| ... | ... | @@ -411,6 +411,20 @@ pub const Ed25519 = struct { |
| 411 | 411 | |
| 412 | 412 | return Signer.init(scalar_and_prefix.scalar, nonce, key_pair.public_key); |
| 413 | 413 | } |
| 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 | } |
| 414 | 428 | }; |
| 415 | 429 | |
| 416 | 430 | /// A (signature, message, public_key) tuple for batch verification |
| ... | ... | @@ -748,9 +762,7 @@ test "signatures with streaming" { |
| 748 | 762 | const io = std.testing.io; |
| 749 | 763 | const kp = Ed25519.KeyPair.generate(io); |
| 750 | 764 | |
| 751 | | var entropy: [Ed25519.noise_length]u8 = undefined; |
| 752 | | io.random(&entropy); |
| 753 | | var signer = try kp.signer(null, &entropy); |
| 765 | var signer = try kp.signer(null, io); |
| 754 | 766 | signer.update("mes"); |
| 755 | 767 | signer.update("sage"); |
| 756 | 768 | const sig = signer.finalize(); |