bun-argon2 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Aissam Irhir
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,246 @@
1
+ # bun-argon2
2
+
3
+ High-performance Argon2 password hashing for Bun and Node.js, built with Rust and napi-rs.
4
+
5
+ [![npm version](https://badge.fury.io/js/bun-argon2.svg)](https://www.npmjs.com/package/bun-argon2)
6
+ [![CI](https://github.com/nexus-aissam/bun-argon2/workflows/CI/badge.svg)](https://github.com/nexus-aissam/bun-argon2/actions)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+
9
+ ## Why bun-argon2?
10
+
11
+ The popular `argon2` npm package has broken native bindings when installed with Bun. This library provides a Bun-first alternative that's:
12
+
13
+ - **Fast** - **1.33x faster** than the `argon2` npm package
14
+ - **Safe** - Uses the battle-tested `argon2` Rust crate
15
+ - **Typed** - Full TypeScript support with strict types
16
+ - **Compatible** - Works with both Bun and Node.js
17
+
18
+ ## Benchmarks
19
+
20
+ Tested on Apple M1 Pro with Bun 1.3.3:
21
+
22
+ | Operation | bun-argon2 | argon2 (npm) | Difference |
23
+ |-----------|------------|--------------|------------|
24
+ | Hash (async) | 3.31 ms | 4.40 ms | **1.33x faster** |
25
+ | Hash (sync) | 3.20 ms | N/A | - |
26
+ | Verify (async) | 3.28 ms | 4.35 ms | **1.33x faster** |
27
+ | Verify (sync) | 3.23 ms | N/A | - |
28
+
29
+ > Benchmark settings: memoryCost=4096 KB, timeCost=2, parallelism=1
30
+ >
31
+ > Run benchmarks yourself: `bun run benchmarks/bench.ts`
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ # Using Bun (recommended)
37
+ bun add bun-argon2
38
+
39
+ # Using npm
40
+ npm install bun-argon2
41
+
42
+ # Using yarn
43
+ yarn add bun-argon2
44
+
45
+ # Using pnpm
46
+ pnpm add bun-argon2
47
+ ```
48
+
49
+ ## Quick Start
50
+
51
+ ```typescript
52
+ import { hash, verify } from 'bun-argon2';
53
+
54
+ // Hash a password
55
+ const hashed = await hash('myPassword123');
56
+ // $argon2id$v=19$m=65536,t=3,p=4$...
57
+
58
+ // Verify a password
59
+ const isValid = await verify(hashed, 'myPassword123');
60
+ // true
61
+ ```
62
+
63
+ ## API Reference
64
+
65
+ ### `hash(password, options?)`
66
+
67
+ Hash a password asynchronously (recommended).
68
+
69
+ ```typescript
70
+ import { hash } from 'bun-argon2';
71
+
72
+ // Basic usage
73
+ const hashed = await hash('password');
74
+
75
+ // With custom options
76
+ const hashed = await hash('password', {
77
+ type: 'argon2id', // 'argon2d' | 'argon2i' | 'argon2id'
78
+ memoryCost: 65536, // Memory in KB (default: 64MB)
79
+ timeCost: 3, // Iterations (default: 3)
80
+ parallelism: 4, // Threads (default: 4)
81
+ hashLength: 32, // Output length in bytes
82
+ salt: customSalt, // Custom salt (optional)
83
+ });
84
+ ```
85
+
86
+ ### `verify(hash, password)`
87
+
88
+ Verify a password against a hash asynchronously.
89
+
90
+ ```typescript
91
+ import { verify } from 'bun-argon2';
92
+
93
+ const isValid = await verify(hash, 'password');
94
+ ```
95
+
96
+ ### `hashSync(password, options?)`
97
+
98
+ Hash a password synchronously (blocking).
99
+
100
+ ```typescript
101
+ import { hashSync } from 'bun-argon2';
102
+
103
+ const hashed = hashSync('password');
104
+ ```
105
+
106
+ ### `verifySync(hash, password)`
107
+
108
+ Verify a password synchronously (blocking).
109
+
110
+ ```typescript
111
+ import { verifySync } from 'bun-argon2';
112
+
113
+ const isValid = verifySync(hash, 'password');
114
+ ```
115
+
116
+ ### `hashRaw(password, options?)`
117
+
118
+ Get raw hash and salt as Buffers (for custom storage).
119
+
120
+ ```typescript
121
+ import { hashRaw } from 'bun-argon2';
122
+
123
+ const { hash, salt } = await hashRaw('password');
124
+ console.log(hash.toString('hex'));
125
+ console.log(salt.toString('hex'));
126
+ ```
127
+
128
+ ### `needsRehash(hash, options?)`
129
+
130
+ Check if a hash needs to be rehashed (e.g., after changing parameters).
131
+
132
+ ```typescript
133
+ import { needsRehash } from 'bun-argon2';
134
+
135
+ const oldHash = '$argon2id$v=19$m=4096,t=1,p=1$...';
136
+
137
+ if (needsRehash(oldHash, { memoryCost: 65536, timeCost: 3 })) {
138
+ // Re-hash with new parameters on next login
139
+ }
140
+ ```
141
+
142
+ ## Options
143
+
144
+ | Option | Type | Default | Description |
145
+ |--------|------|---------|-------------|
146
+ | `type` | `'argon2d' \| 'argon2i' \| 'argon2id'` | `'argon2id'` | Algorithm variant |
147
+ | `memoryCost` | `number` | `65536` | Memory usage in KB (64MB default) |
148
+ | `timeCost` | `number` | `3` | Number of iterations |
149
+ | `parallelism` | `number` | `4` | Number of threads |
150
+ | `hashLength` | `number` | `32` | Output hash length in bytes |
151
+ | `salt` | `Buffer` | auto-generated | Custom salt (16+ bytes recommended) |
152
+
153
+ ## Algorithm Variants
154
+
155
+ - **argon2id** (recommended) - Hybrid of argon2i and argon2d, best for password hashing
156
+ - **argon2i** - Data-independent, resistant to side-channel attacks
157
+ - **argon2d** - Data-dependent, faster but vulnerable to side-channel attacks
158
+
159
+ ## Security Recommendations
160
+
161
+ For password hashing, OWASP recommends:
162
+
163
+ ```typescript
164
+ // Minimum recommended settings
165
+ const options = {
166
+ type: 'argon2id',
167
+ memoryCost: 19456, // 19MB
168
+ timeCost: 2,
169
+ parallelism: 1,
170
+ };
171
+
172
+ // Stronger settings (if resources allow)
173
+ const strongerOptions = {
174
+ type: 'argon2id',
175
+ memoryCost: 65536, // 64MB
176
+ timeCost: 3,
177
+ parallelism: 4,
178
+ };
179
+ ```
180
+
181
+ ## Comparison
182
+
183
+ | Feature | bun-argon2 | argon2 (npm) | @node-rs/argon2 |
184
+ |---------|------------|--------------|-----------------|
185
+ | Bun Support | Native | Broken | Partial |
186
+ | Node.js Support | Yes | Yes | Yes |
187
+ | Async API | Yes | Yes | Yes |
188
+ | Sync API | Yes | Yes | Yes |
189
+ | TypeScript | Full | Basic | Full |
190
+ | Implementation | Pure Rust | C | Pure Rust |
191
+ | Prebuilt Binaries | Yes | Yes | Yes |
192
+
193
+ ## Supported Platforms
194
+
195
+ | Platform | Architecture | Support |
196
+ |----------|--------------|---------|
197
+ | macOS | ARM64 (M1/M2/M3) | Yes |
198
+ | macOS | x64 (Intel) | Yes |
199
+ | Linux | x64 (glibc) | Yes |
200
+ | Linux | x64 (musl/Alpine) | Yes |
201
+ | Linux | ARM64 (glibc) | Yes |
202
+ | Linux | ARM64 (musl) | Yes |
203
+ | Windows | x64 | Yes |
204
+
205
+ ## Development
206
+
207
+ ```bash
208
+ # Clone the repository
209
+ git clone https://github.com/nexus-aissam/bun-argon2.git
210
+ cd bun-argon2
211
+
212
+ # Install dependencies
213
+ bun install
214
+
215
+ # Build native module (requires Rust)
216
+ bun run build
217
+
218
+ # Build TypeScript
219
+ bun run build:ts
220
+
221
+ # Run tests
222
+ bun test
223
+ ```
224
+
225
+ ### Requirements
226
+
227
+ - Bun 1.0+ or Node.js 18+
228
+ - Rust 1.70+ (for building from source)
229
+
230
+ ## License
231
+
232
+ MIT License - see [LICENSE](LICENSE) for details.
233
+
234
+ ## Author
235
+
236
+ Aissam Irhir ([@nexus-aissam](https://github.com/nexus-aissam))
237
+
238
+ ## Contributing
239
+
240
+ Contributions are welcome! Please read our contributing guidelines before submitting a PR.
241
+
242
+ ## Acknowledgments
243
+
244
+ - [argon2](https://crates.io/crates/argon2) - Rust Argon2 implementation
245
+ - [napi-rs](https://napi.rs/) - Rust bindings for Node.js
246
+ - [Bun](https://bun.sh/) - Fast JavaScript runtime
Binary file
@@ -0,0 +1,158 @@
1
+ import { Argon2Options, RawHashResult } from './types.mjs';
2
+ export { Argon2Type } from './types.mjs';
3
+
4
+ /**
5
+ * bun-argon2 - High-performance Argon2 password hashing for Bun and Node.js
6
+ *
7
+ * @module bun-argon2
8
+ * @author Aissam Irhir <aissamirhir@gmail.com>
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { hash, verify } from 'bun-argon2';
13
+ *
14
+ * // Hash a password
15
+ * const hashed = await hash('myPassword123');
16
+ *
17
+ * // Verify a password
18
+ * const isValid = await verify(hashed, 'myPassword123');
19
+ * ```
20
+ */
21
+
22
+ /**
23
+ * Hash a password asynchronously (recommended)
24
+ *
25
+ * Returns a PHC-formatted hash string like:
26
+ * `$argon2id$v=19$m=65536,t=3,p=4$...`
27
+ *
28
+ * @param password - The password to hash
29
+ * @param options - Optional hashing parameters
30
+ * @returns Promise resolving to the hashed password string
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * // Basic usage
35
+ * const hashed = await hash('myPassword123');
36
+ *
37
+ * // With custom options
38
+ * const hashed = await hash('myPassword123', {
39
+ * type: 'argon2id',
40
+ * memoryCost: 65536,
41
+ * timeCost: 3,
42
+ * parallelism: 4,
43
+ * });
44
+ * ```
45
+ */
46
+ declare function hash(password: string, options?: Argon2Options): Promise<string>;
47
+ /**
48
+ * Verify a password against a hash asynchronously (recommended)
49
+ *
50
+ * @param encoded - The PHC-formatted hash string
51
+ * @param password - The password to verify
52
+ * @returns Promise resolving to true if password matches
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const hashed = await hash('myPassword123');
57
+ * const isValid = await verify(hashed, 'myPassword123');
58
+ * console.log(isValid); // true
59
+ * ```
60
+ */
61
+ declare function verify(encoded: string, password: string): Promise<boolean>;
62
+ /**
63
+ * Hash a password synchronously (blocking)
64
+ *
65
+ * Use this only when async is not available (e.g., in constructors).
66
+ * Prefer `hash()` for better performance.
67
+ *
68
+ * @param password - The password to hash
69
+ * @param options - Optional hashing parameters
70
+ * @returns The hashed password string
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * const hashed = hashSync('myPassword123');
75
+ * ```
76
+ */
77
+ declare function hashSync(password: string, options?: Argon2Options): string;
78
+ /**
79
+ * Verify a password against a hash synchronously (blocking)
80
+ *
81
+ * Use this only when async is not available.
82
+ * Prefer `verify()` for better performance.
83
+ *
84
+ * @param encoded - The PHC-formatted hash string
85
+ * @param password - The password to verify
86
+ * @returns True if password matches
87
+ *
88
+ * @example
89
+ * ```typescript
90
+ * const isValid = verifySync(hashed, 'myPassword123');
91
+ * ```
92
+ */
93
+ declare function verifySync(encoded: string, password: string): boolean;
94
+ /**
95
+ * Get raw hash and salt as Buffers asynchronously
96
+ *
97
+ * Unlike `hash()` which returns a PHC string, this returns raw bytes.
98
+ * Useful for custom storage or when you need direct access to the hash bytes.
99
+ *
100
+ * @param password - The password to hash
101
+ * @param options - Optional hashing parameters
102
+ * @returns Promise resolving to object with hash and salt Buffers
103
+ *
104
+ * @example
105
+ * ```typescript
106
+ * const { hash, salt } = await hashRaw('myPassword123');
107
+ * console.log(hash.toString('hex')); // Raw hash as hex
108
+ * console.log(salt.toString('hex')); // Salt as hex
109
+ * ```
110
+ */
111
+ declare function hashRaw(password: string, options?: Argon2Options): Promise<RawHashResult>;
112
+ /**
113
+ * Get raw hash and salt as Buffers synchronously
114
+ *
115
+ * @param password - The password to hash
116
+ * @param options - Optional hashing parameters
117
+ * @returns Object with hash and salt Buffers
118
+ */
119
+ declare function hashRawSync(password: string, options?: Argon2Options): RawHashResult;
120
+ /**
121
+ * Check if a hash needs to be rehashed
122
+ *
123
+ * Useful when you've upgraded your hashing parameters and want to
124
+ * gradually migrate existing hashes.
125
+ *
126
+ * @param encoded - The PHC-formatted hash string
127
+ * @param options - The current hashing parameters to compare against
128
+ * @returns True if the hash uses different parameters
129
+ *
130
+ * @example
131
+ * ```typescript
132
+ * const oldHash = '$argon2id$v=19$m=4096,t=1,p=1$...';
133
+ * const newOptions = { memoryCost: 65536, timeCost: 3 };
134
+ *
135
+ * if (needsRehash(oldHash, newOptions)) {
136
+ * // Re-hash with new parameters on next login
137
+ * }
138
+ * ```
139
+ */
140
+ declare function needsRehash(encoded: string, options?: Argon2Options): boolean;
141
+ /**
142
+ * Get the native library version
143
+ *
144
+ * @returns Version string
145
+ */
146
+ declare function version(): string;
147
+ declare const _default: {
148
+ hash: typeof hash;
149
+ verify: typeof verify;
150
+ hashSync: typeof hashSync;
151
+ verifySync: typeof verifySync;
152
+ hashRaw: typeof hashRaw;
153
+ hashRawSync: typeof hashRawSync;
154
+ needsRehash: typeof needsRehash;
155
+ version: typeof version;
156
+ };
157
+
158
+ export { Argon2Options, RawHashResult, _default as default, hash, hashRaw, hashRawSync, hashSync, needsRehash, verify, verifySync, version };
@@ -0,0 +1,158 @@
1
+ import { Argon2Options, RawHashResult } from './types.js';
2
+ export { Argon2Type } from './types.js';
3
+
4
+ /**
5
+ * bun-argon2 - High-performance Argon2 password hashing for Bun and Node.js
6
+ *
7
+ * @module bun-argon2
8
+ * @author Aissam Irhir <aissamirhir@gmail.com>
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { hash, verify } from 'bun-argon2';
13
+ *
14
+ * // Hash a password
15
+ * const hashed = await hash('myPassword123');
16
+ *
17
+ * // Verify a password
18
+ * const isValid = await verify(hashed, 'myPassword123');
19
+ * ```
20
+ */
21
+
22
+ /**
23
+ * Hash a password asynchronously (recommended)
24
+ *
25
+ * Returns a PHC-formatted hash string like:
26
+ * `$argon2id$v=19$m=65536,t=3,p=4$...`
27
+ *
28
+ * @param password - The password to hash
29
+ * @param options - Optional hashing parameters
30
+ * @returns Promise resolving to the hashed password string
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * // Basic usage
35
+ * const hashed = await hash('myPassword123');
36
+ *
37
+ * // With custom options
38
+ * const hashed = await hash('myPassword123', {
39
+ * type: 'argon2id',
40
+ * memoryCost: 65536,
41
+ * timeCost: 3,
42
+ * parallelism: 4,
43
+ * });
44
+ * ```
45
+ */
46
+ declare function hash(password: string, options?: Argon2Options): Promise<string>;
47
+ /**
48
+ * Verify a password against a hash asynchronously (recommended)
49
+ *
50
+ * @param encoded - The PHC-formatted hash string
51
+ * @param password - The password to verify
52
+ * @returns Promise resolving to true if password matches
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const hashed = await hash('myPassword123');
57
+ * const isValid = await verify(hashed, 'myPassword123');
58
+ * console.log(isValid); // true
59
+ * ```
60
+ */
61
+ declare function verify(encoded: string, password: string): Promise<boolean>;
62
+ /**
63
+ * Hash a password synchronously (blocking)
64
+ *
65
+ * Use this only when async is not available (e.g., in constructors).
66
+ * Prefer `hash()` for better performance.
67
+ *
68
+ * @param password - The password to hash
69
+ * @param options - Optional hashing parameters
70
+ * @returns The hashed password string
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * const hashed = hashSync('myPassword123');
75
+ * ```
76
+ */
77
+ declare function hashSync(password: string, options?: Argon2Options): string;
78
+ /**
79
+ * Verify a password against a hash synchronously (blocking)
80
+ *
81
+ * Use this only when async is not available.
82
+ * Prefer `verify()` for better performance.
83
+ *
84
+ * @param encoded - The PHC-formatted hash string
85
+ * @param password - The password to verify
86
+ * @returns True if password matches
87
+ *
88
+ * @example
89
+ * ```typescript
90
+ * const isValid = verifySync(hashed, 'myPassword123');
91
+ * ```
92
+ */
93
+ declare function verifySync(encoded: string, password: string): boolean;
94
+ /**
95
+ * Get raw hash and salt as Buffers asynchronously
96
+ *
97
+ * Unlike `hash()` which returns a PHC string, this returns raw bytes.
98
+ * Useful for custom storage or when you need direct access to the hash bytes.
99
+ *
100
+ * @param password - The password to hash
101
+ * @param options - Optional hashing parameters
102
+ * @returns Promise resolving to object with hash and salt Buffers
103
+ *
104
+ * @example
105
+ * ```typescript
106
+ * const { hash, salt } = await hashRaw('myPassword123');
107
+ * console.log(hash.toString('hex')); // Raw hash as hex
108
+ * console.log(salt.toString('hex')); // Salt as hex
109
+ * ```
110
+ */
111
+ declare function hashRaw(password: string, options?: Argon2Options): Promise<RawHashResult>;
112
+ /**
113
+ * Get raw hash and salt as Buffers synchronously
114
+ *
115
+ * @param password - The password to hash
116
+ * @param options - Optional hashing parameters
117
+ * @returns Object with hash and salt Buffers
118
+ */
119
+ declare function hashRawSync(password: string, options?: Argon2Options): RawHashResult;
120
+ /**
121
+ * Check if a hash needs to be rehashed
122
+ *
123
+ * Useful when you've upgraded your hashing parameters and want to
124
+ * gradually migrate existing hashes.
125
+ *
126
+ * @param encoded - The PHC-formatted hash string
127
+ * @param options - The current hashing parameters to compare against
128
+ * @returns True if the hash uses different parameters
129
+ *
130
+ * @example
131
+ * ```typescript
132
+ * const oldHash = '$argon2id$v=19$m=4096,t=1,p=1$...';
133
+ * const newOptions = { memoryCost: 65536, timeCost: 3 };
134
+ *
135
+ * if (needsRehash(oldHash, newOptions)) {
136
+ * // Re-hash with new parameters on next login
137
+ * }
138
+ * ```
139
+ */
140
+ declare function needsRehash(encoded: string, options?: Argon2Options): boolean;
141
+ /**
142
+ * Get the native library version
143
+ *
144
+ * @returns Version string
145
+ */
146
+ declare function version(): string;
147
+ declare const _default: {
148
+ hash: typeof hash;
149
+ verify: typeof verify;
150
+ hashSync: typeof hashSync;
151
+ verifySync: typeof verifySync;
152
+ hashRaw: typeof hashRaw;
153
+ hashRawSync: typeof hashRawSync;
154
+ needsRehash: typeof needsRehash;
155
+ version: typeof version;
156
+ };
157
+
158
+ export { Argon2Options, RawHashResult, _default as default, hash, hashRaw, hashRawSync, hashSync, needsRehash, verify, verifySync, version };
package/dist/index.js ADDED
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ default: () => index_default,
24
+ hash: () => hash,
25
+ hashRaw: () => hashRaw,
26
+ hashRawSync: () => hashRawSync,
27
+ hashSync: () => hashSync,
28
+ needsRehash: () => needsRehash,
29
+ verify: () => verify,
30
+ verifySync: () => verifySync,
31
+ version: () => version
32
+ });
33
+ module.exports = __toCommonJS(index_exports);
34
+ var import_fs = require("fs");
35
+ var import_path = require("path");
36
+ var import_url = require("url");
37
+ var import_meta = {};
38
+ var getCurrentDir = () => {
39
+ try {
40
+ return (0, import_path.dirname)((0, import_url.fileURLToPath)(import_meta.url));
41
+ } catch {
42
+ return __dirname;
43
+ }
44
+ };
45
+ function loadNativeBinding() {
46
+ const platform = process.platform;
47
+ const arch = process.arch;
48
+ let targetName;
49
+ switch (platform) {
50
+ case "darwin":
51
+ targetName = arch === "arm64" ? "darwin-arm64" : "darwin-x64";
52
+ break;
53
+ case "linux":
54
+ const isMusl = (0, import_fs.existsSync)("/etc/alpine-release") || process.env.npm_config_libc === "musl";
55
+ if (arch === "arm64") {
56
+ targetName = isMusl ? "linux-arm64-musl" : "linux-arm64-gnu";
57
+ } else {
58
+ targetName = isMusl ? "linux-x64-musl" : "linux-x64-gnu";
59
+ }
60
+ break;
61
+ case "win32":
62
+ targetName = "win32-x64-msvc";
63
+ break;
64
+ default:
65
+ throw new Error(`Unsupported platform: ${platform}-${arch}`);
66
+ }
67
+ const currentDir = getCurrentDir();
68
+ const possiblePaths = [
69
+ // Same directory as this file (dist/)
70
+ (0, import_path.join)(currentDir, `argon2.${targetName}.node`),
71
+ // Parent directory (package root)
72
+ (0, import_path.join)(currentDir, "..", `argon2.${targetName}.node`),
73
+ // CWD (development)
74
+ (0, import_path.join)(process.cwd(), `argon2.${targetName}.node`)
75
+ ];
76
+ for (const modulePath of possiblePaths) {
77
+ try {
78
+ if ((0, import_fs.existsSync)(modulePath)) {
79
+ return require(modulePath);
80
+ }
81
+ } catch {
82
+ continue;
83
+ }
84
+ }
85
+ throw new Error(
86
+ `Failed to load native binding for ${platform}-${arch}. Tried: ${possiblePaths.join(", ")}`
87
+ );
88
+ }
89
+ var native = loadNativeBinding();
90
+ function toNapiOptions(options) {
91
+ if (!options) return void 0;
92
+ return {
93
+ algorithm: options.type,
94
+ memoryCost: options.memoryCost,
95
+ timeCost: options.timeCost,
96
+ parallelism: options.parallelism,
97
+ hashLength: options.hashLength,
98
+ salt: options.salt
99
+ };
100
+ }
101
+ async function hash(password, options) {
102
+ return native.hash(password, toNapiOptions(options));
103
+ }
104
+ async function verify(encoded, password) {
105
+ return native.verify(encoded, password);
106
+ }
107
+ function hashSync(password, options) {
108
+ return native.hashSync(password, toNapiOptions(options));
109
+ }
110
+ function verifySync(encoded, password) {
111
+ return native.verifySync(encoded, password);
112
+ }
113
+ async function hashRaw(password, options) {
114
+ return native.hashRaw(password, toNapiOptions(options));
115
+ }
116
+ function hashRawSync(password, options) {
117
+ return native.hashRawSync(password, toNapiOptions(options));
118
+ }
119
+ function needsRehash(encoded, options) {
120
+ return native.needsRehash(encoded, toNapiOptions(options));
121
+ }
122
+ function version() {
123
+ return native.version();
124
+ }
125
+ var index_default = {
126
+ hash,
127
+ verify,
128
+ hashSync,
129
+ verifySync,
130
+ hashRaw,
131
+ hashRawSync,
132
+ needsRehash,
133
+ version
134
+ };
135
+ // Annotate the CommonJS export names for ESM import in node:
136
+ 0 && (module.exports = {
137
+ hash,
138
+ hashRaw,
139
+ hashRawSync,
140
+ hashSync,
141
+ needsRehash,
142
+ verify,
143
+ verifySync,
144
+ version
145
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,119 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ // src/index.ts
9
+ import { existsSync } from "fs";
10
+ import { join, dirname } from "path";
11
+ import { fileURLToPath } from "url";
12
+ var getCurrentDir = () => {
13
+ try {
14
+ return dirname(fileURLToPath(import.meta.url));
15
+ } catch {
16
+ return __dirname;
17
+ }
18
+ };
19
+ function loadNativeBinding() {
20
+ const platform = process.platform;
21
+ const arch = process.arch;
22
+ let targetName;
23
+ switch (platform) {
24
+ case "darwin":
25
+ targetName = arch === "arm64" ? "darwin-arm64" : "darwin-x64";
26
+ break;
27
+ case "linux":
28
+ const isMusl = existsSync("/etc/alpine-release") || process.env.npm_config_libc === "musl";
29
+ if (arch === "arm64") {
30
+ targetName = isMusl ? "linux-arm64-musl" : "linux-arm64-gnu";
31
+ } else {
32
+ targetName = isMusl ? "linux-x64-musl" : "linux-x64-gnu";
33
+ }
34
+ break;
35
+ case "win32":
36
+ targetName = "win32-x64-msvc";
37
+ break;
38
+ default:
39
+ throw new Error(`Unsupported platform: ${platform}-${arch}`);
40
+ }
41
+ const currentDir = getCurrentDir();
42
+ const possiblePaths = [
43
+ // Same directory as this file (dist/)
44
+ join(currentDir, `argon2.${targetName}.node`),
45
+ // Parent directory (package root)
46
+ join(currentDir, "..", `argon2.${targetName}.node`),
47
+ // CWD (development)
48
+ join(process.cwd(), `argon2.${targetName}.node`)
49
+ ];
50
+ for (const modulePath of possiblePaths) {
51
+ try {
52
+ if (existsSync(modulePath)) {
53
+ return __require(modulePath);
54
+ }
55
+ } catch {
56
+ continue;
57
+ }
58
+ }
59
+ throw new Error(
60
+ `Failed to load native binding for ${platform}-${arch}. Tried: ${possiblePaths.join(", ")}`
61
+ );
62
+ }
63
+ var native = loadNativeBinding();
64
+ function toNapiOptions(options) {
65
+ if (!options) return void 0;
66
+ return {
67
+ algorithm: options.type,
68
+ memoryCost: options.memoryCost,
69
+ timeCost: options.timeCost,
70
+ parallelism: options.parallelism,
71
+ hashLength: options.hashLength,
72
+ salt: options.salt
73
+ };
74
+ }
75
+ async function hash(password, options) {
76
+ return native.hash(password, toNapiOptions(options));
77
+ }
78
+ async function verify(encoded, password) {
79
+ return native.verify(encoded, password);
80
+ }
81
+ function hashSync(password, options) {
82
+ return native.hashSync(password, toNapiOptions(options));
83
+ }
84
+ function verifySync(encoded, password) {
85
+ return native.verifySync(encoded, password);
86
+ }
87
+ async function hashRaw(password, options) {
88
+ return native.hashRaw(password, toNapiOptions(options));
89
+ }
90
+ function hashRawSync(password, options) {
91
+ return native.hashRawSync(password, toNapiOptions(options));
92
+ }
93
+ function needsRehash(encoded, options) {
94
+ return native.needsRehash(encoded, toNapiOptions(options));
95
+ }
96
+ function version() {
97
+ return native.version();
98
+ }
99
+ var index_default = {
100
+ hash,
101
+ verify,
102
+ hashSync,
103
+ verifySync,
104
+ hashRaw,
105
+ hashRawSync,
106
+ needsRehash,
107
+ version
108
+ };
109
+ export {
110
+ index_default as default,
111
+ hash,
112
+ hashRaw,
113
+ hashRawSync,
114
+ hashSync,
115
+ needsRehash,
116
+ verify,
117
+ verifySync,
118
+ version
119
+ };
@@ -0,0 +1,98 @@
1
+ /**
2
+ * bun-argon2 - TypeScript Type Definitions
3
+ *
4
+ * @module bun-argon2/types
5
+ * @author Aissam Irhir <aissamirhir@gmail.com>
6
+ */
7
+ /**
8
+ * Argon2 algorithm variant
9
+ *
10
+ * - `argon2d`: Data-dependent, vulnerable to side-channel attacks but fastest
11
+ * - `argon2i`: Data-independent, secure against side-channel attacks
12
+ * - `argon2id`: Hybrid (recommended), combines benefits of both
13
+ */
14
+ type Argon2Type = "argon2d" | "argon2i" | "argon2id";
15
+ /**
16
+ * Argon2 hashing options
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const options: Argon2Options = {
21
+ * type: 'argon2id',
22
+ * memoryCost: 65536, // 64MB
23
+ * timeCost: 3,
24
+ * parallelism: 4,
25
+ * };
26
+ * ```
27
+ */
28
+ interface Argon2Options {
29
+ /**
30
+ * Algorithm type
31
+ * @default 'argon2id'
32
+ */
33
+ type?: Argon2Type;
34
+ /**
35
+ * Memory cost in KB
36
+ * Higher values increase security but require more memory
37
+ * @default 65536 (64MB)
38
+ */
39
+ memoryCost?: number;
40
+ /**
41
+ * Time cost / iterations
42
+ * Higher values increase security but take longer
43
+ * @default 3
44
+ */
45
+ timeCost?: number;
46
+ /**
47
+ * Parallelism / threads
48
+ * Number of parallel threads to use
49
+ * @default 4
50
+ */
51
+ parallelism?: number;
52
+ /**
53
+ * Hash output length in bytes
54
+ * @default 32
55
+ */
56
+ hashLength?: number;
57
+ /**
58
+ * Custom salt as Buffer
59
+ * If not provided, a secure random salt is generated
60
+ * @default undefined (auto-generated)
61
+ */
62
+ salt?: Buffer;
63
+ }
64
+ /**
65
+ * Raw hash result containing hash and salt as Buffers
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * const result = await hashRaw('password');
70
+ * console.log(result.hash); // Buffer
71
+ * console.log(result.salt); // Buffer
72
+ * ```
73
+ */
74
+ interface RawHashResult {
75
+ /**
76
+ * Raw hash bytes
77
+ */
78
+ hash: Buffer;
79
+ /**
80
+ * Salt used for hashing
81
+ */
82
+ salt: Buffer;
83
+ }
84
+ /**
85
+ * Internal options format for napi bindings
86
+ * napi-rs converts Rust snake_case to JS camelCase
87
+ * @internal
88
+ */
89
+ interface NapiArgon2Options {
90
+ algorithm?: string;
91
+ memoryCost?: number;
92
+ timeCost?: number;
93
+ parallelism?: number;
94
+ hashLength?: number;
95
+ salt?: Buffer;
96
+ }
97
+
98
+ export type { Argon2Options, Argon2Type, NapiArgon2Options, RawHashResult };
@@ -0,0 +1,98 @@
1
+ /**
2
+ * bun-argon2 - TypeScript Type Definitions
3
+ *
4
+ * @module bun-argon2/types
5
+ * @author Aissam Irhir <aissamirhir@gmail.com>
6
+ */
7
+ /**
8
+ * Argon2 algorithm variant
9
+ *
10
+ * - `argon2d`: Data-dependent, vulnerable to side-channel attacks but fastest
11
+ * - `argon2i`: Data-independent, secure against side-channel attacks
12
+ * - `argon2id`: Hybrid (recommended), combines benefits of both
13
+ */
14
+ type Argon2Type = "argon2d" | "argon2i" | "argon2id";
15
+ /**
16
+ * Argon2 hashing options
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const options: Argon2Options = {
21
+ * type: 'argon2id',
22
+ * memoryCost: 65536, // 64MB
23
+ * timeCost: 3,
24
+ * parallelism: 4,
25
+ * };
26
+ * ```
27
+ */
28
+ interface Argon2Options {
29
+ /**
30
+ * Algorithm type
31
+ * @default 'argon2id'
32
+ */
33
+ type?: Argon2Type;
34
+ /**
35
+ * Memory cost in KB
36
+ * Higher values increase security but require more memory
37
+ * @default 65536 (64MB)
38
+ */
39
+ memoryCost?: number;
40
+ /**
41
+ * Time cost / iterations
42
+ * Higher values increase security but take longer
43
+ * @default 3
44
+ */
45
+ timeCost?: number;
46
+ /**
47
+ * Parallelism / threads
48
+ * Number of parallel threads to use
49
+ * @default 4
50
+ */
51
+ parallelism?: number;
52
+ /**
53
+ * Hash output length in bytes
54
+ * @default 32
55
+ */
56
+ hashLength?: number;
57
+ /**
58
+ * Custom salt as Buffer
59
+ * If not provided, a secure random salt is generated
60
+ * @default undefined (auto-generated)
61
+ */
62
+ salt?: Buffer;
63
+ }
64
+ /**
65
+ * Raw hash result containing hash and salt as Buffers
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * const result = await hashRaw('password');
70
+ * console.log(result.hash); // Buffer
71
+ * console.log(result.salt); // Buffer
72
+ * ```
73
+ */
74
+ interface RawHashResult {
75
+ /**
76
+ * Raw hash bytes
77
+ */
78
+ hash: Buffer;
79
+ /**
80
+ * Salt used for hashing
81
+ */
82
+ salt: Buffer;
83
+ }
84
+ /**
85
+ * Internal options format for napi bindings
86
+ * napi-rs converts Rust snake_case to JS camelCase
87
+ * @internal
88
+ */
89
+ interface NapiArgon2Options {
90
+ algorithm?: string;
91
+ memoryCost?: number;
92
+ timeCost?: number;
93
+ parallelism?: number;
94
+ hashLength?: number;
95
+ salt?: Buffer;
96
+ }
97
+
98
+ export type { Argon2Options, Argon2Type, NapiArgon2Options, RawHashResult };
package/dist/types.js ADDED
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __copyProps = (to, from, except, desc) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
+
16
+ // src/types.ts
17
+ var types_exports = {};
18
+ module.exports = __toCommonJS(types_exports);
package/dist/types.mjs ADDED
File without changes
package/package.json ADDED
@@ -0,0 +1,89 @@
1
+ {
2
+ "name": "bun-argon2",
3
+ "version": "1.0.0",
4
+ "description": "High-performance Argon2 password hashing for Bun and Node.js",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": {
11
+ "types": "./dist/index.d.mts",
12
+ "default": "./dist/index.mjs"
13
+ },
14
+ "require": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ }
18
+ }
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "napi": {
24
+ "name": "argon2",
25
+ "triples": {
26
+ "defaults": true,
27
+ "additional": [
28
+ "aarch64-apple-darwin",
29
+ "aarch64-unknown-linux-gnu",
30
+ "aarch64-unknown-linux-musl"
31
+ ]
32
+ }
33
+ },
34
+ "scripts": {
35
+ "build": "napi build --platform --release",
36
+ "build:debug": "napi build --platform",
37
+ "build:ts": "tsup src/index.ts --format cjs,esm --dts --clean",
38
+ "build:all": "bun run build && bun run build:ts",
39
+ "prepublishOnly": "napi prepublish -t npm",
40
+ "test": "bun test",
41
+ "bench": "bun run benchmarks/bench.ts",
42
+ "lint": "eslint src",
43
+ "clean": "rm -rf dist *.node npm"
44
+ },
45
+ "keywords": [
46
+ "argon2",
47
+ "argon2id",
48
+ "argon2i",
49
+ "argon2d",
50
+ "password",
51
+ "hash",
52
+ "hashing",
53
+ "crypto",
54
+ "security",
55
+ "bun",
56
+ "nodejs",
57
+ "rust",
58
+ "napi",
59
+ "native"
60
+ ],
61
+ "author": "Aissam Irhir <aissamirhir@gmail.com>",
62
+ "license": "MIT",
63
+ "repository": {
64
+ "type": "git",
65
+ "url": "git+https://github.com/nexus-aissam/bun-argon2.git"
66
+ },
67
+ "bugs": {
68
+ "url": "https://github.com/nexus-aissam/bun-argon2/issues"
69
+ },
70
+ "homepage": "https://github.com/nexus-aissam/bun-argon2#readme",
71
+ "engines": {
72
+ "node": ">=18.0.0"
73
+ },
74
+ "devDependencies": {
75
+ "@napi-rs/cli": "^2.18.4",
76
+ "@types/bun": "latest",
77
+ "argon2": "^0.44.0",
78
+ "tsup": "^8.4.0",
79
+ "typescript": "^5.9.0"
80
+ },
81
+ "optionalDependencies": {
82
+ "bun-argon2-win32-x64-msvc": "1.0.0",
83
+ "bun-argon2-darwin-x64": "1.0.0",
84
+ "bun-argon2-linux-x64-gnu": "1.0.0",
85
+ "bun-argon2-darwin-arm64": "1.0.0",
86
+ "bun-argon2-linux-arm64-gnu": "1.0.0",
87
+ "bun-argon2-linux-arm64-musl": "1.0.0"
88
+ }
89
+ }