From 4a267c135c553f5eb8f2c99cf5ff53873aad815a Mon Sep 17 00:00:00 2001 From: "Gu://em_" Date: Mon, 20 Jul 2026 00:07:09 +0200 Subject: [PATCH 1/6] Changed crypto primitives naming to be more consistent --- src/crypto.zig | 58 +++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/crypto.zig b/src/crypto.zig index 921b0d0..5f6c7ad 100644 --- a/src/crypto.zig +++ b/src/crypto.zig @@ -1,14 +1,14 @@ ///////////////// Imports // -const AES = @import("crypto/aes.zig"); -const ED25519 = @import("crypto/ed25519.zig"); -const HKDF = @import("crypto/hkdf.zig"); -const HMAC = @import("crypto/hmac.zig"); -const SHA256 = @import("crypto/sha256.zig"); -const SHA512 = @import("crypto/sha512.zig"); -const X25519= @import("crypto/x25519.zig"); -const RANDOM = @import("crypto/random.zig"); +pub const Aes = @import("crypto/aes.zig"); +pub const Ed25519 = @import("crypto/ed25519.zig"); +pub const Hkdf = @import("crypto/hkdf.zig"); +pub const Hmac = @import("crypto/hmac.zig"); +pub const Sha256 = @import("crypto/sha256.zig"); +pub const Sha512 = @import("crypto/sha512.zig"); +pub const X25519= @import("crypto/x25519.zig"); +pub const Random = @import("crypto/random.zig"); ///////////////// Errors @@ -25,25 +25,25 @@ pub const CryptoError = error { // pub const PartialEngine = struct { - aes_cbc256: ? AES.CBC256.Implementation = null, - ed25519: ? ED25519.Implementation = null, - hkdf: ? HKDF.Implementation = null, - hmac: ? HMAC.Implementation = null, - sha256: ? SHA256.Implementation = null, - sha512: ? SHA512.Implementation = null, + aes_cbc256: ? Aes.CBC256.Implementation = null, + ed25519: ? Ed25519.Implementation = null, + hkdf: ? Hkdf.Implementation = null, + hmac: ? Hmac.Implementation = null, + sha256: ? Sha256.Implementation = null, + sha512: ? Sha512.Implementation = null, x25519: ? X25519.Implementation = null, - random: ? RANDOM.Implementation = null, + random: ? Random.Implementation = null, }; pub const Engine = struct { - aes_cbc256: AES.CBC256.Implementation, - ed25519: ED25519.Implementation, - hkdf: HKDF.Implementation, - hmac: HMAC.Implementation, - sha256: SHA256.Implementation, - sha512: SHA512.Implementation, + aes_cbc256: Aes.CBC256.Implementation, + ed25519: Ed25519.Implementation, + hkdf: Hkdf.Implementation, + hmac: Hmac.Implementation, + sha256: Sha256.Implementation, + sha512: Sha512.Implementation, x25519: X25519.Implementation, - random: RANDOM.Implementation, + random: Random.Implementation, }; @@ -56,14 +56,14 @@ pub const Engine = struct { pub fn resolveEngine(comptime provider: PartialEngine) Engine { return .{ - .aes_cbc256 = provider.aes_cbc256 orelse AES.CBC256.defaultImplementation, - .ed25519 = provider.ed25519 orelse ED25519.defaultImplementation, - .hkdf = provider.hkdf orelse HKDF.defaultImplementation, - .hmac = provider.hmac orelse HMAC.defaultImplementation, - .sha256 = provider.sha256 orelse SHA256.defaultImplementation, - .sha512 = provider.sha512 orelse SHA512.defaultImplementation, + .aes_cbc256 = provider.aes_cbc256 orelse Aes.CBC256.defaultImplementation, + .ed25519 = provider.ed25519 orelse Ed25519.defaultImplementation, + .hkdf = provider.hkdf orelse Hkdf.defaultImplementation, + .hmac = provider.hmac orelse Hmac.defaultImplementation, + .sha256 = provider.sha256 orelse Sha256.defaultImplementation, + .sha512 = provider.sha512 orelse Sha512.defaultImplementation, .x25519 = provider.x25519 orelse X25519.defaultImplementation, - .random = provider.random orelse RANDOM.defaultImplementation, + .random = provider.random orelse Random.defaultImplementation, }; } From 856f4f626b9ed5df5dbe81b178960f70545672d3 Mon Sep 17 00:00:00 2001 From: "Gu://em_" Date: Mon, 20 Jul 2026 00:09:23 +0200 Subject: [PATCH 2/6] Changed ed25519 constants names to better align with the stlib implementation and made the generateKeys's function pubkey argument optional to spare a useless memcpy when possible --- src/crypto/ed25519.zig | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/crypto/ed25519.zig b/src/crypto/ed25519.zig index 889f713..ea3a019 100644 --- a/src/crypto/ed25519.zig +++ b/src/crypto/ed25519.zig @@ -5,37 +5,37 @@ const Ed25519 = @import("std").crypto.sign.Ed25519; // Random number generation const rngProvider = @import("random.zig").Implementation; -pub const secret_key_size: comptime_int = Ed25519.SecretKey.encoded_length; -pub const public_key_size: comptime_int = Ed25519.PublicKey.encoded_length; -pub const signature_size : comptime_int = Ed25519.Signature.encoded_length; +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; +pub const seed_length : comptime_int = Ed25519.Signature.encoded_length; pub const Implementation = struct { - generateKeys: *const fn (pubkey_buffer: *[public_key_size]u8, privkey_buffer: *[secret_key_size]u8, rng: rngProvider) CryptoError!void, - sign: *const fn (key: *const [secret_key_size]u8, data: []const u8, signature_out: *const [signature_size]u8) CryptoError!void, - verify: *const fn (key: *const [public_key_size]u8, signature: *const [signature_size]u8, data: []const u8) CryptoError!void, + generateKeys: *const fn (pubkey_buffer: ?*[public_key_length]u8, privkey_buffer: *[secret_key_length]u8, 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_size]u8, privkey_buffer: *[secret_key_size]u8, rng: rngProvider) !void { +pub fn generateKeys(pubkey_buffer: ?*[public_key_length]u8, privkey_buffer: *[secret_key_length]u8, rng: rngProvider) !void { var seed_buffer: [Ed25519.KeyPair.seed_length]u8 = undefined; rng.generate(&seed_buffer); const keypair: Ed25519.KeyPair = Ed25519.KeyPair.generateDeterministic(seed_buffer) catch return CryptoError.FailedKeyGeneration; - - @memcpy(pubkey_buffer[0..public_key_size], &keypair.public_key.bytes); - @memcpy(privkey_buffer[0..secret_key_size], &keypair.secret_key.bytes); + 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); } -pub fn sign(key: *const [secret_key_size]u8, data: []const u8, signature_out: *const [signature_size]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_size]u8, signature: *const [signature_size]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; From 547a515952fe79d5720c2d27dc0f025ec890baaf Mon Sep 17 00:00:00 2001 From: "Gu://em_" Date: Mon, 20 Jul 2026 00:09:47 +0200 Subject: [PATCH 3/6] Implemented X25519 generateKeys and fromEd25519 functions --- src/crypto/x25519.zig | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/src/crypto/x25519.zig b/src/crypto/x25519.zig index 0d756e8..a350fa5 100644 --- a/src/crypto/x25519.zig +++ b/src/crypto/x25519.zig @@ -1,13 +1,39 @@ -//TODO +// Errors +const CryptoError = @import("../crypto.zig").CryptoError; +// Constants and default implementation +const X25519 = @import("std").crypto.dh.X25519; +const Ed25519 = @import("std").crypto.sign.Ed25519; +// Random number generation +const rngProvider = @import("random.zig").Implementation; -const X25519 = @import("std").std.crypto.dh.X25519; +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; 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, + // TODO + // maybe switch to a Keypair system based on the stdlib implementation + // generateKeys: *const fn (keypair: *X25519.KeyPair, rng: rngProvider) CryptoError!void, }; +fn generateKeys (pubkey_buffer: ?*[public_key_length]u8, privkey_buffer: *[secret_key_length]u8, rng: rngProvider) !void { + + var seed_buffer: [seed_length]u8 = undefined; + 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); +} + +fn fromEd25519 (ed25519_keypair: *Ed25519.Keypair, x25519_keypair: *X25519.KeyPair) CryptoError!void { + x25519_keypair.* = X25519.KeyPair.fromEd25519(ed25519_keypair); +} + pub const defaultImplementation: Implementation = .{ - - // One problem, it uses the zig's io module, which is not supported yet as it depends on the target OS - // It may need a custom implementation or some other library + .generateKeys = generateKeys, + .fromEd25519 = fromEd25519, }; From 3209ae87a16089cbee03b3fcb340cedef9be67b9 Mon Sep 17 00:00:00 2001 From: "Gu://em_" Date: Mon, 20 Jul 2026 00:12:48 +0200 Subject: [PATCH 4/6] Began Identity implementation and testing --- src/identity.zig | 63 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/src/identity.zig b/src/identity.zig index dee9100..e467daa 100644 --- a/src/identity.zig +++ b/src/identity.zig @@ -1,7 +1,7 @@ ///////////////// Imports // -const CryptoEngine = @import("crypto.zig").Engine; +const Crypto = @import("crypto.zig"); ///////////////// Constants // @@ -13,25 +13,25 @@ const CryptoEngine = @import("crypto.zig").Engine; // // TODO -pub fn Identity(comptime crypto_engine: CryptoEngine) type { - _ = crypto_engine; +pub fn resolveIdentity(comptime crypto_engine: Crypto.Engine) type { return struct { + const Self = @This(); + //////// Fields // - publicKey: []const u8, - privateKey: []const u8, - signature: []const u8, + privKey: [Crypto.Ed25519.secret_key_length]u8, + signatureKey: [Crypto.X25519.secret_key_size]u8, hash: []const u8, //////// Functions // - pub fn generate() !Identity { - return .{ - // .privateKey = crypto_engine.ed25519.generateKey(...), - // .signature = crypto_engine.x25519. - }; + pub fn generate() !Self { + const result: Self = undefined; + crypto_engine.ed25519.generateKeys(null, &result.signatureKey, crypto_engine.random); + // TODO privKey and signature + return result; } }; } @@ -46,3 +46,44 @@ pub fn Identity(comptime crypto_engine: CryptoEngine) type { const std = @import("std"); const expect = std.testing.expect; +const memeql = std.mem.eql; + +const testPattern: u8 = 0b10101010; +const pubkey_size = Crypto.Ed25519.public_key_length; +const privkey_size = Crypto.Ed25519.secret_key_length; + +// Fills out with alternating 0s and 1s +fn fillPattern(out: []u8) void { + for(out) |*byte| { + byte.* = testPattern; + } +} + +pub fn generateFakeKeys(pubkey_buffer: *[pubkey_size]u8, privkey_buffer: *[privkey_size]u8, rng: Crypto.Random.Implementation) Crypto.CryptoError!void { + _ = rng; + fillPattern(pubkey_buffer); + fillPattern(privkey_buffer); +} + +test "Basic identity generation" { + + const fake_rng: Crypto.Random.Implementation = .{ + .generate = fillPattern, + }; + const fake_ed25519: Crypto.Ed25519.Implementation = .{ + .generateKeys = generateFakeKeys, + }; + const crypto_engine = Crypto.resolveEngine(.{ + .random = fake_rng, + .ed25519 = fake_ed25519, + }); + + const Identity = resolveIdentity(crypto_engine); + const new_id: Identity = try Identity.generate(); + + + try expect(memeql(u8, new_id.privKey, testPattern)); + try expect(memeql(u8, new_id.signatureKey, testPattern)); + // try expect(memeql(u8, new_id.hash, testPattern)); + +} From 69bad53a034bdf1e9ccc9c0f87605cefb494ded4 Mon Sep 17 00:00:00 2001 From: "Gu://em_" Date: Wed, 29 Jul 2026 18:15:54 +0200 Subject: [PATCH 5/6] Refactored Ed25519 to use the stdlib's KeyPair type for better readability, separate generate() and new() identity functions, new update_hash() function for identity and compilation errors fixes --- src/crypto/ed25519.zig | 20 +++++++++++--------- src/crypto/x25519.zig | 15 +++++++++------ src/identity.zig | 37 ++++++++++++++++++++++++++----------- 3 files changed, 46 insertions(+), 26 deletions(-) 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)); From d7139c6ce87a184696a4735ff6b5b0eec34015c6 Mon Sep 17 00:00:00 2001 From: "Gu://em_" Date: Wed, 29 Jul 2026 18:47:40 +0200 Subject: [PATCH 6/6] Refactored the missing X25519 functions to use keypairs, consume seed buffers once they have been used (fill with zeroes), fixed the remaining compilation issues with identity.zig --- src/crypto/ed25519.zig | 2 +- src/crypto/x25519.zig | 14 +++++--------- src/identity.zig | 17 ++++++++++------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/crypto/ed25519.zig b/src/crypto/ed25519.zig index 99f4621..79940ec 100644 --- a/src/crypto/ed25519.zig +++ b/src/crypto/ed25519.zig @@ -25,7 +25,7 @@ pub const Implementation = struct { pub fn generateKeys (destination: *KeyPair, rng: rngProvider) !void { var seed_buffer: [KeyPair.seed_length]u8 = undefined; - defer secureZero(@TypeOf(seed_buffer), seed_buffer); + defer secureZero(u8, &seed_buffer); rng.generate(&seed_buffer); destination.* = KeyPair.generateDeterministic(seed_buffer) catch return CryptoError.FailedKeyGeneration; } diff --git a/src/crypto/x25519.zig b/src/crypto/x25519.zig index b6a7b80..a21bd2d 100644 --- a/src/crypto/x25519.zig +++ b/src/crypto/x25519.zig @@ -3,6 +3,7 @@ const CryptoError = @import("../crypto.zig").CryptoError; // Constants and default implementation const X25519 = @import("std").crypto.dh.X25519; const Ed25519 = @import("std").crypto.sign.Ed25519; +const secureZero = @import("std").crypto.secureZero; // Random number generation const rngProvider = @import("random.zig").Implementation; @@ -15,21 +16,16 @@ 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, + generateKeys: *const fn (destination: *KeyPair, rng: rngProvider) CryptoError!void, fromEd25519: *const fn (ed25519_keypair: *Ed25519.KeyPair, x25519_keypair: *KeyPair) CryptoError!void, - // TODO - // Switch to a Keypair system based on the stdlib implementation - // generateKeys: *const fn (keypair: *X25519.KeyPair, rng: rngProvider) CryptoError!void, }; -fn generateKeys (pubkey_buffer: ?*[public_key_length]u8, privkey_buffer: *[secret_key_length]u8, rng: rngProvider) !void { +fn generateKeys (destination: *KeyPair, rng: rngProvider) !void { var seed_buffer: [seed_length]u8 = undefined; + defer secureZero(u8, &seed_buffer); 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); - @memcpy(privkey_buffer[0..secret_key_length], &keypair.secret_key); + destination.* = X25519.KeyPair.generateDeterministic(seed_buffer) catch return CryptoError.FailedKeyGeneration; } fn fromEd25519 (ed25519_keypair: *Ed25519.KeyPair, x25519_keypair: *KeyPair) CryptoError!void { diff --git a/src/identity.zig b/src/identity.zig index 4c282ea..dc398d6 100644 --- a/src/identity.zig +++ b/src/identity.zig @@ -36,15 +36,15 @@ pub fn resolveIdentity(comptime crypto_engine: Crypto.Engine) type { } 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); + try crypto_engine.ed25519.generateKeys(&self.keys, crypto_engine.random); + try crypto_engine.x25519.fromEd25519(&self.keys, &self.signatureKeys); 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); + crypto_engine.sha256.hash(&self.keys.public_key.bytes, &self.hash); } }; } @@ -88,17 +88,20 @@ test "Basic identity generation" { .sign = undefined, .verify = undefined, }; - const crypto_engine = Crypto.resolveEngine(.{ + const crypto_engine = comptime Crypto.resolveEngine(.{ .random = fake_rng, .ed25519 = fake_ed25519, }); const Identity = resolveIdentity(crypto_engine); - const new_id: Identity = undefined; + var new_id: Identity = undefined; try new_id.generate(); - try expect(memeql(u8, new_id.privKey, testPattern)); - try expect(memeql(u8, new_id.signatureKey, testPattern)); + const expected_secret_key = [_]u8{testPattern} ** new_id.keys.secret_key.bytes.len; + // const expected_signature_key = [_]u8{testPattern} ** new_id.signatureKeys.secret_key.len; + try expect(memeql(u8, &new_id.keys.secret_key.bytes, &expected_secret_key)); + // try expect(memeql(u8, &new_id.signatureKeys.secret_key, &expected_signature_key)); + // try expect(memeql(u8, new_id.hash, testPattern)); }