| ... | @@ -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 | }; |
| 231 | | 231 | |
| 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].*); |
| 238 | | 238 | |
| 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].*); |
| 242 | | 241 | |
| 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 | } |
| 260 | | 259 | |
| 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 | }; |
| 302 | | 311 | |
| ... | @@ -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); |
| 459 | | 468 | |
| 460 | // Blind the key pair | 469 | // Blind the key pair |
| 461 | const blind_kp = try BlindKeySignatures.blind(kp, blind); | 470 | const blind_kp = try BlindKeySignatures.blind(kp, blind, "ctx"); |
| 462 | | 471 | |
| 463 | // Sign a message and check that it can be verified with the blind public key | 472 | // 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); |
| 467 | | 476 | |
| 468 | // Unblind the public key | 477 | // 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 | } |