diff options
author | 2022-04-13 04:20:05 -0700 | |
---|---|---|
committer | 2022-04-13 04:20:05 -0700 | |
commit | 3db3057d421a145743d63ebb5a487fb73e0e9f0b (patch) | |
tree | ece61bf4b75fb7f108c038082a6b273a234f27bf /src/javascript | |
parent | f6d73cb06ec5fe217a4d2d03808f68ecbc2d3461 (diff) | |
download | bun-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.zig | 160 | ||||
-rw-r--r-- | src/javascript/jsc/base.zig | 22 | ||||
-rw-r--r-- | src/javascript/jsc/node/types.zig | 33 | ||||
-rw-r--r-- | src/javascript/jsc/rare_data.zig | 9 |
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; |