aboutsummaryrefslogtreecommitdiff
path: root/src/javascript
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-04-13 04:20:05 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-04-13 04:20:05 -0700
commit3db3057d421a145743d63ebb5a487fb73e0e9f0b (patch)
treeece61bf4b75fb7f108c038082a6b273a234f27bf /src/javascript
parentf6d73cb06ec5fe217a4d2d03808f68ecbc2d3461 (diff)
downloadbun-3db3057d421a145743d63ebb5a487fb73e0e9f0b.tar.gz
bun-3db3057d421a145743d63ebb5a487fb73e0e9f0b.tar.zst
bun-3db3057d421a145743d63ebb5a487fb73e0e9f0b.zip
Support digest("base64" | "hex") in the hashings
Diffstat (limited to 'src/javascript')
-rw-r--r--src/javascript/jsc/api/bun.zig160
-rw-r--r--src/javascript/jsc/base.zig22
-rw-r--r--src/javascript/jsc/node/types.zig33
-rw-r--r--src/javascript/jsc/rare_data.zig9
4 files changed, 187 insertions, 37 deletions
diff --git a/src/javascript/jsc/api/bun.zig b/src/javascript/jsc/api/bun.zig
index 011314644..660f2aba8 100644
--- a/src/javascript/jsc/api/bun.zig
+++ b/src/javascript/jsc/api/bun.zig
@@ -1118,19 +1118,7 @@ pub const Class = NewClass(
.rfn = JSC.WebCore.Blob.writeFile,
.ts = d.ts{},
},
- .sha1 = .{
- .rfn = JSC.wrapWithHasContainer(Crypto.SHA1, "hash", false, false),
- },
- .sha256 = .{
- .rfn = JSC.wrapWithHasContainer(Crypto.SHA256, "hash", false, false),
- },
- .sha384 = .{
- .rfn = JSC.wrapWithHasContainer(Crypto.SHA384, "hash", false, false),
- },
- .sha512 = .{
- .rfn = JSC.wrapWithHasContainer(Crypto.SHA512, "hash", false, false),
- },
- .sha512_256 = .{
+ .sha = .{
.rfn = JSC.wrapWithHasContainer(Crypto.SHA512_256, "hash", false, false),
},
},
@@ -1189,18 +1177,28 @@ pub const Class = NewClass(
.unsafe = .{
.get = getUnsafe,
},
+
.SHA1 = .{
.get = Crypto.SHA1.getter,
},
- .SHA256 = .{
- .get = Crypto.SHA256.getter,
+ .MD5 = .{
+ .get = Crypto.MD5.getter,
},
- .SHA384 = .{
- .get = Crypto.SHA384.getter,
+ .MD4 = .{
+ .get = Crypto.MD4.getter,
+ },
+ .SHA224 = .{
+ .get = Crypto.SHA224.getter,
},
.SHA512 = .{
.get = Crypto.SHA512.getter,
},
+ .SHA384 = .{
+ .get = Crypto.SHA384.getter,
+ },
+ .SHA256 = .{
+ .get = Crypto.SHA256.getter,
+ },
.SHA512_256 = .{
.get = Crypto.SHA512_256.getter,
},
@@ -1238,7 +1236,7 @@ pub const Crypto = struct {
@This(),
.{
.hash = .{
- .rfn = JSC.wrapSync(@This(), "hash"),
+ .rfn = JSC.wrapWithHasContainer(@This(), "hash", false, false),
},
.constructor = .{ .rfn = constructor },
},
@@ -1258,8 +1256,8 @@ pub const Crypto = struct {
.update = .{
.rfn = JSC.wrapSync(@This(), "update"),
},
- .final = .{
- .rfn = JSC.wrapSync(@This(), "final"),
+ .digest = .{
+ .rfn = JSC.wrapSync(@This(), "digest"),
},
.finalize = finalize,
},
@@ -1270,7 +1268,20 @@ pub const Crypto = struct {
},
);
- pub fn hash(
+ fn hashToEncoding(
+ globalThis: *JSGlobalObject,
+ input: JSC.Node.StringOrBuffer,
+ encoding: JSC.Node.Encoding,
+ exception: JSC.C.ExceptionRef,
+ ) JSC.JSValue {
+ var output_digest_buf: Hasher.Digest = undefined;
+
+ Hasher.hash(input.slice(), &output_digest_buf, JSC.VirtualMachine.vm.rareData().boringEngine());
+
+ return encoding.encodeWithSize(globalThis, Hasher.digest, &output_digest_buf, exception);
+ }
+
+ fn hashToBytes(
globalThis: *JSGlobalObject,
input: JSC.Node.StringOrBuffer,
output: ?JSC.ArrayBuffer,
@@ -1293,7 +1304,7 @@ pub const Crypto = struct {
output_digest_slice = bytes[0..Hasher.digest];
}
- Hasher.hash(input.slice(), output_digest_slice);
+ Hasher.hash(input.slice(), output_digest_slice, JSC.VirtualMachine.vm.rareData().boringEngine());
if (output) |output_buf| {
return output_buf.value;
@@ -1303,6 +1314,37 @@ pub const Crypto = struct {
}
}
+ pub fn hash(
+ globalThis: *JSGlobalObject,
+ input: JSC.Node.StringOrBuffer,
+ output: ?JSC.Node.StringOrBuffer,
+ exception: JSC.C.ExceptionRef,
+ ) JSC.JSValue {
+ if (output) |string_or_buffer| {
+ switch (string_or_buffer) {
+ .string => |str| {
+ const encoding = JSC.Node.Encoding.from(str) orelse {
+ JSC.JSError(
+ bun.default_allocator,
+ "Unknown encoding",
+ .{},
+ globalThis.ref(),
+ exception,
+ );
+ return JSC.JSValue.zero;
+ };
+
+ return hashToEncoding(globalThis, input, encoding, exception);
+ },
+ .buffer => |buffer| {
+ return hashToBytes(globalThis, input, buffer.buffer, exception);
+ },
+ }
+ } else {
+ return hashToBytes(globalThis, input, null, exception);
+ }
+ }
+
pub fn constructor(
ctx: js.JSContextRef,
_: js.JSObjectRef,
@@ -1336,12 +1378,47 @@ pub const Crypto = struct {
return existing.asObjectRef();
}
- pub fn update(this: *@This(), buffer: JSC.Node.StringOrBuffer) JSC.JSValue {
+ pub fn update(this: *@This(), thisObj: JSC.C.JSObjectRef, buffer: JSC.Node.StringOrBuffer) JSC.JSValue {
this.hashing.update(buffer.slice());
- return JSC.JSValue.jsUndefined();
+ return JSC.JSValue.c(thisObj);
}
- pub fn final(this: *@This(), globalThis: *JSGlobalObject, exception: JSC.C.ExceptionRef, output: ?JSC.ArrayBuffer) JSC.JSValue {
+ pub fn digest(
+ this: *@This(),
+ globalThis: *JSGlobalObject,
+ output: ?JSC.Node.StringOrBuffer,
+ exception: JSC.C.ExceptionRef,
+ ) JSC.JSValue {
+ if (output) |string_or_buffer| {
+ switch (string_or_buffer) {
+ .string => |str| {
+ const encoding = JSC.Node.Encoding.from(str) orelse {
+ JSC.JSError(
+ bun.default_allocator,
+ "Unknown encoding",
+ .{},
+ globalThis.ref(),
+ exception,
+ );
+ return JSC.JSValue.zero;
+ };
+
+ return this.digestToEncoding(globalThis, exception, encoding);
+ },
+ .buffer => |buffer| {
+ return this.digestToBytes(
+ globalThis,
+ exception,
+ buffer.buffer,
+ );
+ },
+ }
+ } else {
+ return this.digestToBytes(globalThis, exception, null);
+ }
+ }
+
+ fn digestToBytes(this: *@This(), globalThis: *JSGlobalObject, exception: JSC.C.ExceptionRef, output: ?JSC.ArrayBuffer) JSC.JSValue {
var output_digest_buf: Hasher.Digest = undefined;
var output_digest_slice: *Hasher.Digest = &output_digest_buf;
if (output) |output_buf| {
@@ -1370,6 +1447,7 @@ pub const Crypto = struct {
}
this.hashing.final(output_digest_slice);
+
if (output) |output_buf| {
return output_buf.value;
} else {
@@ -1378,17 +1456,39 @@ pub const Crypto = struct {
}
}
+ fn digestToEncoding(this: *@This(), globalThis: *JSGlobalObject, exception: JSC.C.ExceptionRef, encoding: JSC.Node.Encoding) JSC.JSValue {
+ var output_digest_buf: Hasher.Digest = comptime brk: {
+ var bytes: Hasher.Digest = undefined;
+ var i: usize = 0;
+ while (i < Hasher.digest) {
+ bytes[i] = 0;
+ i += 1;
+ }
+ break :brk bytes;
+ };
+
+ var output_digest_slice: *Hasher.Digest = &output_digest_buf;
+
+ this.hashing.final(output_digest_slice);
+
+ return encoding.encodeWithSize(globalThis, Hasher.digest, output_digest_slice, exception);
+ }
+
pub fn finalize(this: *@This()) void {
VirtualMachine.vm.allocator.destroy(this);
}
};
}
- pub const SHA1 = CryptoHasher(Hashers.SHA1, "SHA1", "Bun_SHA1");
- pub const SHA256 = CryptoHasher(Hashers.SHA256, "SHA256", "Bun_SHA256");
- pub const SHA384 = CryptoHasher(Hashers.SHA384, "SHA384", "Bun_SHA384");
- pub const SHA512 = CryptoHasher(Hashers.SHA512, "SHA512", "Bun_SHA512");
- pub const SHA512_256 = CryptoHasher(Hashers.SHA512_256, "SHA512_256", "Bun_SHA512_256");
+ pub const SHA1 = CryptoHasher(Hashers.SHA1, "SHA1", "Bun_Crypto_SHA1");
+ pub const MD5 = CryptoHasher(Hashers.MD5, "MD5", "Bun_Crypto_MD5");
+ pub const MD4 = CryptoHasher(Hashers.MD4, "MD4", "Bun_Crypto_MD4");
+ pub const SHA224 = CryptoHasher(Hashers.SHA224, "SHA224", "Bun_Crypto_SHA224");
+ pub const SHA512 = CryptoHasher(Hashers.SHA512, "SHA512", "Bun_Crypto_SHA512");
+ pub const SHA384 = CryptoHasher(Hashers.SHA384, "SHA384", "Bun_Crypto_SHA384");
+ pub const SHA256 = CryptoHasher(Hashers.SHA256, "SHA256", "Bun_Crypto_SHA256");
+ pub const SHA512_256 = CryptoHasher(Hashers.SHA512_256, "SHA512_256", "Bun_Crypto_SHA512_256");
+ pub const MD5_SHA1 = CryptoHasher(Hashers.MD5_SHA1, "MD5_SHA1", "Bun_Crypto_MD5_SHA1");
};
pub fn serve(
diff --git a/src/javascript/jsc/base.zig b/src/javascript/jsc/base.zig
index 9c07e9b37..23224b7ab 100644
--- a/src/javascript/jsc/base.zig
+++ b/src/javascript/jsc/base.zig
@@ -2557,10 +2557,14 @@ const SSLServer = JSC.API.SSLServer;
const DebugServer = JSC.API.DebugServer;
const DebugSSLServer = JSC.API.DebugSSLServer;
const SHA1 = JSC.API.Bun.Crypto.SHA1;
-const SHA256 = JSC.API.Bun.Crypto.SHA256;
-const SHA384 = JSC.API.Bun.Crypto.SHA384;
+const MD5 = JSC.API.Bun.Crypto.MD5;
+const MD4 = JSC.API.Bun.Crypto.MD4;
+const SHA224 = JSC.API.Bun.Crypto.SHA224;
const SHA512 = JSC.API.Bun.Crypto.SHA512;
+const SHA384 = JSC.API.Bun.Crypto.SHA384;
+const SHA256 = JSC.API.Bun.Crypto.SHA256;
const SHA512_256 = JSC.API.Bun.Crypto.SHA512_256;
+const MD5_SHA1 = JSC.API.Bun.Crypto.MD5_SHA1;
pub const JSPrivateDataPtr = TaggedPointerUnion(.{
AttributeIterator,
@@ -2584,6 +2588,9 @@ pub const JSPrivateDataPtr = TaggedPointerUnion(.{
HTMLRewriter,
JSNode,
LazyPropertiesObject,
+ MD4,
+ MD5_SHA1,
+ MD5,
ModuleNamespace,
NodeFS,
Request,
@@ -2591,6 +2598,12 @@ pub const JSPrivateDataPtr = TaggedPointerUnion(.{
Response,
Router,
Server,
+ SHA1,
+ SHA224,
+ SHA256,
+ SHA384,
+ SHA512_256,
+ SHA512,
SSLServer,
Stats,
TextChunk,
@@ -2598,11 +2611,6 @@ pub const JSPrivateDataPtr = TaggedPointerUnion(.{
TextEncoder,
TimeoutTask,
Transpiler,
- SHA1,
- SHA256,
- SHA384,
- SHA512,
- SHA512_256,
});
pub inline fn GetJSPrivateData(comptime Type: type, ref: js.JSObjectRef) ?*Type {
diff --git a/src/javascript/jsc/node/types.zig b/src/javascript/jsc/node/types.zig
index 63b9b4444..1bf44e211 100644
--- a/src/javascript/jsc/node/types.zig
+++ b/src/javascript/jsc/node/types.zig
@@ -193,6 +193,11 @@ pub const Encoding = enum(u8) {
var str = JSC.ZigString.Empty;
value.toZigString(&str, global);
const slice = str.slice();
+ return from(slice);
+ }
+
+ /// Caller must verify the value is a string
+ pub fn from(slice: []const u8) ?Encoding {
return switch (slice.len) {
0...2 => null,
else => switch (Eight.matchLower(slice)) {
@@ -214,6 +219,34 @@ pub const Encoding = enum(u8) {
},
};
}
+
+ pub fn encodeWithSize(encoding: Encoding, globalThis: *JSC.JSGlobalObject, comptime size: usize, input: *const [size]u8, exception: JSC.C.ExceptionRef) JSC.JSValue {
+ switch (encoding) {
+ .base64 => {
+ var base64: [std.base64.standard.Encoder.calcSize(size)]u8 = undefined;
+ const result = JSC.ZigString.init(std.base64.standard.Encoder.encode(&base64, input)).toValueGC(globalThis);
+ return result;
+ },
+ .base64url => {
+ var buf: [std.base64.url_safe.Encoder.calcSize(size) + "data:;base64,".len]u8 = undefined;
+ var encoded = std.base64.url_safe.Encoder.encode(buf["data:;base64,".len..], input);
+ buf[0.."data:;base64,".len].* = "data:;base64,".*;
+
+ const result = JSC.ZigString.init(buf[0 .. "data:;base64,".len + encoded.len]).toValueGC(globalThis);
+ return result;
+ },
+ .hex => {
+ var buf: [size * 4]u8 = undefined;
+ var out = std.fmt.bufPrint(&buf, "{}", .{std.fmt.fmtSliceHexLower(input)}) catch unreachable;
+ const result = JSC.ZigString.init(out).toValueGC(globalThis);
+ return result;
+ },
+ else => {
+ JSC.throwInvalidArguments("Unexpected encoding", .{}, globalThis.ref(), exception);
+ return JSC.JSValue.zero;
+ },
+ }
+ }
};
const PathOrBuffer = union(Tag) {
diff --git a/src/javascript/jsc/rare_data.zig b/src/javascript/jsc/rare_data.zig
index efd602085..b6559826c 100644
--- a/src/javascript/jsc/rare_data.zig
+++ b/src/javascript/jsc/rare_data.zig
@@ -6,12 +6,21 @@ const RareData = @This();
const Syscall = @import("./node/syscall.zig");
const JSC = @import("javascript_core");
const std = @import("std");
+const BoringSSL = @import("boringssl");
+boring_ssl_engine: ?*BoringSSL.ENGINE = null,
editor_context: EditorContext = EditorContext{},
stderr_store: ?*Blob.Store = null,
stdin_store: ?*Blob.Store = null,
stdout_store: ?*Blob.Store = null,
+pub fn boringEngine(rare: *RareData) *BoringSSL.ENGINE {
+ return rare.boring_ssl_engine orelse brk: {
+ rare.boring_ssl_engine = BoringSSL.ENGINE_new();
+ break :brk rare.boring_ssl_engine.?;
+ };
+}
+
pub fn stderr(rare: *RareData) *Blob.Store {
return rare.stderr_store orelse brk: {
var store = default_allocator.create(Blob.Store) catch unreachable;