diff --git a/src/crypto/ed25519.zig b/src/crypto/ed25519.zig index ea3a019..99f4621 100644 --- a/src/crypto/ed25519.zig +++ b/src/crypto/ed25519.zig @@ -2,9 +2,13 @@ const CryptoError = @import("../crypto.zig").CryptoError; // Constants and default implementation const Ed25519 = @import("std").crypto.sign.Ed25519; +const secureZero = @import("std").crypto.secureZero; // Random number generation const rngProvider = @import("random.zig").Implementation; +// Keypair type +pub const KeyPair = Ed25519.KeyPair; + pub const secret_key_length: comptime_int = Ed25519.SecretKey.encoded_length; pub const public_key_length: comptime_int = Ed25519.PublicKey.encoded_length; pub const signature_length : comptime_int = Ed25519.Signature.encoded_length; @@ -12,30 +16,28 @@ pub const seed_length : comptime_int = Ed25519.Signature.encoded_length; pub const Implementation = struct { - generateKeys: *const fn (pubkey_buffer: ?*[public_key_length]u8, privkey_buffer: *[secret_key_length]u8, rng: rngProvider) CryptoError!void, + generateKeys: *const fn (destination: *KeyPair, rng: rngProvider) CryptoError!void, sign: *const fn (key: *const [secret_key_length]u8, data: []const u8, signature_out: *const [signature_length]u8) CryptoError!void, verify: *const fn (key: *const [public_key_length]u8, signature: *const [signature_length]u8, data: []const u8) CryptoError!void, }; -pub fn generateKeys(pubkey_buffer: ?*[public_key_length]u8, privkey_buffer: *[secret_key_length]u8, rng: rngProvider) !void { +pub fn generateKeys (destination: *KeyPair, rng: rngProvider) !void { - var seed_buffer: [Ed25519.KeyPair.seed_length]u8 = undefined; + var seed_buffer: [KeyPair.seed_length]u8 = undefined; + defer secureZero(@TypeOf(seed_buffer), seed_buffer); rng.generate(&seed_buffer); - const keypair: Ed25519.KeyPair = Ed25519.KeyPair.generateDeterministic(seed_buffer) catch return CryptoError.FailedKeyGeneration; - - if (pubkey_buffer != null) @memcpy(pubkey_buffer.?[0..public_key_length], &keypair.public_key.bytes); - @memcpy(privkey_buffer[0..secret_key_length], &keypair.secret_key.bytes); + destination.* = KeyPair.generateDeterministic(seed_buffer) catch return CryptoError.FailedKeyGeneration; } -pub fn sign(key: *const [secret_key_length]u8, data: []const u8, signature_out: *const [signature_length]u8) !void { +pub fn sign (key: *const [secret_key_length]u8, data: []const u8, signature_out: *const [signature_length]u8) !void { _ = key; _ = data; _ = signature_out; return CryptoError.NotImplemented; } -pub fn verify(key: *const [public_key_length]u8, signature: *const [signature_length]u8, data: []const u8) !void { +pub fn verify (key: *const [public_key_length]u8, signature: *const [signature_length]u8, data: []const u8) !void { // TODO maybe find a more efficient way to do that (excessive copies) const sig = Ed25519.Signature.fromBytes(signature.*); const pubkey = Ed25519.PublicKey.fromBytes(key.*) catch return CryptoError.InvalidKey; diff --git a/src/crypto/x25519.zig b/src/crypto/x25519.zig index a350fa5..b6a7b80 100644 --- a/src/crypto/x25519.zig +++ b/src/crypto/x25519.zig @@ -6,6 +6,9 @@ const Ed25519 = @import("std").crypto.sign.Ed25519; // Random number generation const rngProvider = @import("random.zig").Implementation; +// Keypair type +pub const KeyPair = X25519.KeyPair; + pub const secret_key_length: comptime_int = X25519.secret_length; pub const public_key_length: comptime_int = X25519.public_length; pub const seed_length: comptime_int = X25519.seed_length; @@ -13,9 +16,9 @@ pub const seed_length: comptime_int = X25519.seed_length; pub const Implementation = struct { generateKeys: *const fn (pubkey_buffer: ?*[public_key_length]u8, privkey_buffer: *[secret_key_length]u8, rng: rngProvider) CryptoError!void, - fromEd25519: *const fn (ed25519_keypair: *Ed25519.Keypair, x25519_keypair: *X25519.KeyPair, rng: rngProvider) CryptoError!void, + fromEd25519: *const fn (ed25519_keypair: *Ed25519.KeyPair, x25519_keypair: *KeyPair) CryptoError!void, // TODO - // maybe switch to a Keypair system based on the stdlib implementation + // Switch to a Keypair system based on the stdlib implementation // generateKeys: *const fn (keypair: *X25519.KeyPair, rng: rngProvider) CryptoError!void, }; @@ -25,12 +28,12 @@ fn generateKeys (pubkey_buffer: ?*[public_key_length]u8, privkey_buffer: *[secre rng.generate(&seed_buffer); const keypair: X25519.KeyPair = X25519.KeyPair.generateDeterministic(seed_buffer) catch return CryptoError.FailedKeyGeneration; - if (pubkey_buffer != null) @memcpy(pubkey_buffer.?[0..public_key_length], &keypair.public_key.bytes); - @memcpy(privkey_buffer[0..secret_key_length], &keypair.secret_key.bytes); + if (pubkey_buffer != null) @memcpy(pubkey_buffer.?[0..public_key_length], &keypair.public_key); + @memcpy(privkey_buffer[0..secret_key_length], &keypair.secret_key); } -fn fromEd25519 (ed25519_keypair: *Ed25519.Keypair, x25519_keypair: *X25519.KeyPair) CryptoError!void { - x25519_keypair.* = X25519.KeyPair.fromEd25519(ed25519_keypair); +fn fromEd25519 (ed25519_keypair: *Ed25519.KeyPair, x25519_keypair: *KeyPair) CryptoError!void { + x25519_keypair.* = X25519.KeyPair.fromEd25519(ed25519_keypair.*) catch return CryptoError.InvalidKey; } pub const defaultImplementation: Implementation = .{ diff --git a/src/identity.zig b/src/identity.zig index e467daa..4c282ea 100644 --- a/src/identity.zig +++ b/src/identity.zig @@ -21,18 +21,31 @@ pub fn resolveIdentity(comptime crypto_engine: Crypto.Engine) type { //////// Fields // - privKey: [Crypto.Ed25519.secret_key_length]u8, - signatureKey: [Crypto.X25519.secret_key_size]u8, - hash: []const u8, + keys: Crypto.Ed25519.KeyPair, + signatureKeys: Crypto.X25519.KeyPair, + hash: [Crypto.Sha256.hash_len]u8, //////// Functions // - pub fn generate() !Self { + pub fn new() !Self { const result: Self = undefined; - crypto_engine.ed25519.generateKeys(null, &result.signatureKey, crypto_engine.random); - // TODO privKey and signature + crypto_engine.ed25519.generateKeys(result.keys, crypto_engine.random); + crypto_engine.x25519.fromEd25519(result.keys, result.signatureKeys, crypto_engine.random); + result.update_hash(); return result; } + + pub fn generate(self: *Self) !void { + crypto_engine.ed25519.generateKeys(self.keys, crypto_engine.random); + crypto_engine.x25519.fromEd25519(self.keys, self.signatureKeys, crypto_engine.random); + self.update_hash(); + } + + pub fn update_hash(self: *Self) void { + //WARNING PUBLIC KEY SHOULD BE TRUNCATED + // We should define the truncated hash length somewhere + crypto_engine.sha256.hash(self.keys.public_key, self.hash); + } }; } @@ -59,10 +72,10 @@ fn fillPattern(out: []u8) void { } } -pub fn generateFakeKeys(pubkey_buffer: *[pubkey_size]u8, privkey_buffer: *[privkey_size]u8, rng: Crypto.Random.Implementation) Crypto.CryptoError!void { +pub fn generateFakeKeys(destination: *Crypto.Ed25519.KeyPair, rng: Crypto.Random.Implementation) Crypto.CryptoError!void { _ = rng; - fillPattern(pubkey_buffer); - fillPattern(privkey_buffer); + fillPattern(&destination.public_key.bytes); + fillPattern(&destination.secret_key.bytes); } test "Basic identity generation" { @@ -72,6 +85,8 @@ test "Basic identity generation" { }; const fake_ed25519: Crypto.Ed25519.Implementation = .{ .generateKeys = generateFakeKeys, + .sign = undefined, + .verify = undefined, }; const crypto_engine = Crypto.resolveEngine(.{ .random = fake_rng, @@ -79,8 +94,8 @@ test "Basic identity generation" { }); const Identity = resolveIdentity(crypto_engine); - const new_id: Identity = try Identity.generate(); - + const new_id: Identity = undefined; + try new_id.generate(); try expect(memeql(u8, new_id.privKey, testPattern)); try expect(memeql(u8, new_id.signatureKey, testPattern));