diff options
-rw-r--r-- | packages/bun-types/bun.d.ts | 97 | ||||
-rw-r--r-- | src/bun.js/api/bun.zig | 34 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGlobalObject.cpp | 17 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGlobalObject.h | 2 | ||||
-rwxr-xr-x | test/bun.lockb | bin | 36614 -> 51098 bytes | |||
-rw-r--r-- | test/js/bun/util/password.test.ts | 14 |
6 files changed, 89 insertions, 75 deletions
diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index 2396ffbd9..8e6664aed 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -1143,40 +1143,38 @@ declare module "bun" { | Password.Argon2Algorithm | Password.BCryptAlgorithm, ): Promise<string>; - }; - /** - * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. - * Warning: password hashing is slow, consider using {@link Bun.password} - * instead which runs in a worker thread. - * - * The underlying implementation of these functions are provided by the Zig - * Standard Library. Thanks to @jedisct1 and other Zig constributors for their - * work on this. - * - * ### Example with argon2 - * - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hash("hello world"); - * const verify = await password.verify("hello world", hash); - * console.log(verify); // true - * ``` - * - * ### Example with bcrypt - * ```ts - * import {password} from "bun"; - * - * const hash = await password.hash("hello world", "bcrypt"); - * // algorithm is optional, will be inferred from the hash if not specified - * const verify = await password.verify("hello world", hash, "bcrypt"); - * - * console.log(verify); // true - * ``` - */ - export const passwordSync: { - verify( + /** + * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. + * Warning: password hashing is slow, consider using {@link Bun.password.verify} + * instead which runs in a worker thread. + * + * The underlying implementation of these functions are provided by the Zig + * Standard Library. Thanks to @jedisct1 and other Zig constributors for their + * work on this. + * + * ### Example with argon2 + * + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world"); + * const verify = await password.verifySync("hello world", hash); + * console.log(verify); // true + * ``` + * + * ### Example with bcrypt + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world", "bcrypt"); + * // algorithm is optional, will be inferred from the hash if not specified + * const verify = await password.verifySync("hello world", hash, "bcrypt"); + * + * console.log(verify); // true + * ``` + */ + verifySync( password: StringOrBuffer, hash: StringOrBuffer, /** @@ -1184,7 +1182,38 @@ declare module "bun" { */ algorithm?: Password.AlgorithmLabel, ): boolean; - hash( + + /** + * Synchronously hash and verify passwords using argon2 or bcrypt. The default is argon2. + * Warning: password hashing is slow, consider using {@link Bun.password.hash} + * instead which runs in a worker thread. + * + * The underlying implementation of these functions are provided by the Zig + * Standard Library. Thanks to @jedisct1 and other Zig constributors for their + * work on this. + * + * ### Example with argon2 + * + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world"); + * const verify = await password.verifySync("hello world", hash); + * console.log(verify); // true + * ``` + * + * ### Example with bcrypt + * ```ts + * import {password} from "bun"; + * + * const hash = await password.hashSync("hello world", "bcrypt"); + * // algorithm is optional, will be inferred from the hash if not specified + * const verify = await password.verifySync("hello world", hash, "bcrypt"); + * + * console.log(verify); // true + * ``` + */ + hashSync( /** * The password to hash * diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig index 78a7379c2..7e9e3ca30 100644 --- a/src/bun.js/api/bun.zig +++ b/src/bun.js/api/bun.zig @@ -1632,7 +1632,7 @@ pub const Crypto = struct { return ZigString.fromUTF8(error_message).toErrorInstance(globalThis); } - const unknwon_password_algorithm_message = "unknown algorithm, expected one of: \"bcrypt\", \"argon2id\", \"argon2d\", \"argon2i\" (default is \"argon2id\")"; + const unknown_password_algorithm_message = "unknown algorithm, expected one of: \"bcrypt\", \"argon2id\", \"argon2d\", \"argon2i\" (default is \"argon2id\")"; pub const PasswordObject = struct { pub const pwhash = std.crypto.pwhash; @@ -1666,7 +1666,7 @@ pub const Crypto = struct { const algorithm_string = algorithm_value.getZigString(globalObject); switch (PasswordObject.Algorithm.label.getWithEql(algorithm_string, JSC.ZigString.eqlComptime) orelse { - globalObject.throwInvalidArgumentType("hash", "algorithm", unknwon_password_algorithm_message); + globalObject.throwInvalidArgumentType("hash", "algorithm", unknown_password_algorithm_message); return null; }) { .bcrypt => { @@ -1740,7 +1740,7 @@ pub const Crypto = struct { const algorithm_string = value.getZigString(globalObject); switch (PasswordObject.Algorithm.label.getWithEql(algorithm_string, JSC.ZigString.eqlComptime) orelse { - globalObject.throwInvalidArgumentType("hash", "algorithm", unknwon_password_algorithm_message); + globalObject.throwInvalidArgumentType("hash", "algorithm", unknown_password_algorithm_message); return null; }) { .bcrypt => { @@ -1950,23 +1950,27 @@ pub const Crypto = struct { } }; - pub export fn JSPasswordObject__create(globalObject: *JSC.JSGlobalObject, sync: bool) JSC.JSValue { - var object = JSValue.createEmptyObject(globalObject, 2); + pub export fn JSPasswordObject__create(globalObject: *JSC.JSGlobalObject) JSC.JSValue { + var object = JSValue.createEmptyObject(globalObject, 4); object.put( globalObject, ZigString.static("hash"), - if (!sync) - JSC.NewFunction(globalObject, ZigString.static("hash"), 2, JSPasswordObject__hash, false) - else - JSC.NewFunction(globalObject, ZigString.static("hash"), 2, JSPasswordObject__hashSync, false), + JSC.NewFunction(globalObject, ZigString.static("hash"), 2, JSPasswordObject__hash, false), + ); + object.put( + globalObject, + ZigString.static("hashSync"), + JSC.NewFunction(globalObject, ZigString.static("hashSync"), 2, JSPasswordObject__hashSync, false), ); object.put( globalObject, ZigString.static("verify"), - if (!sync) - JSC.NewFunction(globalObject, ZigString.static("verify"), 2, JSPasswordObject__verify, false) - else - JSC.NewFunction(globalObject, ZigString.static("verify"), 2, JSPasswordObject__verifySync, false), + JSC.NewFunction(globalObject, ZigString.static("verify"), 2, JSPasswordObject__verify, false), + ); + object.put( + globalObject, + ZigString.static("verifySync"), + JSC.NewFunction(globalObject, ZigString.static("verifySync"), 2, JSPasswordObject__verifySync, false), ); return object; } @@ -2333,7 +2337,7 @@ pub const Crypto = struct { const algorithm_string = arguments[2].getZigString(globalObject); algorithm = PasswordObject.Algorithm.label.getWithEql(algorithm_string, JSC.ZigString.eqlComptime) orelse { - globalObject.throwInvalidArgumentType("verify", "algorithm", unknwon_password_algorithm_message); + globalObject.throwInvalidArgumentType("verify", "algorithm", unknown_password_algorithm_message); return JSC.JSValue.undefined; }; } @@ -2398,7 +2402,7 @@ pub const Crypto = struct { const algorithm_string = arguments[2].getZigString(globalObject); algorithm = PasswordObject.Algorithm.label.getWithEql(algorithm_string, JSC.ZigString.eqlComptime) orelse { - globalObject.throwInvalidArgumentType("verify", "algorithm", unknwon_password_algorithm_message); + globalObject.throwInvalidArgumentType("verify", "algorithm", unknown_password_algorithm_message); return JSC.JSValue.undefined; }; } diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index bd9c19133..3e01e2bc7 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -2620,15 +2620,6 @@ void GlobalObject::finishCreation(VM& vm) init.set(result.toObject(globalObject)); }); - m_lazyPasswordSyncObject.initLater( - [](const Initializer<JSObject>& init) { - JSC::VM& vm = init.vm; - JSC::JSGlobalObject* globalObject = init.owner; - - JSValue result = JSValue::decode(JSPasswordObject__create(globalObject, true)); - init.set(result.toObject(globalObject)); - }); - m_lazyPreloadTestModuleObject.initLater( [](const Initializer<JSObject>& init) { JSC::VM& vm = init.vm; @@ -3556,7 +3547,6 @@ extern "C" void Crypto__randomUUID__put(JSC::JSGlobalObject* globalObject, JSC:: extern "C" void Crypto__getRandomValues__put(JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value); DEFINE_BUN_LAZY_GETTER(BUN_LAZY_GETTER_FN_NAME(password), passwordObject) -DEFINE_BUN_LAZY_GETTER(BUN_LAZY_GETTER_FN_NAME(passwordSync), passwordSyncObject) // This is not a publicly exposed API currently. // This is used by the bundler to make Response, Request, FetchEvent, @@ -3624,12 +3614,6 @@ void GlobalObject::installAPIGlobals(JSClassRef* globals, int count, JSC::VM& vm } { - JSC::Identifier identifier = JSC::Identifier::fromString(vm, "passwordSync"_s); - object->putDirectCustomAccessor(vm, identifier, JSC::CustomGetterSetter::create(vm, BUN_LAZY_GETTER_FN_NAME(passwordSync), nullptr), - JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0); - } - - { JSC::Identifier identifier = JSC::Identifier::fromString(vm, "readableStreamToArrayBuffer"_s); object->putDirectBuiltinFunction(vm, this, identifier, readableStreamReadableStreamToArrayBufferCodeGenerator(vm), JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); @@ -3900,7 +3884,6 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) thisObject->m_lazyPreloadTestModuleObject.visit(visitor); thisObject->m_commonJSModuleObjectStructure.visit(visitor); thisObject->m_lazyPasswordObject.visit(visitor); - thisObject->m_lazyPasswordSyncObject.visit(visitor); thisObject->m_commonJSFunctionArgumentsStructure.visit(visitor); thisObject->m_cachedGlobalObjectStructure.visit(visitor); thisObject->m_cachedGlobalProxyStructure.visit(visitor); diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h index 2363df74d..dbafa1a93 100644 --- a/src/bun.js/bindings/ZigGlobalObject.h +++ b/src/bun.js/bindings/ZigGlobalObject.h @@ -264,7 +264,6 @@ public: Structure* commonJSFunctionArgumentsStructure() { return m_commonJSFunctionArgumentsStructure.getInitializedOnMainThread(this); } - JSObject* passwordSyncObject() { return m_lazyPasswordSyncObject.getInitializedOnMainThread(this); } JSObject* passwordObject() { return m_lazyPasswordObject.getInitializedOnMainThread(this); } JSWeakMap* vmModuleContextMap() { return m_vmModuleContextMap.getInitializedOnMainThread(this); } @@ -479,7 +478,6 @@ private: LazyProperty<JSGlobalObject, JSObject> m_lazyRequireCacheObject; LazyProperty<JSGlobalObject, JSObject> m_lazyTestModuleObject; LazyProperty<JSGlobalObject, JSObject> m_lazyPreloadTestModuleObject; - LazyProperty<JSGlobalObject, JSObject> m_lazyPasswordSyncObject; LazyProperty<JSGlobalObject, JSObject> m_lazyPasswordObject; LazyProperty<JSGlobalObject, JSFunction> m_bunSleepThenCallback; diff --git a/test/bun.lockb b/test/bun.lockb Binary files differindex 3b60656d2..64371cbb1 100755 --- a/test/bun.lockb +++ b/test/bun.lockb diff --git a/test/js/bun/util/password.test.ts b/test/js/bun/util/password.test.ts index 67ea332c4..0f916ca44 100644 --- a/test/js/bun/util/password.test.ts +++ b/test/js/bun/util/password.test.ts @@ -1,12 +1,12 @@ import { test, expect, describe } from "bun:test"; -import { Password, password, passwordSync } from "bun"; +import { Password, password } from "bun"; const placeholder = "hey"; describe("hash", () => { describe("arguments parsing", () => { - for (let { hash } of [password, passwordSync]) { + for (let hash of [password.hash, password.hashSync]) { test("no blank password allowed", () => { expect(() => hash("")).toThrow("password must not be empty"); }); @@ -101,7 +101,7 @@ describe("hash", () => { describe("verify", () => { describe("arguments parsing", () => { - for (let { verify } of [password, passwordSync]) { + for (let verify of [password.verify, password.verifySync]) { test("minimum args", () => { // @ts-expect-error expect(() => verify()).toThrow(); @@ -195,11 +195,11 @@ for (let algorithmValue of algorithms) { describe(algorithmValue ? algorithmValue : "default", () => { const hash = (value: string | TypedArray) => { - return algorithmValue ? passwordSync.hash(value, algorithmValue as any) : passwordSync.hash(value); + return algorithmValue ? password.hashSync(value, algorithmValue as any) : password.hashSync(value); }; const hashSync = (value: string | TypedArray) => { - return algorithmValue ? passwordSync.hash(value, algorithmValue as any) : passwordSync.hash(value); + return algorithmValue ? password.hashSync(value, algorithmValue as any) : password.hashSync(value); }; const verify = (pw: string | TypedArray, value: string | TypedArray) => { @@ -207,12 +207,12 @@ for (let algorithmValue of algorithms) { }; const verifySync = (pw: string | TypedArray, value: string | TypedArray) => { - return algorithmValue ? passwordSync.verify(pw, value, algorithmValue as any) : passwordSync.verify(pw, value); + return algorithmValue ? password.verifySync(pw, value, algorithmValue as any) : password.verifySync(pw, value); }; for (let input of [placeholder, Buffer.from(placeholder)]) { describe(typeof input === "string" ? "string" : "buffer", () => { - test("passwordSync", () => { + test("password sync", () => { const hashed = hashSync(input); expect(hashed).toStartWith(prefix); expect(verifySync(input, hashed)).toBeTrue(); |