authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2022-08-03 15:25:15+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-08-03 15:25:15+02:00
logfa321a07cd985c672879c091db6dd0aa6b66f0b7
tree637adcd8edf84f08e4f2f1129abd4e7e45d2d337
parent447a4cc115f5d105d49fcb3e970082b89e5a46dd
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

crypto.sign.ed25519: include a context string in blind key signatures (#12316)

The next revision of the specification is going to include a context string in the way blinded scalars are computed. See: https://github.com/cfrg/draft-irtf-cfrg-signature-key-blinding/issues/30#issuecomment-1180516152 https://github.com/cfrg/draft-irtf-cfrg-signature-key-blinding/pull/37

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

lib/std/crypto/25519/ed25519.zig+18-9
...@@ -229,15 +229,14 @@ pub const Ed25519 = struct {...@@ -229,15 +229,14 @@ pub const Ed25519 = struct {
229 blind_secret_key: BlindSecretKey,229 blind_secret_key: BlindSecretKey,
230 };230 };
231231
232 /// Blind an existing key pair with a blinding seed.232 /// Blind an existing key pair with a blinding seed and a context.
233 pub fn blind(key_pair: Ed25519.KeyPair, blind_seed: [blind_seed_length]u8) !BlindKeyPair {233 pub fn blind(key_pair: Ed25519.KeyPair, blind_seed: [blind_seed_length]u8, ctx: []const u8) !BlindKeyPair {
234 var h: [Sha512.digest_length]u8 = undefined;234 var h: [Sha512.digest_length]u8 = undefined;
235 Sha512.hash(key_pair.secret_key[0..32], &h, .{});235 Sha512.hash(key_pair.secret_key[0..32], &h, .{});
236 Curve.scalar.clamp(h[0..32]);236 Curve.scalar.clamp(h[0..32]);
237 const scalar = Curve.scalar.reduce(h[0..32].*);237 const scalar = Curve.scalar.reduce(h[0..32].*);
238238
239 var blind_h: [Sha512.digest_length]u8 = undefined;239 const blind_h = blindCtx(blind_seed, ctx);
240 Sha512.hash(blind_seed[0..], &blind_h, .{});
241 const blind_factor = Curve.scalar.reduce(blind_h[0..32].*);240 const blind_factor = Curve.scalar.reduce(blind_h[0..32].*);
242241
243 const blind_scalar = Curve.scalar.mul(scalar, blind_factor);242 const blind_scalar = Curve.scalar.mul(scalar, blind_factor);
...@@ -259,9 +258,8 @@ pub const Ed25519 = struct {...@@ -259,9 +258,8 @@ pub const Ed25519 = struct {
259 }258 }
260259
261 /// Recover a public key from a blind version of it.260 /// Recover a public key from a blind version of it.
262 pub fn unblindPublicKey(blind_public_key: [public_length]u8, blind_seed: [blind_seed_length]u8) ![public_length]u8 {261 pub fn unblindPublicKey(blind_public_key: [public_length]u8, blind_seed: [blind_seed_length]u8, ctx: []const u8) ![public_length]u8 {
263 var blind_h: [Sha512.digest_length]u8 = undefined;262 const blind_h = blindCtx(blind_seed, ctx);
264 Sha512.hash(&blind_seed, &blind_h, .{});
265 const inv_blind_factor = Scalar.fromBytes(blind_h[0..32].*).invert().toBytes();263 const inv_blind_factor = Scalar.fromBytes(blind_h[0..32].*).invert().toBytes();
266 const public_key = try (try Curve.fromBytes(blind_public_key)).mul(inv_blind_factor);264 const public_key = try (try Curve.fromBytes(blind_public_key)).mul(inv_blind_factor);
267 return public_key.toBytes();265 return public_key.toBytes();
...@@ -297,6 +295,17 @@ pub const Ed25519 = struct {...@@ -297,6 +295,17 @@ pub const Ed25519 = struct {
297 mem.copy(u8, sig[32..], s[0..]);295 mem.copy(u8, sig[32..], s[0..]);
298 return sig;296 return sig;
299 }297 }
298
299 /// Compute a blind context from a blinding seed and a context.
300 fn blindCtx(blind_seed: [blind_seed_length]u8, ctx: []const u8) [Sha512.digest_length]u8 {
301 var blind_h: [Sha512.digest_length]u8 = undefined;
302 var hx = Sha512.init(.{});
303 hx.update(&blind_seed);
304 hx.update(&[1]u8{0});
305 hx.update(ctx);
306 hx.final(&blind_h);
307 return blind_h;
308 }
300 };309 };
301};310};
302311
...@@ -458,7 +467,7 @@ test "ed25519 with blind keys" {...@@ -458,7 +467,7 @@ test "ed25519 with blind keys" {
458 crypto.random.bytes(&blind);467 crypto.random.bytes(&blind);
459468
460 // Blind the key pair469 // Blind the key pair
461 const blind_kp = try BlindKeySignatures.blind(kp, blind);470 const blind_kp = try BlindKeySignatures.blind(kp, blind, "ctx");
462471
463 // Sign a message and check that it can be verified with the blind public key472 // Sign a message and check that it can be verified with the blind public key
464 const msg = "test";473 const msg = "test";
...@@ -466,6 +475,6 @@ test "ed25519 with blind keys" {...@@ -466,6 +475,6 @@ test "ed25519 with blind keys" {
466 try Ed25519.verify(sig, msg, blind_kp.blind_public_key);475 try Ed25519.verify(sig, msg, blind_kp.blind_public_key);
467476
468 // Unblind the public key477 // Unblind the public key
469 const pk = try BlindKeySignatures.unblindPublicKey(blind_kp.blind_public_key, blind);478 const pk = try BlindKeySignatures.unblindPublicKey(blind_kp.blind_public_key, blind, "ctx");
470 try std.testing.expectEqualSlices(u8, &pk, &kp.public_key);479 try std.testing.expectEqualSlices(u8, &pk, &kp.public_key);
471}480}