diff --git a/.gitignore b/.gitignore index f06235c..491fc35 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ node_modules -dist +lib diff --git a/README.md b/README.md index 8ad2afd..26c9394 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Creating the Verifier --- ```ts -import * as srp6a from 'fast-srp-hap'; +import { SRP } from 'fast-srp-hap'; /** * Computes the verifier of a user. Only needed to add the user to the auth system. @@ -19,12 +19,12 @@ import * as srp6a from 'fast-srp-hap'; * @return {Promise<{salt: Buffer, verifier: Buffer}>} */ async function srp6a_create_user(I: string, P: string) { - const salt = await srp6a.genKey(32); + const salt = await SRP.genKey(32); return { // The salt is required for authenticating the user later salt, - verifier: srp6a.computeVerifier(srp6a.params[4096], salt, Buffer.from(I), Buffer.from(P)), + verifier: SRP.computeVerifier(SRP.params[4096], salt, Buffer.from(I), Buffer.from(P)), }; } @@ -38,7 +38,7 @@ Server --- ```ts -import {Server, genKey, params} from 'fast-srp-hap'; +import {SRP, SrpServer} from 'fast-srp-hap'; (async () => { // Get the user details from somewhere @@ -46,7 +46,7 @@ import {Server, genKey, params} from 'fast-srp-hap'; username: 'username', // Or a Buffer // If we have the plaintext password - salt: await genKey(32), + salt: await SRP.genKey(32), password: 'password', // Or a Buffer // If we have a saved verifier @@ -55,9 +55,9 @@ import {Server, genKey, params} from 'fast-srp-hap'; }; // Generate a secret key - const secret = await genKey(32); + const secret = await SRP.genKey(32); - const server = new Server(params[3076], user, secret); // For Apple SRP use params.hap + const server = new SrpServer(SRP.params[3076], user, secret); // For Apple SRP use params.hap // ... })(); diff --git a/lib/jsbn.d.ts b/jsbn/jsbn.d.ts similarity index 100% rename from lib/jsbn.d.ts rename to jsbn/jsbn.d.ts diff --git a/lib/jsbn.js b/jsbn/jsbn.js similarity index 100% rename from lib/jsbn.js rename to jsbn/jsbn.js diff --git a/package-lock.json b/package-lock.json index a879f28..fa78037 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,13 @@ { "name": "fast-srp-hap", - "version": "1.1.0", + "version": "2.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { "@types/node": { - "version": "12.12.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.3.tgz", - "integrity": "sha512-opgSsy+cEF9N8MgaVPnWVtdJ3o4mV2aMHvDq7thkQUFt0EuOHJon4rQpJfhjmNHB+ikl0Cd6WhWIErOyQ+f7tw==", + "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 }, "balanced-match": { @@ -105,9 +105,9 @@ "dev": true }, "typescript": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.4.tgz", - "integrity": "sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg==", + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", + "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", "dev": true }, "vows": { diff --git a/package.json b/package.json index 9bddf97..b631b22 100644 --- a/package.json +++ b/package.json @@ -2,26 +2,34 @@ "name": "fast-srp-hap", "description": "Secure Remote Password (SRP)", "version": "1.1.0", - "main": "dist/index.js", + "main": "lib/srp.js", "scripts": { - "prepare": "rm -rf dist && tsc", - "test": "vows dist/test/test_*.js --spec" + "clean": "rm -rf lib", + "build": "npm run clean && tsc", + "prepublishOnly": "npm run build", + "postpublish": "npm run clean", + "test": "vows lib/test/test_*.js --spec" }, "repository": { "type": "git", - "url": "https://github.com/zarmack/fast-srp" + "url": "https://github.com/homebridge/fast-srp-hap" }, "author": "Zarmack Tanen", - "licence": "MIT", + "license": "MIT", + "engines": { + "node": ">=10.17.0" + }, "files": [ + "jsbn", "lib", - "dist/index.*", - "dist/lib" + "!lib/test", + "README.md", + "LICENSE" ], "dependencies": {}, "devDependencies": { - "@types/node": "^12.12.3", - "typescript": "^3.6.4", + "@types/node": "^10.17.19", + "typescript": "^3.8.3", "vows": "^0.8.3" } } diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index f69bb03..0000000 --- a/src/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -export * from './lib/srp'; - -export { - default as params, - SrpParams, -} from './lib/params'; - -export default module.exports; diff --git a/src/lib/params.ts b/src/params.ts similarity index 99% rename from src/lib/params.ts rename to src/params.ts index 91a0ce0..1e824ab 100644 --- a/src/lib/params.ts +++ b/src/params.ts @@ -14,7 +14,7 @@ // 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('../../lib/jsbn'); +import BigInteger = require('../jsbn/jsbn'); export function hex(s: string) { return new BigInteger(s.split(/\s|\n/).join(''), 16); @@ -27,9 +27,7 @@ export interface SrpParams { hash: string; } -const params: { - [n: string]: SrpParams; -} = { +export const params = { 1024: { N_length_bits: 1024, N: hex(` diff --git a/src/lib/srp.ts b/src/srp.ts similarity index 81% rename from src/lib/srp.ts rename to src/srp.ts index d8efc5d..da05f71 100644 --- a/src/lib/srp.ts +++ b/src/srp.ts @@ -1,10 +1,11 @@ -import * as crypto from 'crypto'; -import * as assert from 'assert'; -import BigInteger = require('../../lib/jsbn'); +import crypto from 'crypto'; +import assert from 'assert'; +import BigInteger = require('../jsbn/jsbn'); +import {SrpParams, params as srpParams} from './params'; -import {SrpParams} from './params'; +export { SrpParams } from './params'; -var zero = new BigInteger(0, 10); +const zero = new BigInteger(0, 10); function assert_(val: any, msg: string) { if (!val) @@ -34,7 +35,7 @@ function padTo(n: Buffer, len: number) { function padToN(number: BigInteger, params: SrpParams) { assertIsBigInteger(number); - var n = number.toString(16).length % 2 != 0 ? '0' + number.toString(16) : number.toString(16); + 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); } @@ -66,35 +67,68 @@ function getx(params: SrpParams, salt: Buffer, I: Buffer, P: Buffer) { const hashIP = crypto.createHash(params.hash) .update(Buffer.concat([I, Buffer.from(':'), P])) .digest(); - const hashX = crypto.createHash(params.hash) + const hashX: Buffer = crypto.createHash(params.hash) .update(salt) .update(hashIP) .digest(); return new BigInteger(hashX); } -/** - * The verifier is calculated as described in Section 3 of [SRP-RFC]. - * We give the algorithm here for convenience. - * - * The verifier (v) is computed based on the salt (s), user name (I), - * password (P), and group parameters (N, g). - * - * x = H(s | H(I | ":" | P)) - * v = g^x % N - * - * @param {object} params Group parameters, with .N, .g, .hash - * @param {Buffer} salt - * @param {Buffer} I User identity - * @param {Buffer} P User password - * @return {Buffer} - */ -export function computeVerifier(params: SrpParams, salt: Buffer, I: Buffer, P: Buffer) { - assertIsBuffer(salt, 'salt (salt)'); - assertIsBuffer(I, 'identity (I)'); - assertIsBuffer(P, 'password (P)'); - var v_num = params.g.modPow(getx(params, salt, I, P), params.N); - return v_num.toBuffer(params.N_length_bits / 8); +export type GenKeyCallback = (err: Error | null, data: Buffer | null) => void; + +export class SRP { + + public static readonly params = srpParams; + + /** + * The verifier is calculated as described in Section 3 of [SRP-RFC]. + * We give the algorithm here for convenience. + * + * The verifier (v) is computed based on the salt (s), user name (I), + * password (P), and group parameters (N, g). + * + * x = H(s | H(I | ":" | P)) + * v = g^x % N + * + * @param {object} params Group parameters, with .N, .g, .hash + * @param {Buffer} salt + * @param {Buffer} I User identity + * @param {Buffer} P User password + * @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)'); + const v_num = params.g.modPow(getx(params, salt, I, P), params.N); + return v_num.toBuffer(params.N_length_bits / 8); + } + + /** + * Generate a random key. + * + * @param {number} [bytes=32] Length of key + * @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') { + 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!))); + + crypto.randomBytes(bytes, (err, buf) => { + if (err) return callback!(err, null); + return callback!(null, buf); + }); + } + } /** @@ -113,32 +147,6 @@ function getk(params: SrpParams) { return new BigInteger(k_buf); } -/** - * Generate a random key. - * - * @param {number} [bytes=32] Length of key - * @param {function} [callback] If not provided a Promise is returned - * @return {Promise|void} - */ -type GenKeyCallback = (err: Error | null, data: Buffer | null) => void; -export function genKey(callback: GenKeyCallback): void -export function genKey(bytes: number, callback: GenKeyCallback): void -export function genKey(bytes?: number): Promise -export function genKey(bytes: number | GenKeyCallback = 32, callback?: GenKeyCallback): Promise | void { - // bytes is optional - if (typeof bytes !== 'number') { - callback = bytes as unknown as GenKeyCallback; - bytes = 32; - } - - if (!callback) return new Promise((rs, rj) => genKey(bytes as number, (err, data) => err ? rj(err) : rs(data!))); - - crypto.randomBytes(bytes, (err, buf) => { - if (err) return callback!(err, null); - return callback!(null, buf); - }); -} - /** * The server key exchange message also contains the server's public * value (B). The server calculates this value as B = k*v + g^b % N, @@ -147,7 +155,8 @@ export function genKey(bytes: number | GenKeyCallback = 32, callback?: GenKeyCal * * Note: as the tests imply, the entire expression is mod N. * - * @param {object} params Group parameters, with .N, .g, .hash + * @param {SrpParams} params Group parameters, with .N, .g, .hash + * @param {BigInteger} k * @param {BigInteger} v Verifier (stored) * @param {BigInteger} b Server secret exponent * @return {Buffer} B - The server public message @@ -168,7 +177,7 @@ function getB(params: SrpParams, k: BigInteger, v: BigInteger, b: BigInteger) { * Note: for this implementation, we take that to mean 256/8 bytes. * * @param {object} params Group parameters, with .N, .g, .hash - * @param {BigInteger} a Client secret exponent + * @param {BigInteger} a_num Client secret exponent * @return {BigInteger} A - The client public message */ function getA(params: SrpParams, a_num: BigInteger) { @@ -231,10 +240,10 @@ function client_getS(params: SrpParams, k_num: BigInteger, x_num: BigInteger, a_ * The TLS premastersecret as calculated by the server * * @param {BigInteger} params Group parameters, with .N, .g, .hash - * @param {BigInteger} v Verifier (stored on server) - * @param {BigInteger} A Ephemeral client public key (read from client) - * @param {BigInteger} b Server ephemeral private key (generated for session) - * @param {BigInteger} u {@see getu} + * @param {BigInteger} v_num Verifier (stored on server) + * @param {BigInteger} A_num Ephemeral client public key (read from client) + * @param {BigInteger} b_num Server ephemeral private key (generated for session) + * @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) { @@ -255,7 +264,7 @@ function server_getS(params: SrpParams, v_num: BigInteger, A_num: BigInteger, b_ * Compute the shared session key K from S * * @param {object} params Group parameters, with .N, .g, .hash - * @param {Buffer} S Session key + * @param {Buffer} S_buf Session key * @return {Buffer} */ function getK(params: SrpParams, S_buf: Buffer) { @@ -273,7 +282,7 @@ function getK(params: SrpParams, S_buf: Buffer) { } /** - * + * * @param params SRP params * @param u_buf User identity * @param s_buf User salt @@ -291,13 +300,13 @@ function getM1(params: SrpParams, u_buf: Buffer, s_buf: Buffer, A_buf: Buffer, B assertIsBuffer(B_buf!, 'server public key (B)'); assertIsBuffer(K_buf!, 'session key (K)'); - var hN = crypto.createHash(params.hash).update(params.N.toBuffer(true)).digest(); - var hG = crypto.createHash(params.hash).update(params.g.toBuffer(true)).digest(); + 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 (var i = 0; i < hN.length; i++) + for (let i = 0; i < hN.length; i++) hN[i] ^= hG[i]; - var hU = crypto.createHash(params.hash).update(u_buf).digest(); + const hU = crypto.createHash(params.hash).update(u_buf).digest(); return crypto.createHash(params.hash) .update(hN).update(hU).update(s_buf) @@ -332,19 +341,19 @@ function equal(buf1: Buffer, buf2: Buffer) { return buf1.toString('hex') === buf2.toString('hex'); } -export class Client { - private _params: SrpParams; - private _k: BigInteger; - private _x: BigInteger; +export class SrpClient { + private readonly _params: SrpParams; + private readonly _k: BigInteger; + private readonly _x: BigInteger; /** Client private key */ - private _a: BigInteger; + private readonly _a: BigInteger; /** Client public key */ - private _A: Buffer; + private readonly _A: Buffer; /** User identity */ - private _I?: Buffer; + private readonly _I?: Buffer; /** User salt */ - private _s?: Buffer; + private readonly _s?: Buffer; /** Session key */ private _K?: Buffer; @@ -386,7 +395,7 @@ export class Client { this._A = getA(params, this._a); } - + /** * Returns the client's public key (A). * @@ -395,7 +404,7 @@ export class Client { computeA() { return this._A; } - + /** * Sets the server's public key (B). * @@ -462,21 +471,21 @@ export type VerifierIdentity = BaseIdentity & {verifier: Buffer}; export type Identity = PasswordIdentity | VerifierIdentity; -export class Server { - private _params: SrpParams; +export class SrpServer { + private readonly _params: SrpParams; /** Multiplier parameter (H(N, g)) */ - private _k: BigInteger; + private readonly _k: BigInteger; /** Server private key */ - private _b: BigInteger; + private readonly _b: BigInteger; /** Server public key */ - private _B: Buffer; + private readonly _B: Buffer; /** Verifier */ - private _v: BigInteger; + private readonly _v: BigInteger; /** User identity */ - private _I?: Buffer; + private readonly _I?: Buffer; /** User salt */ - private _s?: Buffer; + private readonly _s?: Buffer; /** Session key */ _K?: Buffer; @@ -500,7 +509,7 @@ export class Server { * @param {Buffer} salt_buf User salt (from server) * @param {Buffer} identity_buf Identity/username * @param {Buffer} password_buf Password - * @param {Buffer} secret1_buf Client private key {@see genKey} + * @param {Buffer} secret2_buf Client private key {@see genKey} */ constructor(params: SrpParams, salt_buf: Buffer, identity_buf: Buffer, password_buf: Buffer, secret2_buf: Buffer) constructor(params: SrpParams, verifier_buf: Buffer, secret2_buf: Buffer) @@ -516,7 +525,7 @@ export class Server { assertIsBuffer(secret2_buf!, 'secret2'); this._b = new BigInteger(secret2_buf!); - this._v = new BigInteger(computeVerifier(params, salt_buf as Buffer, identity_buf!, password_buf!)); + this._v = new BigInteger(SRP.computeVerifier(params, salt_buf as Buffer, identity_buf!, password_buf!)); this._I = identity_buf; this._s = salt_buf as Buffer; @@ -533,6 +542,7 @@ export class Server { const identity = salt_buf as Identity; [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'); @@ -546,7 +556,7 @@ export class Server { if ('verifier' in identity) { this._v = new BigInteger(identity.verifier); } else { - this._v = new BigInteger(computeVerifier( + this._v = new BigInteger(SRP.computeVerifier( params, identity.salt, username, typeof identity.password === 'string' ? Buffer.from(identity.password) : identity.password )); diff --git a/src/test/hap_test_data.ts b/src/test/hap_test_data.ts index 653bd07..7c9469e 100644 --- a/src/test/hap_test_data.ts +++ b/src/test/hap_test_data.ts @@ -1,5 +1,4 @@ -import {hex} from '../lib/params'; -import BigInteger = require('../../lib/jsbn'); +import {hex} from '../params'; // Modulus (N), as specified by the 3072-bit group of RFC 5054 export const N = hex(` diff --git a/src/test/test_hap_vectors.ts b/src/test/test_hap_vectors.ts index e50e4f9..183c012 100644 --- a/src/test/test_hap_vectors.ts +++ b/src/test/test_hap_vectors.ts @@ -1,10 +1,8 @@ // @ts-ignore -import * as vows from 'vows'; -import * as assert from 'assert'; -import * as srp from '..'; -import BigInteger = require('../../lib/jsbn'); - -delete exports.__esModule; +import vows from 'vows'; +import assert from 'assert'; +import {SRP, SrpClient, SrpParams, SrpServer} from "../srp"; +import BigInteger = require('../../jsbn/jsbn'); interface Input { /** Identity */ @@ -36,7 +34,7 @@ interface ExpectedOutput { import {N, g, I, p, a, A, b, B, s, v, u, S, K} from './hap_test_data'; -const params = srp.params.hap; +const params = SRP.params.hap; const inputs: Input = { I: Buffer.from(I, 'ascii'), @@ -77,14 +75,14 @@ function numequal(a: BigInteger, b: BigInteger, msg?: string) { assert(a.compareTo(b) === 0, msg); } -function checkVectors(params: srp.SrpParams, inputs: Input, expected: ExpectedOutput, useVerifier = true) { +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'); + hexequal(SRP.computeVerifier(params, inputs.salt, inputs.I, inputs.P), expected.v, 'v'); - const client = new srp.Client(params, inputs.salt, inputs.I, inputs.P, inputs.a, true); + const client = new SrpClient(params, inputs.salt, inputs.I, inputs.P, inputs.a, true); const server = useVerifier ? - new srp.Server(params, {username: inputs.I, salt: inputs.salt, verifier: expected.v}, inputs.b) : - new srp.Server(params, inputs.salt, inputs.I, inputs.P, inputs.b); + new SrpServer(params, {username: inputs.I, salt: inputs.salt, verifier: expected.v}, inputs.b) : + new SrpServer(params, inputs.salt, inputs.I, inputs.P, inputs.b); // @ts-ignore numequal(client._k, new BigInteger(expected.k.toString('hex'), 16), 'k'); diff --git a/src/test/test_picl_vectors.ts b/src/test/test_picl_vectors.ts index 3ded3f2..8942bf0 100644 --- a/src/test/test_picl_vectors.ts +++ b/src/test/test_picl_vectors.ts @@ -1,10 +1,8 @@ // @ts-ignore -import * as vows from 'vows'; -import * as assert from 'assert'; -import * as srp from '..'; -import BigInteger = require('../../lib/jsbn'); - -delete exports.__esModule; +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 @@ -19,7 +17,7 @@ function hex(s: string) { return Buffer.from(s.split(/\s/).join(''), 'hex'); } -const params = srp.params[2048]; +const params = SRP.params[2048]; interface Input { /** Identity */ @@ -318,12 +316,12 @@ function numequal(a: BigInteger, b: BigInteger, msg?: string) { assert(a.compareTo(b) === 0, msg); } -function checkVectors(params: srp.SrpParams, inputs: Input, expected: ExpectedOutput) { +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'); + hexequal(SRP.computeVerifier(params, inputs.salt, inputs.I, inputs.P), expected.v, 'v'); - const client = new srp.Client(params, inputs.salt, inputs.I, inputs.P, inputs.a, false); - const server = new srp.Server(params, expected.v, inputs.b); + 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'); diff --git a/src/test/test_rfc_5054.ts b/src/test/test_rfc_5054.ts index 9986000..9d7e8cd 100644 --- a/src/test/test_rfc_5054.ts +++ b/src/test/test_rfc_5054.ts @@ -1,12 +1,10 @@ // @ts-ignore -import * as vows from 'vows'; -import * as assert from 'assert'; -import * as srp from '..'; -import BigInteger = require('../../lib/jsbn'); +import vows from 'vows'; +import assert from 'assert'; +import {SRP, SrpClient, SrpServer} from '../srp'; +import BigInteger = require('../../jsbn/jsbn'); -delete exports.__esModule; - -const params = srp.params[1024]; +const params = SRP.params[1024]; /* * http://tools.ietf.org/html/rfc5054#appendix-B @@ -60,11 +58,11 @@ function asHex(num: number | BigInteger) { vows.describe('RFC 5054').addBatch({ 'Test vectors': { topic() { - return srp.computeVerifier(params, s, I, P); + return SRP.computeVerifier(params, s, I, P); }, 'x'() { - const client = new srp.Client(params, s, I, P, a, false); + const client = new SrpClient(params, s, I, P, a, false); // @ts-ignore assert.equal(asHex(client._x), x_expected); }, @@ -74,37 +72,37 @@ vows.describe('RFC 5054').addBatch({ }, 'k'() { - const client = new srp.Client(params, s, I, P, a, false); + const client = new SrpClient(params, s, I, P, a, false); // @ts-ignore assert.equal(asHex(client._k), k_expected); }, 'A'() { - const client = new srp.Client(params, s, I, P, a, false); + const client = new SrpClient(params, s, I, P, a, false); assert.equal(client.computeA().toString('hex'), A_expected); }, 'B'(v: Buffer) { - const server = new srp.Server(params, v, b); + const server = new SrpServer(params, v, b); assert.equal(server.computeB().toString('hex'), B_expected); }, 'u'() { - const client = new srp.Client(params, s, I, P, a, false); + const client = new SrpClient(params, s, I, P, a, false); client.setB(Buffer.from(B_expected, 'hex')); // @ts-ignore assert.equal(asHex(client._u), u_expected); }, 'S client'() { - const client = new srp.Client(params, s, I, P, a, false); + const client = new SrpClient(params, s, I, P, a, false); client.setB(Buffer.from(B_expected, 'hex')); // @ts-ignore assert.equal(client._S.toString('hex'), S_expected); }, 'S server'(v: Buffer) { - const server = new srp.Server(params, v, b); + const server = new SrpServer(params, v, b); server.setA(Buffer.from(A_expected, 'hex')); // @ts-ignore assert.equal(server._S.toString('hex'), S_expected); diff --git a/src/test/test_srp.ts b/src/test/test_srp.ts index 9b01d36..9e36209 100644 --- a/src/test/test_srp.ts +++ b/src/test/test_srp.ts @@ -1,11 +1,9 @@ // @ts-ignore -import * as vows from 'vows'; -import * as assert from 'assert'; -import * as srp from '..'; +import vows from 'vows'; +import assert from 'assert'; +import {SRP, SrpClient, SrpServer} from '../srp'; -delete exports.__esModule; - -const params = srp.params[4096]; +const params = SRP.params[4096]; const salt = Buffer.from('salty'); const identity = Buffer.from('alice'); @@ -13,7 +11,7 @@ const password = Buffer.from('password123'); assert(params, 'missing parameters'); -let client: srp.Client, server: srp.Server; +let client: SrpClient, server: SrpServer; let a: Buffer, A: Buffer; let b: Buffer, B: Buffer; let verifier: Buffer; @@ -21,25 +19,25 @@ let verifier: Buffer; vows.describe('srp.js').addBatch({ 'create Verifier'() { - verifier = srp.computeVerifier(params, salt, identity, password); + verifier = SRP.computeVerifier(params, salt, identity, password); assert.equal(verifier.toString('hex'), 'f0e47f50f5dead8db8d93a279e3b62d6ff50854b31fbd3474a886bef916261717e84dd4fb8b4d27feaa5146db7b1cbbc274fdf96a132b5029c2cd72527427a9b9809d5a4d018252928b4fc343bc17ce63c1859d5806f5466014fc361002d8890aeb4d6316ff37331fc2761be0144c91cdd8e00ed0138c0ce51534d1b9a9ba629d7be34d2742dd4097daabc9ecb7aaad89e53c342b038f1d2adae1f2410b7884a3e9a124c357e421bccd4524467e1922660e0a4460c5f7c38c0877b65f6e32f28296282a93fc11bbabb7bb69bf1b3f9391991d8a86dd05e15000b7e38ba38a536bb0bf59c808ec25e791b8944719488b8087df8bfd7ff20822997a53f6c86f3d45d004476d6303301376bb25a9f94b552cce5ed40de5dd7da8027d754fa5f66738c7e3fc4ef3e20d625df62cbe6e7adfc21e47880d8a6ada37e60370fd4d8fc82672a90c29f2e72f35652649d68348de6f36d0e435c8bd42dd00155d35d501becc0661b43e04cdb2da84ce92b8bf49935d73d75efcbd1176d7bbccc3cc4d4b5fefcc02d478614ee1681d2ff3c711a61a7686eb852ae06fb8227be21fb8802719b1271ba1c02b13bbf0a2c2e459d9bedcc8d1269f6a785cb4563aa791b38fb038269f63f58f47e9051499549789269cc7b8ec7026fc34ba73289c4af829d5a532e723967ce9b6c023ef0fd0cfe37f51f10f19463b6534159a09ddd2f51f3b30033'); }, 'create a and b': { topic(this: any) {(async () => { - a = await srp.genKey(64); - b = await srp.genKey(32); + a = await SRP.genKey(64); + b = await SRP.genKey(32); this.callback(); })()}, 'use a and b'() { - client = new srp.Client(params, salt, identity, password, a, false); + client = new SrpClient(params, salt, identity, password, a, false); // client produces A A = client.computeA(); // create server - server = new srp.Server(params, verifier, b); + server = new SrpServer(params, verifier, b); // server produces B B = server.computeB(); @@ -70,8 +68,8 @@ vows.describe('srp.js').addBatch({ }, 'server rejects wrong M1'() { - const bad_client = new srp.Client(params, salt, identity, Buffer.from('bad'), a, false); - const server2 = new srp.Server(params, verifier, b); + 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/); }, @@ -81,7 +79,7 @@ vows.describe('srp.js').addBatch({ // reject 2*N too, but our Buffer-length checks reject it before the // number itself is examined. - var server2 = new srp.Server(params, verifier, b); + var server2 = new SrpServer(params, verifier, b); var Azero = Buffer.alloc(params.N_length_bits / 8); Azero.fill(0); //! var AN = params.N.toBuffer(); @@ -95,7 +93,7 @@ vows.describe('srp.js').addBatch({ 'client rejects bad B'() { // server's "B" must be 1..N-1 . Reject 0 and N and N+1 - var client2 = new srp.Client(params, salt, identity, password, a, false); + var client2 = new SrpClient(params, salt, identity, password, a, false); var Bzero = Buffer.alloc(params.N_length_bits / 8); Bzero.fill(0, 0, params.N_length_bits / 8); //! var BN = params.N.toBuffer(); @@ -108,13 +106,13 @@ vows.describe('srp.js').addBatch({ }, 'client rejects bad M2'() { - client = new srp.Client(params, salt, identity, password, a, false); + client = new SrpClient(params, salt, identity, password, a, false); // client produces A A = client.computeA(); // create server - server = new srp.Server(params, verifier, b); + server = new SrpServer(params, verifier, b); // server produces B B = server.computeB(); diff --git a/tsconfig.json b/tsconfig.json index 4bc56a1..3fff87a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,12 +1,22 @@ { "compilerOptions": { - "strict": true, + "target": "ES2018", + "module": "commonjs", + "lib": [ + "es2015", + "es2016", + "es2017", + "es2018" + ], "declaration": true, + "declarationMap": true, "sourceMap": true, + "outDir": "lib", "rootDir": "src", - "outDir": "dist" + "strict": true, + "esModuleInterop": true }, "include": [ - "src/**/*" + "src/" ] }