From 891727d9595b0266880eb1372e65c7374c9bb40e Mon Sep 17 00:00:00 2001 From: "Gu://em_" Date: Thu, 9 Jul 2026 23:42:48 +0200 Subject: [PATCH] Refactored the crypto submodules to comply with the engine resolution method --- src/crypto.zig | 12 +++--- src/crypto/aes.zig | 39 +++++++++++--------- src/crypto/ed25519.zig | 83 ++++++++++++++++++++---------------------- src/crypto/hkdf.zig | 37 +++++++++---------- src/crypto/hmac.zig | 26 ++++++------- src/crypto/random.zig | 16 ++++---- src/crypto/sha256.zig | 21 +++++------ src/crypto/sha512.zig | 23 ++++++------ src/crypto/x25519.zig | 8 ++-- 9 files changed, 132 insertions(+), 133 deletions(-) diff --git a/src/crypto.zig b/src/crypto.zig index e9813cd..1a8c8d0 100644 --- a/src/crypto.zig +++ b/src/crypto.zig @@ -50,7 +50,7 @@ pub fn resolveEngine(comptime provider: PartialEngine) Engine { return .{ .aes_cbc256 = provider.aes_cbc256 orelse AES.CBC256_DefaultImplementation, - .ed25519 = provider.ed25519 orelse ED25519.DefaultImplementation(randomImpl), + .ed25519 = provider.ed25519 orelse ED25519.defaultImplementation(randomImpl), .hkdf = provider.hkdf orelse HKDF.DefaultImplementation, .hmac = provider.hmac orelse HMAC.DefaultImplementation, .sha256 = provider.sha256 orelse SHA256.DefaultImplementation, @@ -69,9 +69,9 @@ const std = @import("std"); test "AES encryption defaults" { const crypto = resolveEngine(.{}); - - var data = [_]u8{ 1, 2, 3, 4 }; - const key = [_]u8{ 1, 2, 3, 4 }; - const iv = [_]u8{ 1, 2, 3, 4 }; - crypto.aes_cbc256.encrypt(&data, &key, &iv); + + var data: []u8 = undefined; + const key: [32]u8 = undefined; + const iv: [16]u8 = undefined; + crypto.aes_cbc256.encrypt(&key, &iv, &data); } diff --git a/src/crypto/aes.zig b/src/crypto/aes.zig index aceb2c9..e948313 100644 --- a/src/crypto/aes.zig +++ b/src/crypto/aes.zig @@ -1,27 +1,30 @@ +pub const block_size = 16; +pub const key_size = 32; + pub const CBC256_Implementation = struct { - pub const BLOCK_SIZE = 16; - pub const KEY_SIZE = 32; - // NOTE: data should be padded to make its length be a multiple of BLOCK_SIZE - encypt: *const fn (key: *const [KEY_SIZE]u8, iv: *const [BLOCK_SIZE]u8, data: *const []u8) void, - decrypt: *const fn (key: *const [KEY_SIZE]u8, iv: *const [BLOCK_SIZE]u8, data: *const []u8) void, + encrypt: *const fn (key: *const [key_size]u8, iv: *const [block_size]u8, data: *const []u8) void, + decrypt: *const fn (key: *const [key_size]u8, iv: *const [block_size]u8, data: *const []u8) void, }; // TODO -pub const CBC256_DefaultImplementation = struct { - // Zig stdlib seems to provide no support for AES CBC265 - // It may need some custom implementation or another library +// Zig stdlib seems to provide no support for AES CBC265 +// It may need some custom implementation or another library - pub fn encrypt(key: *const [32]u8, iv: *const [16]u8, data: *const []u8) !void { - _ = key; - _ = iv; - _ = data; - } - pub fn decrypt(key: *const [32]u8, iv: *const [16]u8, data: *const []u8) !void { - _ = key; - _ = iv; - _ = data; - } +fn encrypt(key: *const [key_size]u8, iv: *const [block_size]u8, data: *const []u8) void { + _ = key; + _ = iv; + _ = data; +} +fn decrypt(key: *const [key_size]u8, iv: *const [block_size]u8, data: *const []u8) void { + _ = key; + _ = iv; + _ = data; +} + +pub const CBC256_DefaultImplementation: CBC256_Implementation = .{ + .decrypt = decrypt, + .encrypt = encrypt, }; diff --git a/src/crypto/ed25519.zig b/src/crypto/ed25519.zig index 2ffe762..fffc743 100644 --- a/src/crypto/ed25519.zig +++ b/src/crypto/ed25519.zig @@ -1,51 +1,48 @@ -pub const Implementation = struct { - - secret_key_size: comptime_int, - public_key_size: comptime_int, - signature_size: comptime_int, - - generateKeys: *const fn (pubkey_buffer: *[Implementation.public_key_size]u8, privkey_buffer: *[Implementation.secret_key_size]u8) void, - sign: *const fn (key: *const [Implementation.private_key_size]u8, data: []const u8, signature_out: *const [Implementation.signature_size]u8) void, - verify: *const fn (key: *const [Implementation.public_key_size]u8, signature: *const [Implementation.signature_size]u8, data: []const u8) void, -}; - +// Constants and default implementation +const Ed25519 = @import("std").crypto.sign.Ed25519; // Random number generation const rngProvider = @import("random.zig").Implementation; -pub fn defaultImplementation(comptime random: rngProvider) type { +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; - return struct { - - const Ed25519 = @import("std").crypto.sign.Ed25519; +pub const Implementation = struct { - pub const secret_key_size = Ed25519.SecretKey.encoded_length; - pub const public_key_size = Ed25519.PublicKey.encoded_length; - pub const signature_size = Ed25519.Signature.encoded_length; + generateKeys: *const fn (pubkey_buffer: *[public_key_size]u8, privkey_buffer: *[secret_key_size]u8, rng: rngProvider) void, + sign: *const fn (key: *const [secret_key_size]u8, data: []const u8, signature_out: *const [signature_size]u8) void, + verify: *const fn (key: *const [public_key_size]u8, signature: *const [signature_size]u8, data: []const u8) void, +}; - pub fn generateKeys(pubkey_buffer: *[Ed25519.SecretKey.encoded_length]u8, privkey_buffer: *[Ed25519.SecretKey.encoded_length]u8) !void { - - const seed_buffer: [Ed25519.KeyPair.seed_length]u8 = undefined; - random.generate(&seed_buffer); - const keypair: Ed25519.KeyPair = try Ed25519.KeyPair.generateDeterministic(seed_buffer); - - - @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_size]u8, data: []const u8, signature_out: *const [signature_size]u8) !void { - _ = key; - _ = data; - _ = signature_out; - return error.NotImplemented; - } - - pub fn verify(key: *const [public_key_size]u8, signature: *const [signature_size]u8, data: []const u8) !void { - const sig = Ed25519.Signature.fromBytes(signature); - const pubkey = Ed25519.PublicKey.fromBytes(key); - - return sig.verify(sig, data, pubkey); - } - }; +pub fn generateKeys(pubkey_buffer: *[public_key_size]u8, privkey_buffer: *[secret_key_size]u8, rng: rngProvider) !void { + + const seed_buffer: [Ed25519.KeyPair.seed_length]u8 = undefined; + rng.generate(&seed_buffer); + const keypair: Ed25519.KeyPair = try Ed25519.KeyPair.generateDeterministic(seed_buffer); + + + @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_size]u8, data: []const u8, signature_out: *const [signature_size]u8) !void { + _ = key; + _ = data; + _ = signature_out; + return error.NotImplemented; +} + +pub fn verify(key: *const [public_key_size]u8, signature: *const [signature_size]u8, data: []const u8) !void { + const sig = Ed25519.Signature.fromBytes(signature); + const pubkey = Ed25519.PublicKey.fromBytes(key); + + return sig.verify(sig, data, pubkey); +} + + +pub const defaultImplementation: Implementation = .{ + .generateKeys = generateKeys, + .sign = sign, + .verify = verify, +}; diff --git a/src/crypto/hkdf.zig b/src/crypto/hkdf.zig index 05a93a8..9565de0 100644 --- a/src/crypto/hkdf.zig +++ b/src/crypto/hkdf.zig @@ -1,29 +1,28 @@ +const Sha256 = @import("std").crypto.hash.sha2.Sha256; +const Hmac = @import("std").crypto.auth.hmac.Hmac(Sha256); +const Hkdf = @import("std").crypto.kdf.hkdf.Hkdf(Hmac); + +pub const prk_length: comptime_int = Hkdf.prk_length; + + pub const Implementation = struct { - prk_length: comptime_int, - - expand: *const fn (out: []u8, ctx: []const u8, prk: *[Implementation.prk_length]u8) void, - extract: *const fn (out: *[Implementation.prk_length]u8, salt: []const u8, ikm: []const u8) void, + expand: *const fn (out: []u8, ctx: []const u8, prk: *[prk_length]u8) void, + extract: *const fn (out: *[prk_length]u8, salt: []const u8, ikm: []const u8) void, }; -pub const defaultImplementation = struct { - - const Sha256 = @import("std").crypto.hash.sha2.Sha256; - const HashImpl = Sha256; - const HmacImpl = @import("std").crypto.auth.hmac.Hmac(HashImpl); +fn expand(out: []u8, ctx: []const u8, prk: *[prk_length]u8) void { + Hkdf.expand(out, ctx, prk); +} - const Hkdf = @import("std").crypto.kdf.hkdf.Hkdf(HmacImpl); +fn extract(out: *[prk_length]u8, salt: []const u8, ikm: []const u8) void { + out *= Hkdf.extract(salt, ikm); +} - pub const prk_length = Hkdf.prk_length; - - pub fn expand(out: []u8, ctx: []const u8, prk: *[prk_length]u8) void { - Hkdf.expand(out, ctx, prk); - } - - pub fn extract(out: *[prk_length]u8, salt: []const u8, ikm: []const u8) void { - out *= Hkdf.extract(salt, ikm); - } +pub const defaultImplementation: Implementation = .{ + .expand = expand, + .extract = extract, }; diff --git a/src/crypto/hmac.zig b/src/crypto/hmac.zig index 131bb20..96d19b1 100644 --- a/src/crypto/hmac.zig +++ b/src/crypto/hmac.zig @@ -1,20 +1,18 @@ +const Sha256 = @import("std").crypto.hash.sha2.Sha256; +const Hmac = @import("std").crypto.auth.hmac.Hmac(Sha256); + +pub const mac_length: comptime_int = Hmac.mac_length; + + pub const Implementation = struct { - mac_length: comptime_int, - - create: *const fn (out: *[Implementation.mac_length]u8, msg: []const u8, key: []const u8) void, + create: *const fn (out: *[mac_length]u8, msg: []const u8, key: []const u8) void, }; -pub const defaultImplementation = struct { - - const Sha256 = @import("std").crypto.hash.sha2.Sha256; +fn create(out: *[mac_length]u8, msg: []const u8, key: []const u8) void { + Hmac.create(out, msg, key); +} - const HashImpl = Sha256; - const Hmac = @import("std").crypto.auth.hmac.Hmac(Sha256); - - pub const mac_length = Hmac.mac_length; - - pub fn create(out: *[mac_length]u8, msg: []const u8, key: []const u8) void { - Hmac.create(out, msg, key); - } +pub const defaultImplementation: Implementation = .{ + .create = create, }; diff --git a/src/crypto/random.zig b/src/crypto/random.zig index b4d99d9..48be61c 100644 --- a/src/crypto/random.zig +++ b/src/crypto/random.zig @@ -2,14 +2,14 @@ pub const Implementation = struct { generate: *const fn (out: []u8) void, }; -// TODO -pub const defaultImplementation = struct { - - pub fn generate(out: []u8) void { - // WARNING This is not secure at all, use only for testing purposes - for(out) |*byte| { - byte *= undefined; - } +fn generate(out: []u8) void { + // WARNING This is not secure at all, use only for testing purposes + for(out) |*byte| { + byte *= undefined; } +} + +pub const defaultImplementation: Implementation = .{ + .generate = generate, }; diff --git a/src/crypto/sha256.zig b/src/crypto/sha256.zig index 0d913a1..647570c 100644 --- a/src/crypto/sha256.zig +++ b/src/crypto/sha256.zig @@ -1,17 +1,16 @@ +const Sha256 = @import("std").crypto.hash.sha2.Sha256; + +pub const hash_len: comptime_int = Sha256.digest_length; + pub const Implementation = struct { - hash_length: comptime_int, - - hash: *const fn (buffer: []const u8, out: *[Implementation.hash_length]u8) void, + hash: *const fn (buffer: []const u8, out: *[hash_len]u8) void, }; -pub const defaultImplementation = struct { - - const Sha256 = @import("std").crypto.hash.sha2.Sha256; +pub fn hash(buffer: []const u8, out: *[hash_len]u8) !void { + Sha256.hash(buffer, out, .{}); +} - pub const hash_len = Sha256.digest_length; - - pub fn hash(buffer: []const u8, out: *[hash_len]u8) !void { - Sha256.hash(buffer, out, .{}); - } +pub const defaultImplementation: Implementation = .{ + .hash = hash, }; diff --git a/src/crypto/sha512.zig b/src/crypto/sha512.zig index a69a88d..75e0aba 100644 --- a/src/crypto/sha512.zig +++ b/src/crypto/sha512.zig @@ -1,18 +1,19 @@ +const Sha512 = @import("std").crypto.sha2.Sha512; + +pub const hash_len: comptime_int = Sha512.digest_length; + pub const Implementation = struct { hash: *const fn (buffer: []const u8, out: []u8) void, }; -pub const defaultImplementation = struct { - - const Sha512 = @import("std").crypto.sha2.Sha512; - - const HASH_LEN = 64; // In bytes - - pub fn hash(buffer: []const u8, out: []u8) !void { - if (out.len < HASH_LEN) { - return error.BufferTooShort; - } - Sha512.hash(buffer, out, .{}); +fn hash(buffer: []const u8, out: []u8) !void { + if (out.len < hash_len) { + return error.BufferTooShort; } + Sha512.hash(buffer, out, .{}); +} + +pub const defaultImplementation: Implementation = .{ + .hash = hash, }; diff --git a/src/crypto/x25519.zig b/src/crypto/x25519.zig index f3f6607..0d756e8 100644 --- a/src/crypto/x25519.zig +++ b/src/crypto/x25519.zig @@ -1,10 +1,12 @@ +//TODO + +const X25519 = @import("std").std.crypto.dh.X25519; + pub const Implementation = struct { }; -pub const defaultImplementation = struct { - - const X25519 = @import("std").std.crypto.dh.X25519; +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