Refactored the crypto submodules to comply with the engine resolution method

This commit is contained in:
Gu://em_ 2026-07-09 23:42:48 +02:00
parent c292832280
commit 891727d959
9 changed files with 132 additions and 133 deletions

View file

@ -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);
}

View file

@ -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,
};

View file

@ -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,
};

View file

@ -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,
};

View file

@ -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,
};

View file

@ -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,
};

View file

@ -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,
};

View file

@ -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,
};

View file

@ -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