From 3bfd04e45f1832023f0c8ced996e6fdbc35bf00c Mon Sep 17 00:00:00 2001 From: Ranieri Althoff Date: Mon, 17 Jul 2023 19:32:10 +0200 Subject: [PATCH] Run codacy action separate for each language --- .github/workflows/ci.yml | 17 --- README.md | 6 - argon2.mjs | 28 +++-- package.json | 2 +- test.js | 260 --------------------------------------- 5 files changed, 16 insertions(+), 297 deletions(-) delete mode 100644 test.js diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3230b6d..1efb8cd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,25 +37,8 @@ jobs: - name: Run tests with coverage if: matrix.node-version >= 20 - env: - NODE_V8_COVERAGE: coverage/tmp run: yarn test-coverage - - name: Generate coverage - if: matrix.node-version >= 20 && matrix.os == 'ubuntu-20.04' - run: | - sudo apt install lcov - npx c8 report --reporter=text-lcov > lcov-js.info - lcov -c -d . --no-external -o lcov-cpp.info - lcov -r lcov-cpp.info "*/node_modules/*" -o lcov-cpp.info - - - name: Send coverage to Codacy - if: matrix.node-version >= 20 && matrix.os == 'ubuntu-20.04' - uses: codacy/codacy-coverage-reporter-action@v1 - with: - coverage-reports: lcov-cpp.info, lcov-js.info - project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} - test-alpine: name: Test on Alpine Linux runs-on: ubuntu-latest diff --git a/README.md b/README.md index 795523b..95df047 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,6 @@ [![Financial contributors on Open Collective][opencollective-image]][opencollective-url] [![Build status][actions-image]][actions-url] [![NPM package][npm-image]][npm-url] -[![Coverage status][coverage-image]][coverage-url] -[![Code Quality][codequality-image]][codequality-url] Bindings to the reference [Argon2](https://github.com/P-H-C/phc-winner-argon2) implementation. @@ -212,7 +210,3 @@ license over Argon2 and the reference implementation. [npm-url]: https://www.npmjs.com/package/argon2 [actions-image]: https://img.shields.io/github/actions/workflow/status/ranisalt/node-argon2/ci.yml?branch=master&style=flat-square [actions-url]: https://github.com/ranisalt/node-argon2/actions -[coverage-image]: https://img.shields.io/codacy/coverage/3aa6daee00154e1492660ecb2f788f73/master.svg?style=flat-square -[coverage-url]: https://app.codacy.com/gh/ranisalt/node-argon2 -[codequality-image]: https://img.shields.io/codacy/grade/3aa6daee00154e1492660ecb2f788f73/master.svg?style=flat-square -[codequality-url]: https://app.codacy.com/gh/ranisalt/node-argon2 diff --git a/argon2.mjs b/argon2.mjs index af28b56..bc2a411 100644 --- a/argon2.mjs +++ b/argon2.mjs @@ -1,9 +1,9 @@ -"use strict"; -const assert = require("node:assert"); -const { randomBytes, timingSafeEqual } = require("node:crypto"); -const { promisify } = require("node:util"); -const { deserialize, serialize } = require("@phc/format"); -const gypBuild = require("node-gyp-build"); +import assert from "node:assert"; +import { randomBytes, timingSafeEqual } from "node:crypto"; +import { fileURLToPath } from "node:url"; +import { promisify } from "node:util"; +import { deserialize, serialize } from "@phc/format"; +import gypBuild from "node-gyp-build"; const { hash: _hash } = gypBuild(fileURLToPath(new URL(".", import.meta.url))); @@ -12,8 +12,12 @@ const bindingsHash = promisify(_hash); /** @type {(size: number) => Promise} */ const generateSalt = promisify(randomBytes); -/** @enum {0 | 1 | 2} */ -const types = Object.freeze({ argon2d: 0, argon2i: 1, argon2id: 2 }); +export const argon2d = 0; +export const argon2i = 1; +export const argon2id = 2; + +/** @enum {argon2i | argon2d | argon2id} */ +const types = Object.freeze({ argon2d, argon2i, argon2id }); /** @enum {'argon2d' | 'argon2i' | 'argon2id'} */ const names = Object.freeze({ @@ -74,7 +78,7 @@ export const limits = Object.freeze({ * @param {Options & { raw?: boolean }} options * @returns {Promise} */ -async function hash(plain, options) { +export async function hash(plain, options) { const { raw, salt, saltLength, ...rest } = { ...defaults, ...options }; for (const [key, { min, max }] of Object.entries(limits)) { @@ -115,7 +119,7 @@ async function hash(plain, options) { * @param {Options} [options] The current parameters for Argon2 * @return {boolean} `true` if the digest parameters do not match the parameters in `options`, otherwise `false` */ -function needsRehash(digest, options) { +export function needsRehash(digest, options) { const { memoryCost, timeCost, version } = { ...defaults, ...options }; const { @@ -132,7 +136,7 @@ function needsRehash(digest, options) { * @param {Options} [options] The current parameters for Argon2 * @return {Promise} `true` if the digest parameters matches the hash generated from `plain`, otherwise `false` */ -async function verify(digest, plain, options) { +export async function verify(digest, plain, options) { const { id, version = 0x10, @@ -160,5 +164,3 @@ async function verify(digest, plain, options) { ) ); } - -module.exports = { defaults, hash, needsRehash, verify, ...types }; diff --git a/package.json b/package.json index adff687..df2a505 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ }, "scripts": { "build": "prebuildify --napi --strip --tag-armv --tag-libc", - "format": "prettier --write \"*.{js,json}\"", + "format": "prettier --write \"*.{json,mjs}\"", "install": "node-gyp-build", "prepack": "yarn prepare", "prepare": "tsc", diff --git a/test.js b/test.js deleted file mode 100644 index dc89cbe..0000000 --- a/test.js +++ /dev/null @@ -1,260 +0,0 @@ -// @ts-check -const assert = require("node:assert/strict"); -const { describe, it } = require("node:test"); -const argon2 = require("./argon2.js"); - -const { argon2i, argon2d, argon2id } = argon2; -const password = "password"; -const salt = Buffer.alloc(16, "salt"); -const associatedData = Buffer.alloc(16, "ad"); -const secret = Buffer.alloc(16, "secret"); - -// hashes for argon2i and argon2d with default options -const hashes = Object.freeze({ - argon2id: - "$argon2id$v=19$m=65536,t=3,p=4$c2FsdHNhbHRzYWx0c2FsdA$rBWULD5jOGpQy32rLvGcmvQMVqIVNAmrCtekWvUA8bw", - withNull: - "$argon2id$v=19$m=65536,t=3,p=4$c2FsdHNhbHRzYWx0c2FsdA$NqchDOxwWbcBzA+0gtsCtyspEQxqKFf4/PO/AoIvo+Q", - withAd: - "$argon2id$v=19$m=65536,t=3,p=4,data=YWRhZGFkYWRhZGFkYWRhZA$c2FsdHNhbHRzYWx0c2FsdA$TEIIM4GBSUxvMLolL9ePXYP5G/qcr0vywQqqm/ILvsM", - withSecret: - "$argon2id$v=19$m=65536,t=3,p=4$c2FsdHNhbHRzYWx0c2FsdA$8dZyo1MdHgdzBm+VU7+tyW06dUO7B9FyaPImH5ejVOU", - argon2i: - "$argon2i$v=19$m=65536,t=3,p=4$c2FsdHNhbHRzYWx0c2FsdA$1Ccmp7ECb+Rb5XPjqRwEuAjCufY1xQDOJwnHrB+orZ4", - argon2d: - "$argon2d$v=19$m=65536,t=3,p=4$c2FsdHNhbHRzYWx0c2FsdA$VtxJNl5Jr/yZ2UIhvfvL4sGPdDQyGCcy45Cs7rIdFq8", - rawArgon2id: Buffer.from( - "ac15942c3e63386a50cb7dab2ef19c9af40c56a2153409ab0ad7a45af500f1bc", - "hex", - ), - rawWithNull: Buffer.from( - "36a7210cec7059b701cc0fb482db02b72b29110c6a2857f8fcf3bf02822fa3e4", - "hex", - ), - rawArgon2i: Buffer.from( - "d42726a7b1026fe45be573e3a91c04b808c2b9f635c500ce2709c7ac1fa8ad9e", - "hex", - ), - rawArgon2d: Buffer.from( - "56dc49365e49affc99d94221bdfbcbe2c18f743432182732e390aceeb21d16af", - "hex", - ), - oldFormat: - "$argon2i$m=4096,t=3,p=1$tbagT6b1YH33niCo9lVzuA$htv/k+OqWk1V9zD9k5DOBi2kcfcZ6Xu3tWmwEPV3/nc", -}); - -describe("hash", () => { - it("hash with argon2i", async () => { - const hash = await argon2.hash(password, { type: argon2i, salt }); - assert.equal(hashes.argon2i, hash); - }); - - it("argon2i with raw hash", async () => { - const hash = await argon2.hash(password, { - type: argon2i, - raw: true, - salt, - }); - assert(hashes.rawArgon2i.equals(hash)); - }); - - it("hash with argon2d", async () => { - const hash = await argon2.hash(password, { type: argon2d, salt }); - assert.equal(hashes.argon2d, hash); - }); - - it("argon2d with raw hash", async () => { - const hash = await argon2.hash(password, { - type: argon2d, - raw: true, - salt, - }); - assert(hashes.rawArgon2d.equals(hash)); - }); - - it("hash with argon2id", async () => { - const hash = await argon2.hash(password, { type: argon2id, salt }); - assert.equal(hashes.argon2id, hash); - }); - - it("argon2id with raw hash", async () => { - const hash = await argon2.hash(password, { - type: argon2id, - raw: true, - salt, - }); - assert(hashes.rawArgon2id.equals(hash)); - }); - - it("with null in password", async () => { - const hash = await argon2.hash("pass\0word", { salt }); - assert.equal(hashes.withNull, hash); - }); - - it("with raw hash, null in password", async () => { - const hash = await argon2.hash("pass\0word", { raw: true, salt }); - assert(hashes.rawWithNull.equals(hash)); - }); - - it("with associated data", async () => { - const hash = await argon2.hash(password, { associatedData, salt }); - assert.equal(hashes.withAd, hash); - }); - - it("with secret", async () => { - const hash = await argon2.hash(password, { secret, salt }); - assert.equal(hashes.withSecret, hash); - }); -}); - -describe("set options", () => { - it("hash with time cost", async () => { - const hash = await argon2.hash(password, { timeCost: 4 }); - assert.match(hash, /t=4/); - }); - - it("hash with low time cost", async () => { - await assert.rejects(argon2.hash(password, { timeCost: 1 }), { - message: /invalid timeCost.+between \d+ and \d+/i, - }); - }); - - it("hash with high time cost", async () => { - await assert.rejects(argon2.hash(password, { timeCost: 2 ** 32 }), { - message: /invalid timeCost.+between \d+ and \d+/i, - }); - }); - - it("hash with hash length", async () => { - // 4 bytes ascii == 6 bytes base64 - const hash = await argon2.hash(password, { hashLength: 4 }); - assert.match(hash, /\$[^$]{6}$/); - }); - - it("hash with low hash length", async () => { - await assert.rejects(argon2.hash(password, { hashLength: 3 }), { - message: /invalid hashLength.+between \d+ and \d+/i, - }); - }); - - it("hash with high hash length", async () => { - await assert.rejects(argon2.hash(password, { hashLength: 2 ** 32 }), { - message: /invalid hashLength.+between \d+ and \d+/i, - }); - }); - - it("hash with memory cost", async () => { - const hash = await argon2.hash(password, { memoryCost: 8192 }); - assert.match(hash, /m=8192/); - }); - - it("hash with low memory cost", async () => { - await assert.rejects(argon2.hash(password, { memoryCost: 2 ** 9 }), { - message: /invalid memoryCost.+between \d+ and \d+/i, - }); - }); - - it("hash with high memory cost", async () => { - await assert.rejects(argon2.hash(password, { memoryCost: 2 ** 9 }), { - message: /invalid memoryCost.+between \d+ and \d+/i, - }); - }); - - it("hash with parallelism", async () => { - const hash = await argon2.hash(password, { parallelism: 2 }); - assert.match(hash, /p=2/); - }); - - it("hash with low parallelism", async () => { - await assert.rejects(argon2.hash(password, { parallelism: 0 }), { - message: /invalid parallelism.+between \d+ and \d+/i, - }); - }); - - it("hash with high parallelism", async () => { - await assert.rejects(argon2.hash(password, { parallelism: 2 ** 24 }), { - message: /invalid parallelism.+between \d+ and \d+/i, - }); - }); - - it("hash with all options", async () => { - const hash = await argon2.hash(password, { - timeCost: 4, - memoryCost: 8192, - parallelism: 2, - }); - assert.match(hash, /m=8192,t=4,p=2/); - }); -}); - -describe("needsRehash", () => { - it("needs rehash old version", async () => { - const hash = await argon2.hash(password, { version: 0x10 }); - assert(argon2.needsRehash(hash)); - assert(!argon2.needsRehash(hash, { version: 0x10 })); - }); - - it("needs rehash low memory cost", async () => { - const hash = await argon2.hash(password, { memoryCost: 2 ** 15 }); - assert(argon2.needsRehash(hash)); - assert(!argon2.needsRehash(hash, { memoryCost: 2 ** 15 })); - }); - - it("needs rehash low time cost", async () => { - const hash = await argon2.hash(password, { timeCost: 2 }); - assert(argon2.needsRehash(hash)); - assert(!argon2.needsRehash(hash, { timeCost: 2 })); - }); -}); - -describe("verify", () => { - it("verify correct password", async () => { - const hash = await argon2.hash(password); - assert(await argon2.verify(hash, password)); - }); - - it("verify wrong password", async () => { - const hash = await argon2.hash(password); - assert(!(await argon2.verify(hash, "passworld"))); - }); - - it("verify with null in password", async () => { - const hash = await argon2.hash("pass\0word"); - assert(await argon2.verify(hash, "pass\0word")); - }); - - it("verify with associated data", async () => { - const hash = await argon2.hash(password, { associatedData }); - assert(await argon2.verify(hash, "password")); - }); - - it("verify with secret", async () => { - const hash = await argon2.hash(password, { secret }); - assert(await argon2.verify(hash, "password", { secret })); - }); - - it("verify argon2d correct password", async () => { - const hash = await argon2.hash(password, { type: argon2d }); - assert(await argon2.verify(hash, password)); - }); - - it("verify argon2d wrong password", async () => { - const hash = await argon2.hash(password, { type: argon2d }); - assert(!(await argon2.verify(hash, "passworld"))); - }); - - it("verify argon2id correct password", async () => { - const hash = await argon2.hash(password, { type: argon2id }); - assert(await argon2.verify(hash, password)); - }); - - it("verify argon2id wrong password", async () => { - const hash = await argon2.hash(password, { type: argon2id }); - assert(!(await argon2.verify(hash, "passworld"))); - }); - - it("verify old hash format", async () => { - // older hashes did not contain the v (version) parameter - assert(await argon2.verify(hashes.oldFormat, "password")); - }); -});