struct key_blinding [src]

Ed25519 signatures with key blinding.

Members

Source

pub const key_blinding = struct { /// Length (in bytes) of a blinding seed. pub const blind_seed_length = 32; /// A blind secret key. pub const BlindSecretKey = struct { prefix: [64]u8, blind_scalar: CompressedScalar, blind_public_key: BlindPublicKey, }; /// A blind public key. pub const BlindPublicKey = struct { /// Public key equivalent, that can used for signature verification. key: PublicKey, /// Recover a public key from a blind version of it. pub fn unblind(blind_public_key: BlindPublicKey, blind_seed: [blind_seed_length]u8, ctx: []const u8) (IdentityElementError || NonCanonicalError || EncodingError || WeakPublicKeyError)!PublicKey { const blind_h = blindCtx(blind_seed, ctx); const inv_blind_factor = Scalar.fromBytes(blind_h[0..32].*).invert().toBytes(); const pk_p = try (try Curve.fromBytes(blind_public_key.key.bytes)).mul(inv_blind_factor); return PublicKey.fromBytes(pk_p.toBytes()); } }; /// A blind key pair. pub const BlindKeyPair = struct { blind_public_key: BlindPublicKey, blind_secret_key: BlindSecretKey, /// Create an blind key pair from an existing key pair, a blinding seed and a context. pub fn init(key_pair: Ed25519.KeyPair, blind_seed: [blind_seed_length]u8, ctx: []const u8) (NonCanonicalError || IdentityElementError)!BlindKeyPair { var h: [Sha512.digest_length]u8 = undefined; Sha512.hash(&key_pair.secret_key.seed(), &h, .{}); Curve.scalar.clamp(h[0..32]); const scalar = Curve.scalar.reduce(h[0..32].*); const blind_h = blindCtx(blind_seed, ctx); const blind_factor = Curve.scalar.reduce(blind_h[0..32].*); const blind_scalar = Curve.scalar.mul(scalar, blind_factor); const blind_public_key = BlindPublicKey{ .key = try PublicKey.fromBytes((Curve.basePoint.mul(blind_scalar) catch return error.IdentityElement).toBytes()), }; var prefix: [64]u8 = undefined; prefix[0..32].* = h[32..64].*; prefix[32..64].* = blind_h[32..64].*; const blind_secret_key = BlindSecretKey{ .prefix = prefix, .blind_scalar = blind_scalar, .blind_public_key = blind_public_key, }; return BlindKeyPair{ .blind_public_key = blind_public_key, .blind_secret_key = blind_secret_key, }; } /// Sign a message using a blind key pair, and optional random noise. /// Having noise creates non-standard, non-deterministic signatures, /// but has been proven to increase resilience against fault attacks. pub fn sign(key_pair: BlindKeyPair, msg: []const u8, noise: ?[noise_length]u8) (IdentityElementError || KeyMismatchError || NonCanonicalError || WeakPublicKeyError)!Signature { const scalar = key_pair.blind_secret_key.blind_scalar; const prefix = key_pair.blind_secret_key.prefix; return (try PublicKey.fromBytes(key_pair.blind_public_key.key.bytes)) .computeNonceAndSign(msg, noise, scalar, &prefix); } }; /// Compute a blind context from a blinding seed and a context. fn blindCtx(blind_seed: [blind_seed_length]u8, ctx: []const u8) [Sha512.digest_length]u8 { var blind_h: [Sha512.digest_length]u8 = undefined; var hx = Sha512.init(.{}); hx.update(&blind_seed); hx.update(&[1]u8{0}); hx.update(ctx); hx.final(&blind_h); return blind_h; } }