further benchmarking stuff

This commit is contained in:
Zoe
2025-11-28 14:53:06 -06:00
parent e16383e9b9
commit d0f4936b84
25 changed files with 441 additions and 739 deletions

View File

@@ -2,16 +2,16 @@ const std = @import("std");
const Allocator = std.mem.Allocator;
var argon2_params = std.crypto.pwhash.argon2.Params{
.t = 4, // time cost
.m = 256, // memory cost (in KiB)
.p = 1, // parallelism (this doesnt do anything because we are targeting wasm, and we do multithreading differently anyways)
.t = 3, // time cost
.m = 8192, // memory cost (in KiB)
.p = 1, // parallelism
};
const dk_len: usize = 32; // 16 or 32 byte key
pub fn hash(allocator: Allocator, challenge: []const u8, nonce: []const u8) ![]u8 {
const derived = try allocator.alloc(u8, dk_len);
try std.crypto.pwhash.argon2.kdf(allocator, derived, nonce, challenge, argon2_params, .argon2id);
try std.crypto.pwhash.argon2.kdf(allocator, derived, nonce, challenge, argon2_params, .argon2d);
return derived;
}

View File

@@ -77,18 +77,12 @@ pub const Challenge = struct {
const salt_str = challenge;
const salt_bytes_len = try std.base64.standard.Decoder.calcSizeForSlice(salt_str);
std.log.info("salt_bytes_len: {d}\n", .{salt_bytes_len});
const salt_bytes = try allocator.alloc(u8, salt_bytes_len);
defer allocator.free(salt_bytes);
try std.base64.standard.Decoder.decode(salt_bytes, salt_str);
std.log.info("decoded salt: {any}\n", .{salt_bytes});
const usize_salt_bytes: []align(1) usize = std.mem.bytesAsSlice(usize, salt_bytes);
// TODO: the bytes are being read in as little endian, but need to be read in as big endian
std.log.info("usize_salt_bytes: {any}\n", .{usize_salt_bytes});
try salt.ensureCapacity(usize_salt_bytes.len);
@memcpy(salt.limbs[0..usize_salt_bytes.len], usize_salt_bytes);
salt.setLen(usize_salt_bytes.len);
@@ -118,22 +112,16 @@ pub const Challenge = struct {
pub fn solve(self: *Self, allocator: Allocator) ![]u8 {
for (0..self.difficulty) |_| {
std.log.info("Solving challenge with difficulty {d}\n", .{self.difficulty});
for (0..1277) |_| {
try square_mod(&self.salt);
}
try self.salt.bitXor(&self.salt, &managed_one.?);
}
std.log.info("solved challenge: {any}\n", .{self});
return try self.encode(allocator);
}
pub fn verify(self: *Self, allocator: Allocator, solution: *Challenge) !bool {
std.log.info("{d}", .{self.difficulty});
std.log.info("{any} vs {any}\n", .{ self, solution });
if (managed_one == null) {
managed_one = try Int.init(allocator);
try managed_one.?.set(1);
@@ -145,8 +133,6 @@ pub const Challenge = struct {
try square_mod(&solution.salt);
}
std.log.info("{any} vs {any}\n", .{ self, solution });
// I'm like 99.999% sure this can NEVER happen, but its how the solution that I translated from did it so that's
// how I will do it
if (self.salt.eql(solution.salt)) {

View File

@@ -54,9 +54,6 @@ export fn free(ptr: ?*anyopaque, byte_count: usize) void {
///
/// If a target is not needed for the strategy, target_ptr and target_len should be 0.
export fn solve(algorithm: algorithms.Algorithm, strategy: algorithms.Strategy, salt_ptr: [*]u8, salt_len: usize, difficulty: usize, target_ptr: [*]u8, target_len: usize) isize {
std.log.info("Solve called with difficulty {d}\n", .{difficulty});
std.log.info("Using algorithm {s} and strategy {s}\n", .{ @tagName(algorithm), @tagName(strategy) });
switch (algorithm) {
algorithms.Algorithm.sha256 => return solve_argon2_or_sha256(salt_ptr, salt_len, difficulty, algorithm, strategy, target_ptr, target_len),
algorithms.Algorithm.argon2 => return solve_argon2_or_sha256(salt_ptr, salt_len, difficulty, algorithm, strategy, target_ptr, target_len),
@@ -95,10 +92,8 @@ fn solve_argon2_or_sha256(salt_ptr: [*]u8, salt_len: usize, difficulty: usize, a
return -1;
}
// const max_nonce_iterations: u64 = 1_000_000_000;
const max_nonce_iterations: u64 = 100_000;
std.log.info("Solve called with salt {s}\n", .{salt_slice});
const max_nonce_iterations: u64 = 1_000_000_000;
// const max_nonce_iterations: u64 = 100_000;
// 64 + 9 digits for nonce since the max nonce is 999_999_999 (not 1 billion since nonce < max_nonce_iterations)
var input_buffer: []u8 = allocator.alloc(u8, salt_len + 9) catch {
@@ -131,22 +126,16 @@ fn solve_argon2_or_sha256(salt_ptr: [*]u8, salt_len: usize, difficulty: usize, a
return -1;
};
} else {
input = input_buffer[0 .. salt_len + nonce_str.len];
}
const hash_hex_slice = algorithms.SHA256.hash(allocator, input) catch {
std.log.err("Error hashing key", .{});
return -1;
};
if (algorithm == .argon2) {
allocator.free(input);
input = algorithms.SHA256.hash(allocator, input_buffer[0 .. salt_len + nonce_str.len]) catch {
std.log.err("Error hashing salt", .{});
return -1;
};
}
switch (strategy) {
.leading_zeros => {
_ = hex_encoder.encode(hash_hex_slice);
allocator.free(hash_hex_slice);
_ = hex_encoder.encode(input);
allocator.free(input);
if (hex_encoder.countZeroes(difficulty)) {
// Found a solution!
if (__cmpxchg_solution(-1, nonce) == -1) {
@@ -159,8 +148,8 @@ fn solve_argon2_or_sha256(salt_ptr: [*]u8, salt_len: usize, difficulty: usize, a
}
},
.target_number => {
const hex = hex_encoder.encode(hash_hex_slice);
allocator.free(hash_hex_slice);
const hex = hex_encoder.encode(input);
allocator.free(input);
if (std.mem.eql(u8, hex, target_slice.?)) {
// Found a solution!
if (__cmpxchg_solution(-1, nonce) == -1) {
@@ -191,22 +180,17 @@ fn solve_kctf(value_ptr: [*]u8, value_len: usize, difficulty: usize) isize {
const challenge_slice = value_ptr[0..value_len];
std.log.info("Solve called with challenge {s}\n", .{challenge_slice});
const challenge = algorithms.kCTF.Challenge.from_string(allocator, challenge_slice, difficulty) catch |err| {
std.log.info("Error decoding challenge: {s}\n", .{@errorName(err)});
return -1;
};
defer challenge.destroy(allocator);
std.log.info("decoded challenge {any}\n", .{challenge});
const solution = challenge.solve(allocator) catch |err| {
std.log.info("Error solving challenge: {s}\n", .{@errorName(err)});
return -1;
};
std.log.info("Solution: {s}\n", .{solution});
const output_ptr = allocator.alloc(u8, solution.len + 4) catch return 0;
var output_slice = output_ptr[0 .. solution.len + 2];

View File

@@ -74,24 +74,22 @@ fn validate_argon2_or_sha256(challenge_ptr: [*]u8, challenge_len: usize, nonce:
var input: []u8 = undefined;
if (algorithm == .argon2) {
input = algorithms.Argon2.hash(allocator, input_slice[0..challenge_len], input_slice[challenge_len .. challenge_len + nonce_slice.len]) catch return false;
defer allocator.free(input);
} else {
input = input_slice[0 .. challenge_len + nonce_slice.len];
input = algorithms.SHA256.hash(allocator, input_slice[0 .. challenge_len + nonce_slice.len]) catch return false;
}
defer allocator.free(input);
var hex_encoder = utils.HexEncoder{};
const hash_hex_slice = algorithms.SHA256.hash(allocator, input) catch return false;
defer allocator.free(hash_hex_slice);
switch (strategy) {
.leading_zeros => {
_ = hex_encoder.encode(hash_hex_slice);
_ = hex_encoder.encode(input);
if (hex_encoder.countZeroes(difficulty)) {
return true;
}
},
.target_number => {
if (std.mem.eql(u8, hex_encoder.encode(hash_hex_slice), target_slice.?)) {
if (std.mem.eql(u8, hex_encoder.encode(input), target_slice.?)) {
return true;
}
},
@@ -105,18 +103,13 @@ fn validate_kctf(challenge_ptr: [*]u8, challenge_len: usize, solution_ptr: [*]u8
const challenge_buf = challenge_ptr[0..challenge_len];
const solution_buf = solution_ptr[0..solution_len];
std.log.info("Validate called with challenge {s} and solution {s}\n", .{ challenge_buf, solution_buf });
const challenge = algorithms.kCTF.Challenge.from_string(allocator, challenge_buf, difficulty) catch return false;
std.log.info("decoded challenge {any}\n", .{challenge});
const solution = algorithms.kCTF.Challenge.from_string(allocator, solution_buf, difficulty) catch return false;
defer {
challenge.destroy(allocator);
solution.destroy(allocator);
}
std.log.info("decoded challenge and solution\n", .{});
const is_valid = challenge.verify(allocator, solution) catch return false;
return is_valid;
@@ -137,10 +130,7 @@ export fn hash(challenge_ptr: [*]u8, challenge_len: usize, nonce_ptr: [*]u8, non
hash_slice = algorithms.SHA256.hash(allocator, input_slice[0 .. challenge_len + nonce_len]) catch return 0;
},
algorithms.Algorithm.argon2 => {
const argon_key = algorithms.Argon2.hash(allocator, challenge, nonce) catch return 0;
defer allocator.free(argon_key);
hash_slice = algorithms.SHA256.hash(allocator, argon_key) catch return 0;
hash_slice = algorithms.Argon2.hash(allocator, challenge, nonce) catch return 0;
},
else => return 0,
}