diff --git a/src/crypto.zig b/src/crypto.zig index 5f6c7ad..921b0d0 100644 --- a/src/crypto.zig +++ b/src/crypto.zig @@ -1,14 +1,14 @@ ///////////////// Imports // -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"); +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"); ///////////////// 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, }; } diff --git a/src/crypto/ed25519.zig b/src/crypto/ed25519.zig index 79940ec..889f713 100644 --- a/src/crypto/ed25519.zig +++ b/src/crypto/ed25519.zig @@ -2,42 +2,40 @@ 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; -pub const seed_length : comptime_int = Ed25519.Signature.encoded_length; +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 Implementation = struct { - 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, + 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, }; -pub fn generateKeys (destination: *KeyPair, rng: rngProvider) !void { +pub fn generateKeys(pubkey_buffer: *[public_key_size]u8, privkey_buffer: *[secret_key_size]u8, rng: rngProvider) !void { - var seed_buffer: [KeyPair.seed_length]u8 = undefined; - defer secureZero(u8, &seed_buffer); + var seed_buffer: [Ed25519.KeyPair.seed_length]u8 = undefined; rng.generate(&seed_buffer); - destination.* = KeyPair.generateDeterministic(seed_buffer) catch return CryptoError.FailedKeyGeneration; + 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); } -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_size]u8, data: []const u8, signature_out: *const [signature_size]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_size]u8, signature: *const [signature_size]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 a21bd2d..0d756e8 100644 --- a/src/crypto/x25519.zig +++ b/src/crypto/x25519.zig @@ -1,38 +1,13 @@ -// 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; -const secureZero = @import("std").crypto.secureZero; -// Random number generation -const rngProvider = @import("random.zig").Implementation; +//TODO -// 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; +const X25519 = @import("std").std.crypto.dh.X25519; pub const Implementation = struct { - generateKeys: *const fn (destination: *KeyPair, rng: rngProvider) CryptoError!void, - fromEd25519: *const fn (ed25519_keypair: *Ed25519.KeyPair, x25519_keypair: *KeyPair) CryptoError!void, }; -fn generateKeys (destination: *KeyPair, rng: rngProvider) !void { - - var seed_buffer: [seed_length]u8 = undefined; - defer secureZero(u8, &seed_buffer); - rng.generate(&seed_buffer); - destination.* = X25519.KeyPair.generateDeterministic(seed_buffer) catch return CryptoError.FailedKeyGeneration; -} - -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 = .{ - .generateKeys = generateKeys, - .fromEd25519 = fromEd25519, + + // 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 }; diff --git a/src/identity.zig b/src/identity.zig index dc398d6..dee9100 100644 --- a/src/identity.zig +++ b/src/identity.zig @@ -1,7 +1,7 @@ ///////////////// Imports // -const Crypto = @import("crypto.zig"); +const CryptoEngine = @import("crypto.zig").Engine; ///////////////// Constants // @@ -13,38 +13,25 @@ const Crypto = @import("crypto.zig"); // // TODO -pub fn resolveIdentity(comptime crypto_engine: Crypto.Engine) type { +pub fn Identity(comptime crypto_engine: CryptoEngine) type { + _ = crypto_engine; return struct { - const Self = @This(); - //////// Fields // - keys: Crypto.Ed25519.KeyPair, - signatureKeys: Crypto.X25519.KeyPair, - hash: [Crypto.Sha256.hash_len]u8, + publicKey: []const u8, + privateKey: []const u8, + signature: []const u8, + hash: []const u8, //////// Functions // - pub fn new() !Self { - const result: Self = undefined; - 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 { - 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.bytes, &self.hash); + pub fn generate() !Identity { + return .{ + // .privateKey = crypto_engine.ed25519.generateKey(...), + // .signature = crypto_engine.x25519. + }; } }; } @@ -59,49 +46,3 @@ pub fn resolveIdentity(comptime crypto_engine: Crypto.Engine) 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(destination: *Crypto.Ed25519.KeyPair, rng: Crypto.Random.Implementation) Crypto.CryptoError!void { - _ = rng; - fillPattern(&destination.public_key.bytes); - fillPattern(&destination.secret_key.bytes); -} - -test "Basic identity generation" { - - const fake_rng: Crypto.Random.Implementation = .{ - .generate = fillPattern, - }; - const fake_ed25519: Crypto.Ed25519.Implementation = .{ - .generateKeys = generateFakeKeys, - .sign = undefined, - .verify = undefined, - }; - const crypto_engine = comptime Crypto.resolveEngine(.{ - .random = fake_rng, - .ed25519 = fake_ed25519, - }); - - const Identity = resolveIdentity(crypto_engine); - var new_id: Identity = undefined; - try new_id.generate(); - - 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)); - -}