diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..ec369b7 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,32 @@ +{ + "parser": "@typescript-eslint/parser", + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" // uses the recommended rules from the @typescript-eslint/eslint-plugin + ], + "parserOptions": { + "ecmaVersion": 2018, + "sourceType": "module" + }, + "ignorePatterns": [ + "bin/", + "lib/", + "jsbn" + ], + "rules": { + "quotes": ["error", "double"], + "indent": ["error", 2, { "SwitchCase": 1 }], + "linebreak-style": ["error", "unix"], + "semi": ["error", "always"], + + "comma-dangle": ["error", "always-multiline"], + "dot-notation": "error", + "eqeqeq": "error", + "curly": ["error", "all"], + "brace-style": ["error"], + + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/camelcase": "off" + } +} diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 1a489f6..7ce864f 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -23,11 +23,20 @@ jobs: uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - - name: npm install, build and test - run: | - npm ci - npm run build --if-present - npm test + - name: Run npm ci + run: npm ci + env: + CI: true + - name: Run npm build + run: npm build + env: + CI: true + - name: Run npm lint + run: npm lint + env: + CI: true + - name: Run npm test + run: npm test env: CI: true diff --git a/README.md b/README.md index 26c9394..4ffc0c3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -fast-srp +fast-srp-hap === Is a pure [NodeJS](https://nodejs.org/) implementation of the [SRP6a protocol](http://srp.stanford.edu/). diff --git a/jsbn/jsbn.d.ts b/jsbn/jsbn.d.ts index 2f03838..8e19bbb 100644 --- a/jsbn/jsbn.d.ts +++ b/jsbn/jsbn.d.ts @@ -1,23 +1,23 @@ declare class BigInteger { - constructor(number: number | string, base?: number); - constructor(number: Buffer); - constructor(number: unknown); + constructor(number: number | string, base?: number); + constructor(number: Buffer); + constructor(number: unknown); - toString(base?: number): string; - toBuffer(trimOrSize?: true | number): Buffer; + toString(base?: number): string; + toBuffer(trimOrSize?: true | number): Buffer; - /** @return {number} 1 if this > a, -1 if this < a, 0 if equal */ - compareTo(a: BigInteger): -1 | 0 | 1; - - multiply(b: BigInteger): BigInteger; - - add(b: BigInteger | number): BigInteger; - subtract(b: BigInteger): BigInteger; - - modPow(b: BigInteger, N: BigInteger): BigInteger; - mod(b: BigInteger): BigInteger; + /** @return {number} 1 if this > a, -1 if this < a, 0 if equal */ + compareTo(a: BigInteger): -1 | 0 | 1; - bitLength(): number; + multiply(b: BigInteger): BigInteger; + + add(b: BigInteger | number): BigInteger; + subtract(b: BigInteger): BigInteger; + + modPow(b: BigInteger, N: BigInteger): BigInteger; + mod(b: BigInteger): BigInteger; + + bitLength(): number; } export = BigInteger; diff --git a/package-lock.json b/package-lock.json index fa78037..677f8a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,12 +4,194 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", + "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", + "dev": true + }, + "@babel/highlight": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", + "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.9.0", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "@types/eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", + "integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==", + "dev": true + }, "@types/node": { "version": "10.17.19", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.19.tgz", "integrity": "sha512-46/xThm3zvvc9t9/7M3AaLEqtOpqlYYYcCZbpYVAQHG20+oMZBkae/VMrn4BTi6AJ8cpack0mEXhGiKmDNbLrQ==", "dev": true }, + "@typescript-eslint/eslint-plugin": { + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.27.0.tgz", + "integrity": "sha512-/my+vVHRN7zYgcp0n4z5A6HAK7bvKGBiswaM5zIlOQczsxj/aiD7RcgD+dvVFuwFaGh5+kM7XA6Q6PN0bvb1tw==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "2.27.0", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.0.0", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/experimental-utils": { + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.27.0.tgz", + "integrity": "sha512-vOsYzjwJlY6E0NJRXPTeCGqjv5OHgRU1kzxHKWJVPjDYGbPgLudBXjIlc+OD1hDBZ4l1DLbOc5VjofKahsu9Jw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/typescript-estree": "2.27.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + } + }, + "@typescript-eslint/parser": { + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.27.0.tgz", + "integrity": "sha512-HFUXZY+EdwrJXZo31DW4IS1ujQW3krzlRjBrFRrJcMDh0zCu107/nRfhk/uBasO8m0NVDbBF5WZKcIUMRO7vPg==", + "dev": true, + "requires": { + "@types/eslint-visitor-keys": "^1.0.0", + "@typescript-eslint/experimental-utils": "2.27.0", + "@typescript-eslint/typescript-estree": "2.27.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "@typescript-eslint/typescript-estree": { + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.27.0.tgz", + "integrity": "sha512-t2miCCJIb/FU8yArjAvxllxbTiyNqaXJag7UOpB5DVoM3+xnjeOngtqlJkLRnMtzaRcJhe3CIR9RmL40omubhg==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^6.3.0", + "tsutils": "^3.17.1" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "acorn": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", + "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", + "dev": true + }, + "acorn-jsx": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", + "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", + "dev": true + }, + "ajv": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", + "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-escapes": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "dev": true, + "requires": { + "type-fest": "^0.11.0" + }, + "dependencies": { + "type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true + } + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -26,30 +208,352 @@ "concat-map": "0.0.1" } }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, "diff": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==", "dev": true }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", + "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.3", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + } + } + }, + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz", + "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, + "espree": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", + "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.2.0.tgz", + "integrity": "sha512-weltsSqdeWIX9G2qQZz7KlTRJdkkOCTPgLYJUz1Hacf48R4YOwGPHO3+ORfWedqJKbq5WQmsgK90n+pFLIKt/Q==", + "dev": true, + "requires": { + "estraverse": "^5.0.0" + }, + "dependencies": { + "estraverse": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.0.0.tgz", + "integrity": "sha512-j3acdrMzqrxmJTNj5dbr1YbjacrYgAxVMeF0gK16E3j494mOe7xygM/ZLIguEQ0ETwAg2hlJCtHRGav+y0Ny5A==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, "eyes": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=", "dev": true }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "glob": { "version": "7.1.5", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz", @@ -64,6 +568,61 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -80,6 +639,171 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "inquirer": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", + "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^3.0.0", + "cli-cursor": "^3.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.15", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.5.3", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -89,6 +813,45 @@ "brace-expansion": "^1.1.7" } }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -98,18 +861,344 @@ "wrappy": "1" } }, + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-async": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.0.tgz", + "integrity": "sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg==", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, + "rxjs": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", + "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } + } + }, + "strip-json-comments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz", + "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "tslib": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", + "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==", + "dev": true + }, + "tsutils": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", + "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, "typescript": { "version": "3.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", "dev": true }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "v8-compile-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "dev": true + }, "vows": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/vows/-/vows-0.8.3.tgz", @@ -121,11 +1210,35 @@ "glob": "^7.1.2" } }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } } } } diff --git a/package.json b/package.json index b631b22..25d6fd8 100644 --- a/package.json +++ b/package.json @@ -5,10 +5,11 @@ "main": "lib/srp.js", "scripts": { "clean": "rm -rf lib", + "lint": "eslint 'src/**/*.{js,ts,json}'", "build": "npm run clean && tsc", + "test": "vows lib/test/test_*.js --spec", "prepublishOnly": "npm run build", - "postpublish": "npm run clean", - "test": "vows lib/test/test_*.js --spec" + "postpublish": "npm run clean" }, "repository": { "type": "git", @@ -30,6 +31,9 @@ "devDependencies": { "@types/node": "^10.17.19", "typescript": "^3.8.3", - "vows": "^0.8.3" + "vows": "^0.8.3", + "eslint": "^6.8.0", + "@typescript-eslint/parser": "^2.27.0", + "@typescript-eslint/eslint-plugin": "^2.27.0" } } diff --git a/src/params.ts b/src/params.ts index 1e824ab..001b9c1 100644 --- a/src/params.ts +++ b/src/params.ts @@ -14,10 +14,10 @@ // since these are meant to be used internally, all values are numbers. If // you want to add parameter sets, you'll need to convert them to bignums. -import BigInteger = require('../jsbn/jsbn'); +import BigInteger = require("../jsbn/jsbn"); -export function hex(s: string) { - return new BigInteger(s.split(/\s|\n/).join(''), 16); +export function hex(s: string): BigInteger { + return new BigInteger(s.split(/\s|\n/).join(""), 16); } export interface SrpParams { @@ -37,8 +37,8 @@ export const params = { 7BCF1885 C529F566 660E57EC 68EDBC3C 05726CC0 2FD4CBF4 976EAA9A FD5138FE 8376435B 9FC61D2F C0EB06E3 `), - g: hex('02'), - hash: 'sha1', + g: hex("02"), + hash: "sha1", }, 1536: { @@ -52,8 +52,8 @@ export const params = { F7CCB7AE 837C264A E3A9BEB8 7F8A2FE9 B8B5292E 5A021FFF 5E91479E 8CE7A28C 2442C6F3 15180F93 499A234D CF76E3FE D135F9BB `), - g: hex('02'), - hash: 'sha1', + g: hex("02"), + hash: "sha1", }, 2048: { @@ -70,8 +70,8 @@ export const params = { 94B5C803 D89F7AE4 35DE236D 525F5475 9B65E372 FCD68EF2 0FA7111F 9E4AFF73 `), - g: hex('02'), - hash: 'sha256', + g: hex("02"), + hash: "sha256", }, 3072: { @@ -92,8 +92,8 @@ export const params = { BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF `), - g: hex('05'), - hash: 'sha256', + g: hex("05"), + hash: "sha256", }, hap: { @@ -114,8 +114,8 @@ export const params = { BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF `), - g: hex('05'), - hash: 'sha512', + g: hex("05"), + hash: "sha512", }, 4096: { @@ -141,8 +141,8 @@ export const params = { D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34063199 FFFFFFFF FFFFFFFF `), - g: hex('05'), - hash: 'sha256', + g: hex("05"), + hash: "sha256", }, 6244: { @@ -177,8 +177,8 @@ export const params = { 387FE8D7 6E3C0468 043E8F66 3F4860EE 12BF2D5B 0B7474D6 E694F91E 6DCC4024 FFFFFFFF FFFFFFFF `), - g: hex('05'), - hash: 'sha256', + g: hex("05"), + hash: "sha256", }, 8192: { @@ -222,8 +222,8 @@ export const params = { FC026E47 9558E447 5677E9AA 9E3050E2 765694DF C81F56E8 80B96E71 60C980DD 98EDD3DF FFFFFFFF FFFFFFFF `), - g: hex('13'), - hash: 'sha256', + g: hex("13"), + hash: "sha256", }, }; diff --git a/src/srp.ts b/src/srp.ts index da05f71..c6f92b5 100644 --- a/src/srp.ts +++ b/src/srp.ts @@ -1,15 +1,24 @@ -import crypto from 'crypto'; -import assert from 'assert'; -import BigInteger = require('../jsbn/jsbn'); -import {SrpParams, params as srpParams} from './params'; +import crypto from "crypto"; +import assert from "assert"; +import BigInteger = require("../jsbn/jsbn"); +import { SrpParams, params as srpParams } from "./params"; -export { SrpParams } from './params'; +export { SrpParams } from "./params"; const zero = new BigInteger(0, 10); -function assert_(val: any, msg: string) { - if (!val) - throw new Error(msg || 'assertion'); +function assert_(val: V, msg: string): void{ + if (!val) { + throw new Error(msg || "assertion"); + } +} + +function assertIsBuffer(arg: Buffer, argname = "arg"): void { + assert_(Buffer.isBuffer(arg), `Type error: ${argname} must be a buffer`); +} + +function assertIsBigInteger(arg: BigInteger, argname?: string): void { + assert_(arg.constructor.name === "BigInteger", `Type error: ${argname} must be a BigInteger`); } /** @@ -22,30 +31,21 @@ function assert_(val: any, msg: string) { * @param {number} len Length of the resulting Buffer * @return {Buffer} */ -function padTo(n: Buffer, len: number) { - assertIsBuffer(n, 'n'); +function padTo(n: Buffer, len: number): Buffer { + assertIsBuffer(n, "n"); const padding = len - n.length; - assert_(padding > -1, 'Negative padding. Very uncomfortable.'); + assert_(padding > -1, "Negative padding. Very uncomfortable."); const result = Buffer.alloc(len); result.fill(0, 0, padding); n.copy(result, padding); - assert.equal(result.length, len); + assert.strictEqual(result.length, len); return result; } -function padToN(number: BigInteger, params: SrpParams) { +function padToN(number: BigInteger, params: SrpParams): Buffer { assertIsBigInteger(number); - const n = number.toString(16).length % 2 != 0 ? '0' + number.toString(16) : number.toString(16); - return padTo(Buffer.from(n, 'hex'), params.N_length_bits / 8); -} - -function assertIsBuffer(arg: Buffer, argname: string, ___?: any) { - argname = argname || 'arg'; - assert_(Buffer.isBuffer(arg), `Type error: ${argname} must be a buffer`); -} - -function assertIsBigInteger(arg: BigInteger, argname?: string) { - assert_(arg.constructor.name === 'BigInteger', `Type error: ${argname} must be a BigInteger`); + const n = number.toString(16).length % 2 !== 0 ? "0" + number.toString(16) : number.toString(16); + return padTo(Buffer.from(n, "hex"), params.N_length_bits / 8); } /** @@ -60,12 +60,12 @@ function assertIsBigInteger(arg: BigInteger, argname?: string) { * @param {Buffer} P User password * @return {BigInteger} User secret */ -function getx(params: SrpParams, salt: Buffer, I: Buffer, P: Buffer) { - assertIsBuffer(salt, 'salt (salt)'); - assertIsBuffer(I, 'identity (I)'); - assertIsBuffer(P, 'password (P)'); +function getx(params: SrpParams, salt: Buffer, I: Buffer, P: Buffer): BigInteger { + assertIsBuffer(salt, "salt (salt)"); + assertIsBuffer(I, "identity (I)"); + assertIsBuffer(P, "password (P)"); const hashIP = crypto.createHash(params.hash) - .update(Buffer.concat([I, Buffer.from(':'), P])) + .update(Buffer.concat([I, Buffer.from(":"), P])) .digest(); const hashX: Buffer = crypto.createHash(params.hash) .update(salt) @@ -97,13 +97,18 @@ export class SRP { * @return {Buffer} */ public static computeVerifier(params: SrpParams, salt: Buffer, I: Buffer, P: Buffer): Buffer { - assertIsBuffer(salt, 'salt (salt)'); - assertIsBuffer(I, 'identity (I)'); - assertIsBuffer(P, 'password (P)'); + assertIsBuffer(salt, "salt (salt)"); + assertIsBuffer(I, "identity (I)"); + assertIsBuffer(P, "password (P)"); + // eslint-disable-next-line @typescript-eslint/camelcase const v_num = params.g.modPow(getx(params, salt, I, P), params.N); return v_num.toBuffer(params.N_length_bits / 8); } + + public static genKey(callback: GenKeyCallback): void; + public static genKey(bytes: number, callback: GenKeyCallback): void; + public static genKey(bytes?: number): Promise; /** * Generate a random key. * @@ -111,20 +116,21 @@ export class SRP { * @param {function} [callback] If not provided a Promise is returned * @return {Promise|void} */ - public static genKey(callback: GenKeyCallback): void; - public static genKey(bytes: number, callback: GenKeyCallback): void; - public static genKey(bytes?: number): Promise; public static genKey(bytes: number | GenKeyCallback = 32, callback?: GenKeyCallback): Promise | void { // bytes is optional - if (typeof bytes !== 'number') { + if (typeof bytes !== "number") { callback = bytes as unknown as GenKeyCallback; bytes = 32; } - if (!callback) return new Promise((rs, rj) => SRP.genKey(bytes as number, (err, data) => err ? rj(err) : rs(data!))); + if (!callback) { + return new Promise((rs, rj) => SRP.genKey(bytes as number, (err, data) => err ? rj(err) : rs(data!))); + } crypto.randomBytes(bytes, (err, buf) => { - if (err) return callback!(err, null); + if (err) { + return callback!(err, null); + } return callback!(null, buf); }); } @@ -137,7 +143,7 @@ export class SRP { * @param {object} params Group parameters, with .N, .g, .hash * @return {BigInteger} */ -function getk(params: SrpParams) { +function getk(params: SrpParams): BigInteger { const k_buf = crypto .createHash(params.hash) .update(padToN(params.N, params)) @@ -161,7 +167,7 @@ function getk(params: SrpParams) { * @param {BigInteger} b Server secret exponent * @return {Buffer} B - The server public message */ -function getB(params: SrpParams, k: BigInteger, v: BigInteger, b: BigInteger) { +function getB(params: SrpParams, k: BigInteger, v: BigInteger, b: BigInteger): Buffer { assertIsBigInteger(v); assertIsBigInteger(k); assertIsBigInteger(b); @@ -178,12 +184,12 @@ function getB(params: SrpParams, k: BigInteger, v: BigInteger, b: BigInteger) { * * @param {object} params Group parameters, with .N, .g, .hash * @param {BigInteger} a_num Client secret exponent - * @return {BigInteger} A - The client public message + * @return {Buffer} A - The client public message */ -function getA(params: SrpParams, a_num: BigInteger) { +function getA(params: SrpParams, a_num: BigInteger): Buffer { assertIsBigInteger(a_num); if (Math.ceil(a_num.toString(16).length / 2) < 32) { - console.warn('getA: client key length %d is less than the recommended 256 bits', a_num.bitLength()); + console.warn("getA: client key length %d is less than the recommended 256 bits", a_num.bitLength()); } return params.g.modPow(a_num, params.N).toBuffer(params.N_length_bits / 8); } @@ -200,9 +206,9 @@ function getA(params: SrpParams, a_num: BigInteger) { * @param {Buffer} B Server ephemeral public key * @return {BigInteger} u - Shared scrambling parameter */ -function getu(params: SrpParams, A: Buffer, B: Buffer) { - assertIsBuffer(A, 'A'); - assertIsBuffer(B, 'B'); +function getu(params: SrpParams, A: Buffer, B: Buffer): BigInteger { + assertIsBuffer(A, "A"); + assertIsBuffer(B, "B"); const u_buf = crypto.createHash(params.hash) .update(padTo(A, params.N_length_bits / 8)) .update(padTo(B, params.N_length_bits / 8)) @@ -213,22 +219,23 @@ function getu(params: SrpParams, A: Buffer, B: Buffer) { /** * The TLS premaster secret as calculated by the client * - * @param {object} params Group parameters, with .N, .g, .hash - * @param {Buffer} salt Salt (read from server) - * @param {Buffer} I User identity (read from user) - * @param {Buffer} P User password (read from user) - * @param {BigInteger} a Ephemeral private key (generated for session) - * @param {BigInteger} B Server ephemeral public key (read from server) + * @param {SrpParams} params Group parameters, with .N, .g, .hash + * @param {BigInteger} k_num + * @param {BigInteger} x_num + * @param {BigInteger} a_num + * @param {BigInteger} B_num + * @param {BigInteger} u_num * @return {Buffer} */ -function client_getS(params: SrpParams, k_num: BigInteger, x_num: BigInteger, a_num: BigInteger, B_num: BigInteger, u_num: BigInteger) { +function client_getS(params: SrpParams, k_num: BigInteger, x_num: BigInteger, a_num: BigInteger, B_num: BigInteger, u_num: BigInteger): Buffer { assertIsBigInteger(k_num); assertIsBigInteger(x_num); assertIsBigInteger(a_num); assertIsBigInteger(B_num); assertIsBigInteger(u_num); - if ((zero.compareTo(B_num) >= 0) || (params.N.compareTo(B_num) <= 0)) - throw new Error('invalid server-supplied "B", must be 1..N-1'); + if ((zero.compareTo(B_num) >= 0) || (params.N.compareTo(B_num) <= 0)) { + throw new Error("invalid server-supplied \"B\", must be 1..N-1"); + } const S_num = B_num.subtract(k_num.multiply(params.g.modPow(x_num, params.N))) .modPow(a_num.add(u_num.multiply(x_num)), params.N) @@ -246,13 +253,14 @@ function client_getS(params: SrpParams, k_num: BigInteger, x_num: BigInteger, a_ * @param {BigInteger} u_num {@see getu} * @return {Buffer} */ -function server_getS(params: SrpParams, v_num: BigInteger, A_num: BigInteger, b_num: BigInteger, u_num: BigInteger) { +function server_getS(params: SrpParams, v_num: BigInteger, A_num: BigInteger, b_num: BigInteger, u_num: BigInteger): Buffer { assertIsBigInteger(v_num); assertIsBigInteger(A_num); assertIsBigInteger(b_num); assertIsBigInteger(u_num); - if ((zero.compareTo(A_num) >= 0) || (params.N.compareTo(A_num) <= 0)) - throw new Error('invalid client-supplied "A", must be 1..N-1'); + if ((zero.compareTo(A_num) >= 0) || (params.N.compareTo(A_num) <= 0)) { + throw new Error("invalid client-supplied \"A\", must be 1..N-1"); + } const S_num = A_num.multiply(v_num.modPow(u_num, params.N)) .modPow(b_num, params.N) @@ -267,13 +275,13 @@ function server_getS(params: SrpParams, v_num: BigInteger, A_num: BigInteger, b_ * @param {Buffer} S_buf Session key * @return {Buffer} */ -function getK(params: SrpParams, S_buf: Buffer) { - assertIsBuffer(S_buf, 'S'); - if (params.hash === 'sha1') { +function getK(params: SrpParams, S_buf: Buffer): Buffer { + assertIsBuffer(S_buf, "S"); + if (params.hash === "sha1") { // use t_mgf1 interleave for short sha1 hashes return Buffer.concat([ crypto.createHash(params.hash).update(S_buf).update(Buffer.from([0,0,0,0])).digest(), - crypto.createHash(params.hash).update(S_buf).update(Buffer.from([0,0,0,1])).digest() + crypto.createHash(params.hash).update(S_buf).update(Buffer.from([0,0,0,1])).digest(), ]); } else { // use hash as-is otherwise @@ -292,19 +300,20 @@ function getK(params: SrpParams, S_buf: Buffer) { */ function getM1(params: SrpParams, u_buf: Buffer, s_buf: Buffer, A_buf: Buffer, B_buf: Buffer, K_buf: Buffer): Buffer function getM1(params: SrpParams, A_buf: Buffer, B_buf: Buffer, K_buf: Buffer): Buffer -function getM1(params: SrpParams, u_buf: Buffer, s_buf: Buffer, A_buf: Buffer, B_buf?: Buffer, K_buf?: Buffer) { +function getM1(params: SrpParams, u_buf: Buffer, s_buf: Buffer, A_buf: Buffer, B_buf?: Buffer, K_buf?: Buffer): Buffer { if (arguments.length > 4) { - assertIsBuffer(u_buf, 'identity (I)'); - assertIsBuffer(s_buf, 'salt (s)') - assertIsBuffer(A_buf, 'client public key (A)'); - assertIsBuffer(B_buf!, 'server public key (B)'); - assertIsBuffer(K_buf!, 'session key (K)'); + assertIsBuffer(u_buf, "identity (I)"); + assertIsBuffer(s_buf, "salt (s)"); + assertIsBuffer(A_buf, "client public key (A)"); + assertIsBuffer(B_buf!, "server public key (B)"); + assertIsBuffer(K_buf!, "session key (K)"); const hN = crypto.createHash(params.hash).update(params.N.toBuffer(true)).digest(); const hG = crypto.createHash(params.hash).update(params.g.toBuffer(true)).digest(); - for (let i = 0; i < hN.length; i++) + for (let i = 0; i < hN.length; i++) { hN[i] ^= hG[i]; + } const hU = crypto.createHash(params.hash).update(u_buf).digest(); @@ -315,9 +324,9 @@ function getM1(params: SrpParams, u_buf: Buffer, s_buf: Buffer, A_buf: Buffer, B } else { [A_buf, B_buf, s_buf] = [u_buf, s_buf, A_buf]; - assertIsBuffer(A_buf, 'A'); - assertIsBuffer(B_buf, 'B'); - assertIsBuffer(s_buf, 'S'); + assertIsBuffer(A_buf, "A"); + assertIsBuffer(B_buf, "B"); + assertIsBuffer(s_buf, "S"); return crypto.createHash(params.hash) .update(A_buf).update(B_buf).update(s_buf) @@ -325,20 +334,20 @@ function getM1(params: SrpParams, u_buf: Buffer, s_buf: Buffer, A_buf: Buffer, B } } -function getM2(params: SrpParams, A_buf: Buffer, M1_buf: Buffer, K_buf: Buffer) { - assertIsBuffer(A_buf, 'A'); - assertIsBuffer(M1_buf, 'M1'); - assertIsBuffer(K_buf, 'K'); +function getM2(params: SrpParams, A_buf: Buffer, M1_buf: Buffer, K_buf: Buffer): Buffer { + assertIsBuffer(A_buf, "A"); + assertIsBuffer(M1_buf, "M1"); + assertIsBuffer(K_buf, "K"); return crypto.createHash(params.hash) .update(A_buf).update(M1_buf).update(K_buf) .digest(); } -function equal(buf1: Buffer, buf2: Buffer) { +function equal(buf1: Buffer, buf2: Buffer): boolean { // constant-time comparison. A drop in the ocean compared to our // non-constant-time modexp operations, but still good practice. - return buf1.toString('hex') === buf2.toString('hex'); + return buf1.toString("hex") === buf2.toString("hex"); } export class SrpClient { @@ -376,12 +385,13 @@ export class SrpClient { * @param {Buffer} identity_buf Identity/username * @param {Buffer} password_buf Password * @param {Buffer} secret1_buf Client private key {@see genKey} + * @param {boolean} hap */ constructor(params: SrpParams, salt_buf: Buffer, identity_buf: Buffer, password_buf: Buffer, secret1_buf: Buffer, hap = true) { - assertIsBuffer(salt_buf, 'salt (s)'); - assertIsBuffer(identity_buf, 'identity (I)'); - assertIsBuffer(password_buf, 'password (P)'); - assertIsBuffer(secret1_buf, 'secret1'); + assertIsBuffer(salt_buf, "salt (s)"); + assertIsBuffer(identity_buf, "identity (I)"); + assertIsBuffer(password_buf, "password (P)"); + assertIsBuffer(secret1_buf, "secret1"); this._params = params; this._k = getk(params); @@ -401,7 +411,7 @@ export class SrpClient { * * @return {Buffer} */ - computeA() { + computeA(): Buffer { return this._A; } @@ -410,7 +420,7 @@ export class SrpClient { * * @param {Buffer} B_buf The server's public key */ - setB(B_buf: Buffer) { + setB(B_buf: Buffer): void { const u_num = getu(this._params, this._A, B_buf); const S_buf_x = client_getS(this._params, this._k, this._x, this._a, new BigInteger(B_buf), u_num); @@ -432,9 +442,10 @@ export class SrpClient { * * @return {Buffer} */ - computeM1() { - if (this._M1 === undefined) - throw new Error('incomplete protocol'); + computeM1(): Buffer { + if (this._M1 === undefined) { + throw new Error("incomplete protocol"); + } return this._M1; } @@ -444,9 +455,10 @@ export class SrpClient { * * @param M2 The server's M2 value */ - checkM2(M2: Buffer) { - if (!equal(this._M2!, M2)) - throw new Error('server is not authentic'); + checkM2(M2: Buffer): void { + if (!equal(this._M2!, M2)) { + throw new Error("server is not authentic"); + } } /** @@ -454,9 +466,10 @@ export class SrpClient { * * @return {Buffer} */ - computeK() { - if (this._K === undefined) - throw new Error('incomplete protocol'); + computeK(): Buffer { + if (this._K === undefined) { + throw new Error("incomplete protocol"); + } return this._K; } } @@ -519,10 +532,10 @@ export class SrpServer { this._k = getk(params); if (arguments.length > 3) { - assertIsBuffer(salt_buf as Buffer, 'salt (salt)'); - assertIsBuffer(identity_buf!, 'identity (I)'); - assertIsBuffer(password_buf!, 'password (P)'); - assertIsBuffer(secret2_buf!, 'secret2'); + assertIsBuffer(salt_buf as Buffer, "salt (salt)"); + assertIsBuffer(identity_buf!, "identity (I)"); + assertIsBuffer(password_buf!, "password (P)"); + assertIsBuffer(secret2_buf!, "secret2"); this._b = new BigInteger(secret2_buf!); this._v = new BigInteger(SRP.computeVerifier(params, salt_buf as Buffer, identity_buf!, password_buf!)); @@ -531,34 +544,40 @@ export class SrpServer { this._s = salt_buf as Buffer; } else if (salt_buf instanceof Buffer) { const verifier_buf = salt_buf; + // noinspection JSUnusedAssignment [secret2_buf, salt_buf, identity_buf, password_buf] = [identity_buf, undefined, undefined, undefined]; - assertIsBuffer(verifier_buf, 'verifier (v)'); - assertIsBuffer(secret2_buf!, 'secret2'); + assertIsBuffer(verifier_buf, "verifier (v)"); + assertIsBuffer(secret2_buf!, "secret2"); this._b = new BigInteger(secret2_buf!); this._v = new BigInteger(verifier_buf); } else { const identity = salt_buf as Identity; + // noinspection JSUnusedAssignment [secret2_buf, salt_buf, identity_buf, password_buf] = [identity_buf, undefined, undefined, undefined]; // noinspection SuspiciousTypeOfGuard - assert(identity.username instanceof Buffer || typeof identity.username === 'string', 'identity.username (I) must be a string or Buffer'); - assertIsBuffer(identity.salt, 'identity.salt (s)'); - assert('password' in identity || 'verifier' in identity, 'identity requires a password or verifier'); - if ('verifier' in identity) assertIsBuffer(identity.verifier, 'identity.verifier (v)'); - else assert(identity.password instanceof Buffer || typeof identity.password === 'string', 'identity.password (p) must be a string or Buffer'); - assertIsBuffer(secret2_buf!, 'secret2'); + assert(identity.username instanceof Buffer || typeof identity.username === "string", "identity.username (I) must be a string or Buffer"); + assertIsBuffer(identity.salt, "identity.salt (s)"); + assert("password" in identity || "verifier" in identity, "identity requires a password or verifier"); + if ("verifier" in identity) { + assertIsBuffer(identity.verifier, "identity.verifier (v)"); + } else { + // noinspection SuspiciousTypeOfGuard + assert(identity.password instanceof Buffer || typeof identity.password === "string", "identity.password (p) must be a string or Buffer"); + } + assertIsBuffer(secret2_buf!, "secret2"); - const username = typeof identity.username === 'string' ? Buffer.from(identity.username) : identity.username; + const username = typeof identity.username === "string" ? Buffer.from(identity.username) : identity.username; this._b = new BigInteger(secret2_buf!); - if ('verifier' in identity) { + if ("verifier" in identity) { this._v = new BigInteger(identity.verifier); } else { this._v = new BigInteger(SRP.computeVerifier( params, identity.salt, username, - typeof identity.password === 'string' ? Buffer.from(identity.password) : identity.password + typeof identity.password === "string" ? Buffer.from(identity.password) : identity.password, )); } @@ -574,7 +593,7 @@ export class SrpServer { * * @return {Buffer} */ - computeB() { + computeB(): Buffer { return this._B; } @@ -583,7 +602,7 @@ export class SrpServer { * * @param {Buffer} A The client's public key */ - setA(A: Buffer) { + setA(A: Buffer): void { const u_num = getu(this._params, A, this._B); const S_buf = server_getS(this._params, this._v, new BigInteger(A), this._b, u_num); @@ -604,11 +623,13 @@ export class SrpServer { * * @param {Buffer} M1 The client's M1 value */ - checkM1(M1: Buffer) { - if (this._M1 === undefined) - throw new Error('incomplete protocol'); - if (!equal(this._M1, M1)) - throw new Error('client did not use the same password'); + checkM1(M1: Buffer): void { + if (this._M1 === undefined) { + throw new Error("incomplete protocol"); + } + if (!equal(this._M1, M1)) { + throw new Error("client did not use the same password"); + } } /** @@ -616,9 +637,10 @@ export class SrpServer { * * @return {Buffer} */ - computeK() { - if (this._K === undefined) - throw new Error('incomplete protocol'); + computeK(): Buffer { + if (this._K === undefined) { + throw new Error("incomplete protocol"); + } return this._K; } @@ -628,9 +650,11 @@ export class SrpServer { * * @return {Buffer} */ - computeM2() { - if (this._M2 === undefined) - throw new Error('incomplete protocol'); + computeM2(): Buffer { + if (this._M2 === undefined) { + throw new Error("incomplete protocol"); + } return this._M2; } + } diff --git a/src/test/hap_test_data.ts b/src/test/hap_test_data.ts index 7c9469e..a52a870 100644 --- a/src/test/hap_test_data.ts +++ b/src/test/hap_test_data.ts @@ -1,4 +1,4 @@ -import {hex} from '../params'; +import { hex } from "../params"; // Modulus (N), as specified by the 3072-bit group of RFC 5054 export const N = hex(` @@ -17,13 +17,13 @@ export const N = hex(` `); // Generator (g), as specified by the 3072-bit group of RFC 5054 -export const g = hex('05'); +export const g = hex("05"); // Username (I), as an ASCII string without quotes -export const I = 'alice'; +export const I = "alice"; // Password (p), as an ASCII string without quotes -export const p = 'password123'; +export const p = "password123"; // A private (a) export const a = hex(` diff --git a/src/test/test_hap_vectors.ts b/src/test/test_hap_vectors.ts index 183c012..3c907f7 100644 --- a/src/test/test_hap_vectors.ts +++ b/src/test/test_hap_vectors.ts @@ -1,8 +1,9 @@ +/* eslint-disable @typescript-eslint/ban-ts-ignore */ // @ts-ignore -import vows from 'vows'; -import assert from 'assert'; -import {SRP, SrpClient, SrpParams, SrpServer} from "../srp"; -import BigInteger = require('../../jsbn/jsbn'); +import vows from "vows"; +import assert from "assert"; +import { SRP, SrpClient, SrpParams, SrpServer } from "../srp"; +import BigInteger = require("../../jsbn/jsbn"); interface Input { /** Identity */ @@ -32,13 +33,14 @@ interface ExpectedOutput { M1: Buffer; } -import {N, g, I, p, a, A, b, B, s, v, u, S, K} from './hap_test_data'; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import {N, g, I, p, a, A, b, B, s, v, u, S, K} from "./hap_test_data"; const params = SRP.params.hap; const inputs: Input = { - I: Buffer.from(I, 'ascii'), - P: Buffer.from(p, 'ascii'), + I: Buffer.from(I, "ascii"), + P: Buffer.from(p, "ascii"), salt: s.toBuffer(true), // a and b are usually random. For testing, we force them to specific values. a: a.toBuffer(true), @@ -47,9 +49,9 @@ const inputs: Input = { const expected: ExpectedOutput = { // 'k' encodes the group (N and g), used in SRP-6a - k: Buffer.from('a9c2e2559bf0ebb53f0cbbf62282906bede7f2182f00678211fbd5bde5b285033a4993503b87397f9be5ec02080fedbc0835587ad039060879b8621e8c3659e0', 'hex'), + k: Buffer.from("a9c2e2559bf0ebb53f0cbbf62282906bede7f2182f00678211fbd5bde5b285033a4993503b87397f9be5ec02080fedbc0835587ad039060879b8621e8c3659e0", "hex"), // 'x' is derived from the salt and password - x: Buffer.from('b149ecb0946b0b206d77e73d95deb7c41bd12e86a5e2eea3893d5416591a002ff94bfea384dc0e1c550f7ed4d5a9d2ad1f1526f01c56b5c10577730cc4a4d709', 'hex'), + x: Buffer.from("b149ecb0946b0b206d77e73d95deb7c41bd12e86a5e2eea3893d5416591a002ff94bfea384dc0e1c550f7ed4d5a9d2ad1f1526f01c56b5c10577730cc4a4d709", "hex"), // 'v' is the SRP verifier v: v.toBuffer(true), // 'B' is the server's public message @@ -63,21 +65,21 @@ const expected: ExpectedOutput = { // 'K' is the shared derived key K: K.toBuffer(true), // 'M1' is the client's proof that it knows the shared key - M1: Buffer.from('5f7c14ab57ed0e94fd1d78c6b4dd09ed7e340b7e05d419a9fd760f6b35e523d1310777a1ae1d2826f596f3a85116cc457c7c964d4f44ded5559da818c88b617f', 'hex'), + M1: Buffer.from("5f7c14ab57ed0e94fd1d78c6b4dd09ed7e340b7e05d419a9fd760f6b35e523d1310777a1ae1d2826f596f3a85116cc457c7c964d4f44ded5559da818c88b617f", "hex"), }; -function hexequal(a: Buffer, b: Buffer, msg?: string) { - assert.equal(a.length, b.length, msg); - assert.equal(a.toString('hex'), b.toString('hex'), msg); +function hexequal(a: Buffer, b: Buffer, msg?: string): void { + assert.strictEqual(a.length, b.length, msg); + assert.strictEqual(a.toString("hex"), b.toString("hex"), msg); } -function numequal(a: BigInteger, b: BigInteger, msg?: string) { +function numequal(a: BigInteger, b: BigInteger, msg?: string): void { assert(a.compareTo(b) === 0, msg); } -function checkVectors(params: SrpParams, inputs: Input, expected: ExpectedOutput, useVerifier = true) { - hexequal(inputs.I, Buffer.from('616c696365', 'hex'), 'I'); - hexequal(SRP.computeVerifier(params, inputs.salt, inputs.I, inputs.P), expected.v, 'v'); +function checkVectors(params: SrpParams, inputs: Input, expected: ExpectedOutput, useVerifier = true): void { + hexequal(inputs.I, Buffer.from("616c696365", "hex"), "I"); + hexequal(SRP.computeVerifier(params, inputs.salt, inputs.I, inputs.P), expected.v, "v"); const client = new SrpClient(params, inputs.salt, inputs.I, inputs.P, inputs.a, true); const server = useVerifier ? @@ -85,9 +87,9 @@ function checkVectors(params: SrpParams, inputs: Input, expected: ExpectedOutput new SrpServer(params, inputs.salt, inputs.I, inputs.P, inputs.b); // @ts-ignore - numequal(client._k, new BigInteger(expected.k.toString('hex'), 16), 'k'); + numequal(client._k, new BigInteger(expected.k.toString("hex"), 16), "k"); // @ts-ignore - numequal(client._x, new BigInteger(expected.x.toString('hex'), 16), 'x'); + numequal(client._x, new BigInteger(expected.x.toString("hex"), 16), "x"); hexequal(client.computeA(), expected.A); hexequal(server.computeB(), expected.B); @@ -99,7 +101,7 @@ function checkVectors(params: SrpParams, inputs: Input, expected: ExpectedOutput client.setB(expected.B); // @ts-ignore - numequal(client._u, new BigInteger(expected.u.toString('hex'), 16)); + numequal(client._u, new BigInteger(expected.u.toString("hex"), 16)); // @ts-ignore hexequal(client._S, expected.S); hexequal(client.computeM1(), expected.M1); @@ -107,15 +109,15 @@ function checkVectors(params: SrpParams, inputs: Input, expected: ExpectedOutput server.setA(expected.A); // @ts-ignore - numequal(server._u, new BigInteger(expected.u.toString('hex'), 16)); + numequal(server._u, new BigInteger(expected.u.toString("hex"), 16)); // @ts-ignore hexequal(server._S, expected.S); - assert.throws(() => server.checkM1(Buffer.from('notM1')), /client did not use the same password/); + assert.throws(() => server.checkM1(Buffer.from("notM1")), /client did not use the same password/); server.checkM1(expected.M1); // happy, not throwy hexequal(server.computeK(), expected.K); } -vows.describe('HomeKit vectors').addBatch({ - 'with verifier': () => checkVectors(params, inputs, expected), - 'with password': () => checkVectors(params, inputs, expected, false), +vows.describe("HomeKit vectors").addBatch({ + "with verifier": () => checkVectors(params, inputs, expected), + "with password": () => checkVectors(params, inputs, expected, false), }).export(module); diff --git a/src/test/test_picl_vectors.ts b/src/test/test_picl_vectors.ts index 8942bf0..ae72ba8 100644 --- a/src/test/test_picl_vectors.ts +++ b/src/test/test_picl_vectors.ts @@ -1,8 +1,9 @@ +/* eslint-disable @typescript-eslint/ban-ts-ignore */ // @ts-ignore -import vows from 'vows'; -import assert from 'assert'; -import {SRP, SrpClient, SrpParams, SrpServer} from '../srp'; -import BigInteger = require('../../jsbn/jsbn'); +import vows from "vows"; +import assert from "assert"; +import { SRP, SrpClient, SrpParams, SrpServer } from "../srp"; +import BigInteger = require("../../jsbn/jsbn"); /* * Vectors from https://wiki.mozilla.org/Identity/AttachedServices/KeyServerProtocol @@ -13,8 +14,8 @@ import BigInteger = require('../../jsbn/jsbn'); * Note that P is the HKDF-stretched key, computed elsewhere. */ -function hex(s: string) { - return Buffer.from(s.split(/\s/).join(''), 'hex'); +function hex(s: string): Buffer { + return Buffer.from(s.split(/\s/).join(""), "hex"); } const params = SRP.params[2048]; @@ -53,9 +54,9 @@ interface ExpectedOutput { */ const inputs_1: Input = { - I: Buffer.from('andré@example.org', 'utf8'), - P: hex('00f9b71800ab5337 d51177d8fbc682a3 653fa6dae5b87628 eeec43a18af59a9d'), - salt: hex('00f1000000000000000000000000000000000000000000000000000000000179'), + I: Buffer.from("andré@example.org", "utf8"), + P: hex("00f9b71800ab5337 d51177d8fbc682a3 653fa6dae5b87628 eeec43a18af59a9d"), + salt: hex("00f1000000000000000000000000000000000000000000000000000000000179"), // a and b are usually random. For testing, we force them to specific values. a: hex(` 00f2000000000000 0000000000000000 0000000000000000 0000000000000000 @@ -81,10 +82,10 @@ const inputs_1: Input = { const expected_1: ExpectedOutput = { // 'k' encodes the group (N and g), used in SRP-6a - k: hex('05b9e8ef059c6b32 ea59fc1d322d37f0 4aa30bae5aa9003b 8321e21ddb04e300'), + k: hex("05b9e8ef059c6b32 ea59fc1d322d37f0 4aa30bae5aa9003b 8321e21ddb04e300"), // 'x' is derived from the salt and password // 'v' is the SRP verifier - x: hex('b5200337cc3f3f92 6cdddae0b2d31029 c069936a844aff58 779a545be89d0abe'), + x: hex("b5200337cc3f3f92 6cdddae0b2d31029 c069936a844aff58 779a545be89d0abe"), v: hex(` 00173ffa0263e63c cfd6791b8ee2a40f 048ec94cd95aa8a3 125726f9805e0c82 83c658dc0b607fbb 25db68e68e93f265 8483049c68af7e82 14c49fde2712a775 @@ -118,7 +119,7 @@ const expected_1: ExpectedOutput = { 7374d73e79be2c39 75632de562c59647 0bb27bad79c3e2fc ddf194e1666cb9fc `), // 'u' combines the two public messages - u: hex('b284aa1064e87751 50da6b5e2147b47c a7df505bed94a6f4 bb2ad873332ad732'), + u: hex("b284aa1064e87751 50da6b5e2147b47c a7df505bed94a6f4 bb2ad873332ad732"), // 'S' is the shared secret S: hex(` 0092aaf0f527906a a5e8601f5d707907 a03137e1b601e04b 5a1deb02a981f4be @@ -131,15 +132,15 @@ const expected_1: ExpectedOutput = { 6001497c27f362ed bafb25e0f045bfdf 9fb02db9c908f103 40a639fe84c31b27 `), // 'K' is the shared derived key - K: hex('e68fd0112bfa31dc ffc8e9c96a1cbadb 4c3145978ff35c73 e5bf8d30bbc7499a'), + K: hex("e68fd0112bfa31dc ffc8e9c96a1cbadb 4c3145978ff35c73 e5bf8d30bbc7499a"), // 'M1' is the client's proof that it knows the shared key - M1: hex('27949ec1e0f16256 33436865edb037e2 3eb6bf5cb91873f2 a2729373c2039008') + M1: hex("27949ec1e0f16256 33436865edb037e2 3eb6bf5cb91873f2 a2729373c2039008"), }; /* inputs_2/expected_2 have leading 0x00 bytes in 'x' and 'u' */ const inputs_2: Input = { I: inputs_1.I, P: inputs_1.P, - salt: hex('00f1000000000000000000000000000000000000000000000000000000000021'), + salt: hex("00f1000000000000000000000000000000000000000000000000000000000021"), a: hex(` 00f2000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 @@ -159,11 +160,11 @@ const inputs_2: Input = { 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000001 - `) + `), }; const expected_2: ExpectedOutput = { k: expected_1.k, - x: hex('009b2740fb49284d 69cab7c916d449ee d7dcabf41332b8b8 d6928f529bd1a94e'), + x: hex("009b2740fb49284d 69cab7c916d449ee d7dcabf41332b8b8 d6928f529bd1a94e"), v: hex(` 1cd8b856685672ee 7a5895d897121234 6c17c3472f2696e4 8cdeec5533c06693 179bc24802b762bc c1e1f8fc8abe607a f2f44aac9172e7dd 0c0110e45cf3b700 @@ -197,7 +198,7 @@ const expected_2: ExpectedOutput = { cdcb555a6b16e844 5b03e09776eba841 7576dac458afbbd5 2902dfb0282bed79 `), // 'u' combines the two public messages - u: hex('000e4039be3989ad 088dc17d8ade899a 6409e7e57b3e8518 cee1cbc77e1de243'), + u: hex("000e4039be3989ad 088dc17d8ade899a 6409e7e57b3e8518 cee1cbc77e1de243"), // 'S' is the shared secret S: hex(` 5c7f591d134d19f9 fcedc2b4e3eecd3d 5deadfe7dd42bd59 b1c960516c65ab61 @@ -210,15 +211,15 @@ const expected_2: ExpectedOutput = { e75f0058f718ec14 f9bbeb29ff966e00 ddfdd2d38a1c7a68 ac455a57b972d528 `), // 'K' is the shared derived key - K: hex('b637ede0b7a31c46 b2567e855eb8a7f7 a994937deee76479 62afbe35d6929709'), + K: hex("b637ede0b7a31c46 b2567e855eb8a7f7 a994937deee76479 62afbe35d6929709"), // 'M1' is the client's proof that it knows the shared key - M1: hex('67c83797eb1a3987 e2d48d287e3bd772 d25db2b3cd86ea22 c8cf3ae932a1e45b') + M1: hex("67c83797eb1a3987 e2d48d287e3bd772 d25db2b3cd86ea22 c8cf3ae932a1e45b"), }; /* inputs_3/expected_3 have leading 0x00 bytes in 'x' and 'K' */ const inputs_3: Input = { I: inputs_2.I, P: inputs_2.P, - salt: hex('00f1000000000000000000000000000000000000000000000000000000000021'), + salt: hex("00f1000000000000000000000000000000000000000000000000000000000021"), a: hex(` 00f2000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 @@ -229,7 +230,7 @@ const inputs_3: Input = { 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 00000000000001a0 `), - b: inputs_2.b + b: inputs_2.b, }; const expected_3: ExpectedOutput = { k: expected_2.k, @@ -246,7 +247,7 @@ const expected_3: ExpectedOutput = { 6c7011f3c979eaab 469f06465a5b7239 afaee535aedc5bd2 1a220546e0e6b70b 5b6f54db3fea46d5 7ebc7fe46156d793 c59e6290d3cf9bc2 4316528da34f4640 `), - u: hex('865d0efca6cf17d6 f489e129231f1a48 b20c83ec6581d11f 3a2fa48ea93cd305'), + u: hex("865d0efca6cf17d6 f489e129231f1a48 b20c83ec6581d11f 3a2fa48ea93cd305"), S: hex(` 0ae26456e1a0dec1 ce162fb2e5bc7300 3c285e17c0b44f03 7ebbc57f8020ceae 5d10a9e6e44eab2a 6915b582ab5f6e7d 16002ce05e524015 e9bc7c56d5131da4 @@ -257,14 +258,14 @@ const expected_3: ExpectedOutput = { 249f7734081aa42d 58dd54f8f725b245 175cf7d102e1086c eba4cfe7e49a2d27 ffd6aef7549d402f bfcea78b4f3398ac 9ab1ee199f70acb6 4d2a17e159ff500d `), - K: hex('00217598a4008956 4b17196bd43422d6 03a0a88a545b61b3 98c42c9cbcc1d1b3'), - M1: hex('96d815ecece1dff4 254cd77517b37b97 65e741c1a57169ab af538e867444ec7f') + K: hex("00217598a4008956 4b17196bd43422d6 03a0a88a545b61b3 98c42c9cbcc1d1b3"), + M1: hex("96d815ecece1dff4 254cd77517b37b97 65e741c1a57169ab af538e867444ec7f"), }; /* inputs_4/expected_4 have leading 0x00 bytes in 'x' and 'M1' */ const inputs_4: Input = { I: inputs_2.I, P: inputs_2.P, - salt: hex('00f1000000000000000000000000000000000000000000000000000000000021'), + salt: hex("00f1000000000000000000000000000000000000000000000000000000000021"), a: hex(` 00f2000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 @@ -275,7 +276,7 @@ const inputs_4: Input = { 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000190 `), - b: inputs_2.b + b: inputs_2.b, }; const expected_4: ExpectedOutput = { k: expected_2.k, @@ -292,7 +293,7 @@ const expected_4: ExpectedOutput = { c690f9478d5b331d c00eef68670edbf3 629fd1a6c85267d2 cbb90f1670e7ba09 cf2b5a9b00be8e11 f33e47a1c1f04eca f35bccb61af1116e 4d0f9d475017bad2 `), - u: hex('d0913eb75b61e15a 87756ffa04d4f967 e492bd0b330a2b11 fe8976aada2bb1ee'), + u: hex("d0913eb75b61e15a 87756ffa04d4f967 e492bd0b330a2b11 fe8976aada2bb1ee"), S: hex(` 7ba3ce4a3d236b95 3c2d0fee42195c85 081664a44f55b82d a3abf66ac68bdbd7 ad82d5ad95090782 5241fb706de8fc58 0a29e4579fbbedf3 0bec0138b3f76e06 @@ -303,30 +304,30 @@ const expected_4: ExpectedOutput = { d4a9bf0242bfe703 26fc19b68c90e83b 59b5cc21886ab602 f8bfa16fb50c3147 9aad5e31698abf67 863b7ca6b6ac25a7 09a24d8f94c80bbf 691e38c81beb3c72 `), - K: hex('bd2a167a93b8496e 68c7e24b37956924 672eb8249d25c281 13984912d5cf27a6'), - M1: hex('00cef66a047d506c bf941c236218e583 5343534ae08cf0cd 0fb7980bed242e05') + K: hex("bd2a167a93b8496e 68c7e24b37956924 672eb8249d25c281 13984912d5cf27a6"), + M1: hex("00cef66a047d506c bf941c236218e583 5343534ae08cf0cd 0fb7980bed242e05"), }; -function hexequal(a: Buffer, b: Buffer, msg?: string) { - assert.equal(a.length, b.length, msg); - assert.equal(a.toString('hex'), b.toString('hex'), msg); +function hexequal(a: Buffer, b: Buffer, msg?: string): void { + assert.strictEqual(a.length, b.length, msg); + assert.strictEqual(a.toString("hex"), b.toString("hex"), msg); } -function numequal(a: BigInteger, b: BigInteger, msg?: string) { +function numequal(a: BigInteger, b: BigInteger, msg?: string): void { assert(a.compareTo(b) === 0, msg); } -function checkVectors(params: SrpParams, inputs: Input, expected: ExpectedOutput) { - hexequal(inputs.I, Buffer.from('616e6472c3a9406578616d706c652e6f7267', 'hex'), 'I'); - hexequal(SRP.computeVerifier(params, inputs.salt, inputs.I, inputs.P), expected.v, 'v'); +function checkVectors(params: SrpParams, inputs: Input, expected: ExpectedOutput): void { + hexequal(inputs.I, Buffer.from("616e6472c3a9406578616d706c652e6f7267", "hex"), "I"); + hexequal(SRP.computeVerifier(params, inputs.salt, inputs.I, inputs.P), expected.v, "v"); const client = new SrpClient(params, inputs.salt, inputs.I, inputs.P, inputs.a, false); const server = new SrpServer(params, expected.v, inputs.b); // @ts-ignore - numequal(client._k, new BigInteger(expected.k.toString('hex'), 16), 'k'); + numequal(client._k, new BigInteger(expected.k.toString("hex"), 16), "k"); // @ts-ignore - numequal(client._x, new BigInteger(expected.x.toString('hex'), 16), 'x'); + numequal(client._x, new BigInteger(expected.x.toString("hex"), 16), "x"); hexequal(client.computeA(), expected.A); hexequal(server.computeB(), expected.B); @@ -338,7 +339,7 @@ function checkVectors(params: SrpParams, inputs: Input, expected: ExpectedOutput client.setB(expected.B); // @ts-ignore - numequal(client._u, new BigInteger(expected.u.toString('hex'), 16)); + numequal(client._u, new BigInteger(expected.u.toString("hex"), 16)); // @ts-ignore hexequal(client._S, expected.S); hexequal(client.computeM1(), expected.M1); @@ -346,17 +347,17 @@ function checkVectors(params: SrpParams, inputs: Input, expected: ExpectedOutput server.setA(expected.A); // @ts-ignore - numequal(server._u, new BigInteger(expected.u.toString('hex'), 16)); + numequal(server._u, new BigInteger(expected.u.toString("hex"), 16)); // @ts-ignore hexequal(server._S, expected.S); - assert.throws(() => server.checkM1(Buffer.from('notM1')), /client did not use the same password/); + assert.throws(() => server.checkM1(Buffer.from("notM1")), /client did not use the same password/); server.checkM1(expected.M1); // happy, not throwy hexequal(server.computeK(), expected.K); } -vows.describe('picl vectors').addBatch({ - 'vectors 1': () => checkVectors(params, inputs_1, expected_1), - 'vectors 2': () => checkVectors(params, inputs_2, expected_2), - 'vectors 3': () => checkVectors(params, inputs_3, expected_3), - 'vectors 4': () => checkVectors(params, inputs_4, expected_4), +vows.describe("picl vectors").addBatch({ + "vectors 1": () => checkVectors(params, inputs_1, expected_1), + "vectors 2": () => checkVectors(params, inputs_2, expected_2), + "vectors 3": () => checkVectors(params, inputs_3, expected_3), + "vectors 4": () => checkVectors(params, inputs_4, expected_4), }).export(module); diff --git a/src/test/test_rfc_5054.ts b/src/test/test_rfc_5054.ts index 9d7e8cd..86ecde6 100644 --- a/src/test/test_rfc_5054.ts +++ b/src/test/test_rfc_5054.ts @@ -1,8 +1,9 @@ +/* eslint-disable @typescript-eslint/ban-ts-ignore */ // @ts-ignore -import vows from 'vows'; -import assert from 'assert'; -import {SRP, SrpClient, SrpServer} from '../srp'; -import BigInteger = require('../../jsbn/jsbn'); +import vows from "vows"; +import assert from "assert"; +import { SRP, SrpClient, SrpServer } from "../srp"; +import BigInteger = require("../../jsbn/jsbn"); const params = SRP.params[1024]; @@ -10,15 +11,15 @@ const params = SRP.params[1024]; * http://tools.ietf.org/html/rfc5054#appendix-B */ -function hex(h: string) { - return h.split(/\s/).join(''); +function hex(h: string): string { + return h.split(/\s/).join(""); } -const I = Buffer.from('alice'); -const P = Buffer.from('password123'); -const s = Buffer.from('beb25379d1a8581eb5a727673a2441ee', 'hex'); -const k_expected = '7556aa045aef2cdd07abaf0f665c3e818913186f'; -const x_expected = '94b7555aabe9127cc58ccf4993db6cf84d16c124'; +const I = Buffer.from("alice"); +const P = Buffer.from("password123"); +const s = Buffer.from("beb25379d1a8581eb5a727673a2441ee", "hex"); +const k_expected = "7556aa045aef2cdd07abaf0f665c3e818913186f"; +const x_expected = "94b7555aabe9127cc58ccf4993db6cf84d16c124"; const v_expected = hex(` 7e273de8 696ffc4f 4e337d05 b4b375be b0dde156 9e8fa00a 9886d812 9bada1f1 822223ca 1a605b53 0e379ba4 729fdc59 f105b478 7e5186f5 @@ -26,8 +27,8 @@ const v_expected = hex(` ea53d15c 1aff87b2 b9da6e04 e058ad51 cc72bfc9 033b564e 26480d78 e955a5e2 9e7ab245 db2be315 e2099afb `); -const a = Buffer.from('60975527035cf2ad1989806f0407210bc81edc04e2762a56afd529ddda2d4393', 'hex'); -const b = Buffer.from('e487cb59d31ac550471e81f00f6928e01dda08e974a004f49e61f5d105284d20', 'hex'); +const a = Buffer.from("60975527035cf2ad1989806f0407210bc81edc04e2762a56afd529ddda2d4393", "hex"); +const b = Buffer.from("e487cb59d31ac550471e81f00f6928e01dda08e974a004f49e61f5d105284d20", "hex"); const A_expected = hex(` 61d5e490 f6f1b795 47b0704c 436f523d d0e560f0 c64115bb 72557ec4 4352e890 3211c046 92272d8b 2d1a5358 a2cf1b6e 0bfcf99f 921530ec @@ -42,7 +43,7 @@ const B_expected = hex(` 37089e6f 9c6059f3 88838e7a 00030b33 1eb76840 910440b1 b27aaeae eb4012b7 d7665238 a8e3fb00 4b117b58 `); -const u_expected = 'ce38b9593487da98554ed47d70a7ae5f462ef019'; +const u_expected = "ce38b9593487da98554ed47d70a7ae5f462ef019"; const S_expected = hex(` b0dc82ba bcf30674 ae450c02 87745e79 90a3381f 63b387aa f271a10d 233861e3 59b48220 f7c4693c 9ae12b0a 6f67809f 0876e2d0 13800d6c @@ -51,61 +52,61 @@ const S_expected = hex(` c346d7e4 74b29ede 8a469ffe ca686e5a `); -function asHex(num: number | BigInteger) { +function asHex(num: number | BigInteger): string { return num.toString(16); } -vows.describe('RFC 5054').addBatch({ - 'Test vectors': { - topic() { +vows.describe("RFC 5054").addBatch({ + "Test vectors": { + topic(): Buffer { return SRP.computeVerifier(params, s, I, P); }, - 'x'() { + "x"(): void { const client = new SrpClient(params, s, I, P, a, false); // @ts-ignore - assert.equal(asHex(client._x), x_expected); + assert.strictEqual(asHex(client._x), x_expected); }, - 'V'(v: Buffer) { - assert.equal(v.toString('hex'), v_expected); + "V"(v: Buffer): void { + assert.strictEqual(v.toString("hex"), v_expected); }, - 'k'() { + "k"(): void { const client = new SrpClient(params, s, I, P, a, false); // @ts-ignore - assert.equal(asHex(client._k), k_expected); + assert.strictEqual(asHex(client._k), k_expected); }, - 'A'() { + "A"(): void { const client = new SrpClient(params, s, I, P, a, false); - assert.equal(client.computeA().toString('hex'), A_expected); + assert.strictEqual(client.computeA().toString("hex"), A_expected); }, - 'B'(v: Buffer) { + "B"(v: Buffer): void { const server = new SrpServer(params, v, b); - assert.equal(server.computeB().toString('hex'), B_expected); + assert.strictEqual(server.computeB().toString("hex"), B_expected); }, - 'u'() { + "u"(): void { const client = new SrpClient(params, s, I, P, a, false); - client.setB(Buffer.from(B_expected, 'hex')); + client.setB(Buffer.from(B_expected, "hex")); // @ts-ignore - assert.equal(asHex(client._u), u_expected); + assert.strictEqual(asHex(client._u), u_expected); }, - 'S client'() { + "S client"(): void { const client = new SrpClient(params, s, I, P, a, false); - client.setB(Buffer.from(B_expected, 'hex')); + client.setB(Buffer.from(B_expected, "hex")); // @ts-ignore - assert.equal(client._S.toString('hex'), S_expected); + assert.strictEqual(client._S.toString("hex"), S_expected); }, - 'S server'(v: Buffer) { + "S server"(v: Buffer): void { const server = new SrpServer(params, v, b); - server.setA(Buffer.from(A_expected, 'hex')); + server.setA(Buffer.from(A_expected, "hex")); // @ts-ignore - assert.equal(server._S.toString('hex'), S_expected); + assert.strictEqual(server._S.toString("hex"), S_expected); }, }, }).export(module); diff --git a/src/test/test_srp.ts b/src/test/test_srp.ts index 9e36209..c3a4c40 100644 --- a/src/test/test_srp.ts +++ b/src/test/test_srp.ts @@ -1,15 +1,16 @@ +// eslint-disable-next-line @typescript-eslint/ban-ts-ignore // @ts-ignore -import vows from 'vows'; -import assert from 'assert'; -import {SRP, SrpClient, SrpServer} from '../srp'; +import vows from "vows"; +import assert from "assert"; +import { SRP, SrpClient, SrpServer } from "../srp"; const params = SRP.params[4096]; -const salt = Buffer.from('salty'); -const identity = Buffer.from('alice'); -const password = Buffer.from('password123'); +const salt = Buffer.from("salty"); +const identity = Buffer.from("alice"); +const password = Buffer.from("password123"); -assert(params, 'missing parameters'); +assert(params, "missing parameters"); let client: SrpClient, server: SrpServer; let a: Buffer, A: Buffer; @@ -17,20 +18,23 @@ let b: Buffer, B: Buffer; let verifier: Buffer; // let S_client, S_server; -vows.describe('srp.js').addBatch({ - 'create Verifier'() { +vows.describe("srp.js").addBatch({ + "create Verifier"() { verifier = SRP.computeVerifier(params, salt, identity, password); - assert.equal(verifier.toString('hex'), 'f0e47f50f5dead8db8d93a279e3b62d6ff50854b31fbd3474a886bef916261717e84dd4fb8b4d27feaa5146db7b1cbbc274fdf96a132b5029c2cd72527427a9b9809d5a4d018252928b4fc343bc17ce63c1859d5806f5466014fc361002d8890aeb4d6316ff37331fc2761be0144c91cdd8e00ed0138c0ce51534d1b9a9ba629d7be34d2742dd4097daabc9ecb7aaad89e53c342b038f1d2adae1f2410b7884a3e9a124c357e421bccd4524467e1922660e0a4460c5f7c38c0877b65f6e32f28296282a93fc11bbabb7bb69bf1b3f9391991d8a86dd05e15000b7e38ba38a536bb0bf59c808ec25e791b8944719488b8087df8bfd7ff20822997a53f6c86f3d45d004476d6303301376bb25a9f94b552cce5ed40de5dd7da8027d754fa5f66738c7e3fc4ef3e20d625df62cbe6e7adfc21e47880d8a6ada37e60370fd4d8fc82672a90c29f2e72f35652649d68348de6f36d0e435c8bd42dd00155d35d501becc0661b43e04cdb2da84ce92b8bf49935d73d75efcbd1176d7bbccc3cc4d4b5fefcc02d478614ee1681d2ff3c711a61a7686eb852ae06fb8227be21fb8802719b1271ba1c02b13bbf0a2c2e459d9bedcc8d1269f6a785cb4563aa791b38fb038269f63f58f47e9051499549789269cc7b8ec7026fc34ba73289c4af829d5a532e723967ce9b6c023ef0fd0cfe37f51f10f19463b6534159a09ddd2f51f3b30033'); + assert.strictEqual(verifier.toString("hex"), "f0e47f50f5dead8db8d93a279e3b62d6ff50854b31fbd3474a886bef916261717e84dd4fb8b4d27feaa5146db7b1cbbc274fdf96a132b5029c2cd72527427a9b9809d5a4d018252928b4fc343bc17ce63c1859d5806f5466014fc361002d8890aeb4d6316ff37331fc2761be0144c91cdd8e00ed0138c0ce51534d1b9a9ba629d7be34d2742dd4097daabc9ecb7aaad89e53c342b038f1d2adae1f2410b7884a3e9a124c357e421bccd4524467e1922660e0a4460c5f7c38c0877b65f6e32f28296282a93fc11bbabb7bb69bf1b3f9391991d8a86dd05e15000b7e38ba38a536bb0bf59c808ec25e791b8944719488b8087df8bfd7ff20822997a53f6c86f3d45d004476d6303301376bb25a9f94b552cce5ed40de5dd7da8027d754fa5f66738c7e3fc4ef3e20d625df62cbe6e7adfc21e47880d8a6ada37e60370fd4d8fc82672a90c29f2e72f35652649d68348de6f36d0e435c8bd42dd00155d35d501becc0661b43e04cdb2da84ce92b8bf49935d73d75efcbd1176d7bbccc3cc4d4b5fefcc02d478614ee1681d2ff3c711a61a7686eb852ae06fb8227be21fb8802719b1271ba1c02b13bbf0a2c2e459d9bedcc8d1269f6a785cb4563aa791b38fb038269f63f58f47e9051499549789269cc7b8ec7026fc34ba73289c4af829d5a532e723967ce9b6c023ef0fd0cfe37f51f10f19463b6534159a09ddd2f51f3b30033"); }, - 'create a and b': { - topic(this: any) {(async () => { - a = await SRP.genKey(64); - b = await SRP.genKey(32); - this.callback(); - })()}, + "create a and b": { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + topic(this: any): void { + (async (): Promise => { + a = await SRP.genKey(64); + b = await SRP.genKey(32); + this.callback(); + })(); + }, - 'use a and b'() { + "use a and b"(): void { client = new SrpClient(params, salt, identity, password, a, false); // client produces A @@ -61,51 +65,51 @@ vows.describe('srp.js').addBatch({ // client and server agree on K const client_K = client.computeK(); const server_K = server.computeK(); - assert.equal(client_K.toString('hex'), server_K.toString('hex')); + assert.strictEqual(client_K.toString("hex"), server_K.toString("hex")); // server is authentic - assert.doesNotThrow(() => client.checkM2(serverM2), 'M2 didn\'t check'); + assert.doesNotThrow(() => client.checkM2(serverM2), "M2 didn't check"); }, - 'server rejects wrong M1'() { - const bad_client = new SrpClient(params, salt, identity, Buffer.from('bad'), a, false); + "server rejects wrong M1"(): void { + const bad_client = new SrpClient(params, salt, identity, Buffer.from("bad"), a, false); const server2 = new SrpServer(params, verifier, b); bad_client.setB(server2.computeB()); assert.throws(() => server.checkM1(bad_client.computeM1()), /client did not use the same password/); }, - 'server rejects bad A'() { + "server rejects bad A"(): void { // client's "A" must be 1..N-1 . Reject 0 and N and N+1. We should // reject 2*N too, but our Buffer-length checks reject it before the // number itself is examined. - var server2 = new SrpServer(params, verifier, b); - var Azero = Buffer.alloc(params.N_length_bits / 8); + const server2 = new SrpServer(params, verifier, b); + const Azero = Buffer.alloc(params.N_length_bits / 8); Azero.fill(0); -//! var AN = params.N.toBuffer(); -//! var AN1 = params.N.add(1).toBuffer(); - var AN = Buffer.from(params.N.toString(16), 'hex'); - var AN1 = Buffer.from(params.N.add(1).toString(16), 'hex'); + //! var AN = params.N.toBuffer(); + //! var AN1 = params.N.add(1).toBuffer(); + const AN = Buffer.from(params.N.toString(16), "hex"); + const AN1 = Buffer.from(params.N.add(1).toString(16), "hex"); assert.throws(() => server2.setA(Azero), /invalid client-supplied "A"/); assert.throws(() => server2.setA(AN), /invalid client-supplied "A"/); assert.throws(() => server2.setA(AN1), /invalid client-supplied "A"/); }, - 'client rejects bad B'() { + "client rejects bad B"(): void { // server's "B" must be 1..N-1 . Reject 0 and N and N+1 - var client2 = new SrpClient(params, salt, identity, password, a, false); - var Bzero = Buffer.alloc(params.N_length_bits / 8); + const client2 = new SrpClient(params, salt, identity, password, a, false); + const Bzero = Buffer.alloc(params.N_length_bits / 8); Bzero.fill(0, 0, params.N_length_bits / 8); -//! var BN = params.N.toBuffer(); -//! var BN1 = params.N.add(1).toBuffer(); - var BN = Buffer.from(params.N.toString(16), 'hex'); - var BN1 = Buffer.from(params.N.add(1).toString(16), 'hex'); + //! var BN = params.N.toBuffer(); + //! var BN1 = params.N.add(1).toBuffer(); + const BN = Buffer.from(params.N.toString(16), "hex"); + const BN1 = Buffer.from(params.N.add(1).toString(16), "hex"); assert.throws(() => client2.setB(Bzero), /invalid server-supplied "B"/); assert.throws(() => client2.setB(BN), /invalid server-supplied "B"/); assert.throws(() => client2.setB(BN1), /invalid server-supplied "B"/); }, - 'client rejects bad M2'() { + "client rejects bad M2"(): void { client = new SrpClient(params, salt, identity, password, a, false); // client produces A @@ -130,15 +134,15 @@ vows.describe('srp.js').addBatch({ server.checkM1(client.computeM1()); let serverM2 = server.computeM2(); // we tamper with the server's M2 - serverM2 = Buffer.from('a'); + serverM2 = Buffer.from("a"); // client and server agree on K - var client_K = client.computeK(); - var server_K = server.computeK(); - assert.equal(client_K.toString('hex'), server_K.toString('hex')); + const client_K = client.computeK(); + const server_K = server.computeK(); + assert.strictEqual(client_K.toString("hex"), server_K.toString("hex")); // server is NOT authentic - assert.throws(() => client.checkM2(serverM2), 'M2 didn\'t check'); + assert.throws(() => client.checkM2(serverM2), "M2 didn't check"); }, }, }).export(module);