Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
543d213
Add randomBytes function for secure random generation
zendrx Jul 20, 2026
894bc0a
Implement randomBytes function in buzz_crypto.zig
zendrx Jul 20, 2026
ddcc330
Replace random bytes generation with Io random
zendrx Jul 20, 2026
f4115ef
Update randomBytes function signature
zendrx Jul 20, 2026
e0702fc
Fix typo in randomByes function name to randomBytes
zendrx Jul 20, 2026
fd1ea18
Fix type casting for length in randomBytes function
zendrx Jul 20, 2026
5ff6610
Fix allocation error in randomBytes function
zendrx Jul 20, 2026
c74c726
Add error handling for buffer allocation
zendrx Jul 20, 2026
48de213
Change 'fn' to 'fun' in randomBytes declaration
zendrx Jul 20, 2026
e95b76f
Add cryptographic functions for HMAC and Argon2id
zendrx Jul 20, 2026
f336e6a
Add HMAC-SHA256 and Argon2id functions
zendrx Jul 20, 2026
128f47d
Simplify argon2id function parameters
zendrx Jul 20, 2026
498ce2a
Refactor cryptographic functions for consistency
zendrx Jul 20, 2026
0f8cd16
Refactor HMAC and Argon2 functions in crypto.buzz
zendrx Jul 20, 2026
1607555
Fix argon2 hash call to use io from context
zendrx Jul 20, 2026
2d252ce
Fix argon2 function to use correct context allocator
zendrx Jul 20, 2026
91dd935
Update argon2 function documentation
zendrx Jul 20, 2026
f48c907
Fix hash buffer reference and push true for validation
zendrx Jul 20, 2026
e64bd89
Fix hash variable assignment in buzz_crypto.zig
zendrx Jul 20, 2026
9bc2043
Fix variable name for Argon2 hash result
zendrx Jul 20, 2026
85d934a
Change wasm_native flag for crypto library to false
zendrx Jul 20, 2026
c77b726
Update buzz_crypto.zig
zendrx Jul 20, 2026
fa54186
fixed type redundant
zendrx Jul 21, 2026
c95432b
Change len from const to var in randomBytes function
zendrx Jul 21, 2026
5e99af2
Change variable declaration from var to const
zendrx Jul 21, 2026
3d306d3
Change len to var for reassignment in randomBytes
zendrx Jul 21, 2026
1c80129
Refactor randomBytes function to use const for len
zendrx Jul 22, 2026
d19f0e0
Merge branch 'buzz-language:main' into main
zendrx Jul 22, 2026
38945d8
Add randomBytes tests
zendrx Jul 23, 2026
afb2497
Refactor crypto test cases to use updated imports
zendrx Jul 23, 2026
888f5be
Refactor hash test cases in crypto.buzz
zendrx Jul 23, 2026
c186745
Update assertions to use 'message' parameter
zendrx Jul 23, 2026
18c4e54
Handle errors in argon2 hashing and verification tests
zendrx Jul 23, 2026
3200fe6
Refactor assertions for clarity in crypto tests
zendrx Jul 23, 2026
f4e14ff
Update error handling in argon2 tests
zendrx Jul 23, 2026
898a6b4
Enhance verifyArgon2 with InvalidArgumentError
zendrx Jul 23, 2026
a3f530b
Add AuthenticationFailed error object
zendrx Jul 23, 2026
e6fb53f
Update error handling for Argon2 functions
zendrx Jul 23, 2026
3692515
Delete argon2 invalid hash test case
zendrx Jul 23, 2026
8361700
Merge branch 'buzz-language:main' into main
zendrx Jul 28, 2026
ed0f02e
Merge branch 'buzz-language:main' into main
zendrx Jul 30, 2026
d5b8686
Refactor Argon2 parameters for password hashing
zendrx Aug 2, 2026
969949e
Merge branch 'buzz-language:main' into main
zendrx Aug 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions src/lib/buzz_crypto.zig
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,67 @@ pub export fn hash(ctx: *api.NativeCtx) callconv(.c) c_int {
return 1;
}

pub export fn randomBytes(ctx: *api.NativeCtx) callconv(.c) c_int {
const len_val = ctx.vm.bz_peek(0);
const len = @as(usize, @intCast(len_val.integer()));
const buffer = api.VM.allocator.alloc(u8, len) catch {
ctx.vm.pushError("errors.OutOfMemoryError", null);
return -1;
};
defer api.VM.allocator.free(buffer);
std.Io.random(ctx.getIo(), buffer);
ctx.vm.bz_push(
api.VM.bz_stringToValue(ctx.vm, buffer.ptr, buffer.len),
);
return 1;
}

