Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
*.debug text eol=lf merge=union

# Generated codes
packages/argon2/index.js linguist-detectable=false
packages/argon2/index.d.ts linguist-detectable=false
packages/bcrypt/index.js linguist-detectable=false
packages/bcrypt/index.d.ts linguist-detectable=false
packages/crc32/index.js linguist-detectable=false
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ cargo-features = ["strip"]
[workspace]
members = [
"./crates/alloc",
"./packages/argon2",
"./packages/bcrypt",
"./packages/crc32",
"./packages/deno-lint",
Expand Down
10 changes: 10 additions & 0 deletions packages/argon2/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
target
Cargo.lock
.cargo
.github
npm
.eslintrc
.prettierignore
rustfmt.toml
yarn.lock
*.node
16 changes: 16 additions & 0 deletions packages/argon2/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
edition = "2021"
name = "node-rs_argon2"
version = "0.0.0"

[lib]
crate-type = ["cdylib"]

[dependencies]
argon2 = {version = "0.3", features = ["parallel"]}
napi = {version = "2", default-features = false, features = ["napi3"]}
napi-derive = {version = "2", default-features = false, features = ["type-def"]}
rand = {version = "0.8", features = ["nightly", "simd_support"]}

[build-dependencies]
napi-build = "1"
70 changes: 70 additions & 0 deletions packages/argon2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# `@node-rs/argon2`

![](https://github.com/napi-rs/node-rs/workflows/CI/badge.svg)
![](https://img.shields.io/npm/dm/@node-rs/argon2.svg?sanitize=true)

[argon2](https://crates.io/crates/argon2) binding for Node.js.

## Support matrix

| | node12 | node14 | node16 | node17 |
| ------------------- | ------ | ------ | ------ | ------ |
| Windows x64 | ✓ | ✓ | ✓ | ✓ |
| Windows x32 | ✓ | ✓ | ✓ | ✓ |
| Windows arm64 | ✓ | ✓ | ✓ | ✓ |
| macOS x64 | ✓ | ✓ | ✓ | ✓ |
| macOS arm64(m chip) | ✓ | ✓ | ✓ | ✓ |
| Linux x64 gnu | ✓ | ✓ | ✓ | ✓ |
| Linux x64 musl | ✓ | ✓ | ✓ | ✓ |
| Linux arm gnu | ✓ | ✓ | ✓ | ✓ |
| Linux arm64 gnu | ✓ | ✓ | ✓ | ✓ |
| Linux arm64 musl | ✓ | ✓ | ✓ | ✓ |
| Android arm64 | ✓ | ✓ | ✓ | ✓ |
| Android armv7 | ✓ | ✓ | ✓ | ✓ |
| FreeBSD x64 | ✓ | ✓ | ✓ | ✓ |

## API

```typescript
export const enum Algorithm {
Argon2d = 0,
Argon2i = 1,
Argon2id = 2,
}
export const enum Version {
V0x10 = 0,
V0x13 = 1,
}
export interface Options {
/**
* Memory size, expressed in kilobytes, between 1 and (2^32)-1.
* Value is an integer in decimal (1 to 10 digits).
*/
memoryCost?: number | undefined | null
/**
* Number of iterations, between 1 and (2^32)-1.
* Value is an integer in decimal (1 to 10 digits).
*/
timeCost?: number | undefined | null
/**
* Degree of parallelism, between 1 and 255.
* Value is an integer in decimal (1 to 3 digits).
*/
outputLen?: number | undefined | null
parallelism?: number | undefined | null
algorithm?: Algorithm | undefined | null
version?: Version | undefined | null
secret?: Buffer | undefined | null
}
export function hash(
password: string | Buffer,
options?: Options | undefined | null,
abortSignal?: AbortSignal | undefined | null,
): Promise<string>
export function verify(
hashed: string | Buffer,
password: string | Buffer,
options?: Options | undefined | null,
abortSignal?: AbortSignal | undefined | null,
): Promise<boolean>
```
49 changes: 49 additions & 0 deletions packages/argon2/__test__/argon2.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { randomBytes } from 'crypto'

import test from 'ava'

import { Algorithm, hash, verify, Version } from '../index.js'

test('should be able to hash string', async (t) => {
await t.notThrowsAsync(() => hash('whatever'))
await t.notThrowsAsync(() =>
hash('whatever', {
secret: randomBytes(32),
}),
)
})

test('should be able to verify hashed string', async (t) => {
const PASSWORD = 'Argon2_is_the_best_algorithm_ever'
t.true(await verify(await hash(PASSWORD), PASSWORD))
t.true(
await verify(
await hash(PASSWORD, {
algorithm: Algorithm.Argon2d,
}),
PASSWORD,
),
)
t.true(
await verify(
await hash(PASSWORD, {
algorithm: Algorithm.Argon2i,
}),
PASSWORD,
),
)
const secret = randomBytes(32)
t.true(
await verify(
await hash(PASSWORD, {
algorithm: Algorithm.Argon2d,
version: Version.V0x10,
secret,
}),
PASSWORD,
{
secret,
},
),
)
})
42 changes: 42 additions & 0 deletions packages/argon2/benchmark/argon2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const { cpus } = require('os')

const nodeArgon2 = require('argon2')
const { Suite } = require('benchmark')
const chalk = require('chalk')

const { hash, verify, Algorithm } = require('../index')

const PASSWORD = '$v=19$m=4096,t=3,p=1$fyLYvmzgpBjDTP6QSypj3g$pb1Q3Urv1amxuFft0rGwKfEuZPhURRDV7TJqcBnwlGo'
const CORES = cpus().length

const suite = new Suite('Hash with all cores')

suite
.add(
'@node-rs/argon',
async (deferred) => {
await hash(PASSWORD, {
algorithm: Algorithm.Argon2id,
parallelism: CORES,
})
deferred.resolve()
},
{ defer: true },
)
.add(
'node-argon',
async (deferred) => {
await nodeArgon2.hash(PASSWORD, { type: nodeArgon2.argon2id, parallelism: CORES })
deferred.resolve()
},
{
defer: true,
},
)
.on('cycle', function (event) {
console.info(String(event.target))
})
.on('complete', function () {
console.info(`${this.name} bench suite: Fastest is ${chalk.green(this.filter('fastest').map('name'))}`)
})
.run()
5 changes: 5 additions & 0 deletions packages/argon2/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
extern crate napi_build;

fn main() {
napi_build::setup();
}
52 changes: 52 additions & 0 deletions packages/argon2/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/* tslint:disable */
/* eslint-disable */

/* auto-generated by NAPI-RS */

export class ExternalObject<T> {
readonly '': {
readonly '': unique symbol
[K: symbol]: T
}
}
export const enum Algorithm {
Argon2d = 0,
Argon2i = 1,
Argon2id = 2,
}
export const enum Version {
V0x10 = 0,
V0x13 = 1,
}
export interface Options {
/**
* Memory size, expressed in kilobytes, between 1 and (2^32)-1.
* Value is an integer in decimal (1 to 10 digits).
*/
memoryCost?: number | undefined | null
/**
* Number of iterations, between 1 and (2^32)-1.
* Value is an integer in decimal (1 to 10 digits).
*/
timeCost?: number | undefined | null
/**
* Degree of parallelism, between 1 and 255.
* Value is an integer in decimal (1 to 3 digits).
*/
outputLen?: number | undefined | null
parallelism?: number | undefined | null
algorithm?: Algorithm | undefined | null
version?: Version | undefined | null
secret?: Buffer | undefined | null
}
export function hash(
password: string | Buffer,
options?: Options | undefined | null,
abortSignal?: AbortSignal | undefined | null,
): Promise<string>
export function verify(
hashed: string | Buffer,
password: string | Buffer,
options?: Options | undefined | null,
abortSignal?: AbortSignal | undefined | null,
): Promise<boolean>
Loading