Files
bun.sh/src/bun.js/node/node_crypto_binding.zig
2024-11-13 21:11:56 -08:00

98 lines
3.5 KiB
Zig

const std = @import("std");
const bun = @import("root").bun;
const Environment = bun.Environment;
const JSC = bun.JSC;
const string = bun.string;
const Output = bun.Output;
const ZigString = JSC.ZigString;
const Crypto = JSC.API.Bun.Crypto;
const BoringSSL = bun.BoringSSL;
const assert = bun.assert;
const EVP = Crypto.EVP;
const PBKDF2 = EVP.PBKDF2;
const JSValue = JSC.JSValue;
const validators = @import("./util/validators.zig");
fn randomInt(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue {
const arguments = callframe.arguments(2).slice();
//min, max
if (!arguments[0].isNumber()) return globalThis.throwInvalidArgumentTypeValue("min", "safe integer", arguments[0]);
if (!arguments[1].isNumber()) return globalThis.throwInvalidArgumentTypeValue("max", "safe integer", arguments[1]);
const min = arguments[0].to(i64);
const max = arguments[1].to(i64);
if (min > JSC.MAX_SAFE_INTEGER or min < JSC.MIN_SAFE_INTEGER) {
return globalThis.throwInvalidArgumentRangeValue("min", "It must be a safe integer type number", min);
}
if (max > JSC.MAX_SAFE_INTEGER) {
return globalThis.throwInvalidArgumentRangeValue("max", "It must be a safe integer type number", max);
}
if (min >= max) {
return globalThis.throwInvalidArgumentRangeValue("max", "should be greater than min", max);
}
const diff = max - min;
if (diff > 281474976710655) {
return globalThis.throwInvalidArgumentRangeValue("max - min", "It must be <= 281474976710655", diff);
}
return JSC.JSValue.jsNumberFromInt64(std.crypto.random.intRangeLessThan(i64, min, max));
}
fn pbkdf2(
globalThis: *JSC.JSGlobalObject,
callframe: *JSC.CallFrame,
) bun.JSError!JSC.JSValue {
const arguments = callframe.arguments(5);
const data = PBKDF2.fromJS(globalThis, arguments.slice(), true) orelse {
assert(globalThis.hasException());
return .zero;
};
const job = PBKDF2.Job.create(JSC.VirtualMachine.get(), globalThis, &data);
return job.promise.value();
}
fn pbkdf2Sync(
globalThis: *JSC.JSGlobalObject,
callframe: *JSC.CallFrame,
) bun.JSError!JSC.JSValue {
const arguments = callframe.arguments(5);
var data = PBKDF2.fromJS(globalThis, arguments.slice(), false) orelse {
assert(globalThis.hasException());
return .zero;
};
defer data.deinit();
var out_arraybuffer = JSC.JSValue.createBufferFromLength(globalThis, @intCast(data.length));
if (out_arraybuffer == .zero or globalThis.hasException()) {
data.deinit();
return .zero;
}
const output = out_arraybuffer.asArrayBuffer(globalThis) orelse {
data.deinit();
globalThis.throwOutOfMemory();
return .zero;
};
if (!data.run(output.slice())) {
const err = Crypto.createCryptoError(globalThis, BoringSSL.ERR_get_error());
BoringSSL.ERR_clear_error();
globalThis.throwValue(err);
return .zero;
}
return out_arraybuffer;
}
pub fn createNodeCryptoBindingZig(global: *JSC.JSGlobalObject) JSC.JSValue {
const crypto = JSC.JSValue.createEmptyObject(global, 3);
crypto.put(global, bun.String.init("pbkdf2"), JSC.JSFunction.create(global, "pbkdf2", pbkdf2, 5, .{}));
crypto.put(global, bun.String.init("pbkdf2Sync"), JSC.JSFunction.create(global, "pbkdf2Sync", pbkdf2Sync, 5, .{}));
crypto.put(global, bun.String.init("randomInt"), JSC.JSFunction.create(global, "randomInt", randomInt, 2, .{}));
return crypto;
}