pub export fn argon2(ctx: *api.NativeCtx) callconv(.c) c_int {
var pass_len: usize = 0;
const pass_ptr = ctx.vm.bz_peek(0).bz_valueToString(&pass_len);
const password = pass_ptr.?[0..pass_len];
var hash_buf: [256]u8 = undefined;
const io = ctx.getIo();
const params = std.crypto.pwhash.argon2.Params.owasp_2id;
const hash_r = std.crypto.pwhash.argon2.strHash(password, .{
.allocator = api.VM.allocator,
.params = params,
}, &hash_buf, io) catch {
ctx.vm.pushError("errors.AuthenticationFailed", "argon2 failed");
return -1;
};
ctx.vm.bz_push(
api.VM.bz_stringToValue(ctx.vm, hash_r.ptr, hash_r.len),
);

return 1;
}

pub export fn verifyArgon2(ctx: *api.NativeCtx) callconv(.c) c_int {
var pass_len: usize = 0;
const pass_ptr = ctx.vm.bz_peek(1).bz_valueToString(&pass_len);
const password = pass_ptr.?[0..pass_len];

var hash_len: usize = 0;
const hash_ptr = ctx.vm.bz_peek(0).bz_valueToString(&hash_len);
const encoded_hash = hash_ptr.?[0..hash_len];

std.crypto.pwhash.argon2.strVerify(encoded_hash, password, .{ .allocator = api.VM.allocator }, ctx.getIo()) catch {
ctx.vm.pushError("errors.AuthenticationFailed", "argon2 verification failed");
return -1;
};

ctx.vm.bz_push(.True);

return 1;
}

pub const library = api.BuzzApi(
"crypto",
&.{
&.{ "hash", hash },
&.{ "randomBytes", randomBytes },
&.{ "argon2", argon2 },
&.{ "verifyArgon2", verifyArgon2 },
},
){};
19 changes: 19 additions & 0 deletions src/lib/crypto.buzz
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
namespace crypto;

import "buzz:errors";

/// Hash algorithms
export enum HashAlgorithm {
Md5,
Expand All @@ -22,3 +24,20 @@ export enum HashAlgorithm {
/// @param data Data to hash
/// @return Hash of data has hex string
export extern fun hash(algo: HashAlgorithm, data: str) > str;

/// Generate Cryptographically secure randombytes
/// @param len Number of random bytes to generate
/// @return randombytes as string
export extern fun randomBytes(len: int) > str;


/// Hash a password using Argon2id
/// @param password The password to hash
/// @return The encoded hash string
export extern fun argon2(password: str) > str !> errors\AuthenticationFailed;

/// Verify a password against an Argon2id hash
/// @param password The password to verify
/// @param hash The encoded hash string from argon2id()
/// @return true if the password matches the hash
export extern fun verifyArgon2(password: str, hash: str) > bool !> errors\AuthenticationFailed;
5 changes: 5 additions & 0 deletions src/lib/errors.buzz
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,8 @@ export object UnderflowError {
export object UnexpectedError {
message: str = "UnexpectedError",
}

/// Error raised when an authentication process failed
export object AuthenticationFailed {
message: str = "AuthenticationFailed",
}
2 changes: 1 addition & 1 deletion src/lib/static_libraries.zig
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub const Library = struct {
/// Libraries bundled with the compiler and runtime.
pub const all = [_]Library{
.{ .header = static_headers.buffer, .zig_path = "buzz_buffer.zig", .wasm_native = true },
.{ .header = static_headers.crypto, .zig_path = "buzz_crypto.zig", .wasm_native = true },
.{ .header = static_headers.crypto, .zig_path = "buzz_crypto.zig", .wasm_native = false },
.{ .header = static_headers.debug, .zig_path = "buzz_debug.zig", .wasm_native = true },
.{ .header = static_headers.errors, .zig_path = null, .wasm_native = false },
.{ .header = static_headers.ffi, .zig_path = "buzz_ffi.zig", .wasm_native = false },
Expand Down
63 changes: 63 additions & 0 deletions tests/behavior/crypto.buzz
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,66 @@ test "hash" {
message: "sha3-256",
);
}

test "randomBytes returns correct length" {
final len = 16;
final bytes = randomBytes(len);
std\assert(
bytes.len() == len,
message: "randomBytes should return a string of the requested length"
);
}

test "randomBytes returns different values" {
final b1 = randomBytes(8);
final b2 = randomBytes(8);
std\assert(
b1 != b2,
message: "randomBytes should return different values"
);
}

test "argon2 hashes and verifies" {
final password = "my-secure-password";
final hash = argon2(password) catch from {
std\assert(
false,
message: "argon2 failed"
);
return;
};
final valid = verifyArgon2(password, hash) catch from {
std\assert(
false,
message: "verifyArgon2 failed"
);
return;
};
std\assert(
valid,
message: "argon2 verification should succeed for correct password"
);
}

test "argon2 fails for wrong password" {
final password = "my-secure-password";
final wrong = "wrong-password";
final hash = argon2(password) catch from {
std\assert(
false,
message: "argon2 failed"
);
return;
};
final valid = verifyArgon2(wrong, hash) catch from {
std\assert(
false,
message: "verifyArgon2 failed"
);
return;
};
std\assert(
!valid,
message: "argon2 verification should fail for wrong password"
);
}