mirror of
https://github.com/danog/fast-srp.git
synced 2024-11-30 04:19:18 +01:00
Restructured the project a bit
This commit is contained in:
parent
d8e2938064
commit
462b688de4
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,2 @@
|
|||||||
node_modules
|
node_modules
|
||||||
dist
|
lib
|
||||||
|
14
README.md
14
README.md
@ -9,7 +9,7 @@ Creating the Verifier
|
|||||||
---
|
---
|
||||||
|
|
||||||
```ts
|
```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.
|
* 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}>}
|
* @return {Promise<{salt: Buffer, verifier: Buffer}>}
|
||||||
*/
|
*/
|
||||||
async function srp6a_create_user(I: string, P: string) {
|
async function srp6a_create_user(I: string, P: string) {
|
||||||
const salt = await srp6a.genKey(32);
|
const salt = await SRP.genKey(32);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// The salt is required for authenticating the user later
|
// The salt is required for authenticating the user later
|
||||||
salt,
|
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
|
```ts
|
||||||
import {Server, genKey, params} from 'fast-srp-hap';
|
import {SRP, SrpServer} from 'fast-srp-hap';
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
// Get the user details from somewhere
|
// Get the user details from somewhere
|
||||||
@ -46,7 +46,7 @@ import {Server, genKey, params} from 'fast-srp-hap';
|
|||||||
username: 'username', // Or a Buffer
|
username: 'username', // Or a Buffer
|
||||||
|
|
||||||
// If we have the plaintext password
|
// If we have the plaintext password
|
||||||
salt: await genKey(32),
|
salt: await SRP.genKey(32),
|
||||||
password: 'password', // Or a Buffer
|
password: 'password', // Or a Buffer
|
||||||
|
|
||||||
// If we have a saved verifier
|
// If we have a saved verifier
|
||||||
@ -55,9 +55,9 @@ import {Server, genKey, params} from 'fast-srp-hap';
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Generate a secret key
|
// 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
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
})();
|
})();
|
||||||
|
0
lib/jsbn.d.ts → jsbn/jsbn.d.ts
vendored
0
lib/jsbn.d.ts → jsbn/jsbn.d.ts
vendored
14
package-lock.json
generated
14
package-lock.json
generated
@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "fast-srp-hap",
|
"name": "fast-srp-hap",
|
||||||
"version": "1.1.0",
|
"version": "2.0.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "12.12.3",
|
"version": "10.17.19",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.19.tgz",
|
||||||
"integrity": "sha512-opgSsy+cEF9N8MgaVPnWVtdJ3o4mV2aMHvDq7thkQUFt0EuOHJon4rQpJfhjmNHB+ikl0Cd6WhWIErOyQ+f7tw==",
|
"integrity": "sha512-46/xThm3zvvc9t9/7M3AaLEqtOpqlYYYcCZbpYVAQHG20+oMZBkae/VMrn4BTi6AJ8cpack0mEXhGiKmDNbLrQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
@ -105,9 +105,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"typescript": {
|
"typescript": {
|
||||||
"version": "3.6.4",
|
"version": "3.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.4.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz",
|
||||||
"integrity": "sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg==",
|
"integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"vows": {
|
"vows": {
|
||||||
|
26
package.json
26
package.json
@ -2,26 +2,34 @@
|
|||||||
"name": "fast-srp-hap",
|
"name": "fast-srp-hap",
|
||||||
"description": "Secure Remote Password (SRP)",
|
"description": "Secure Remote Password (SRP)",
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"main": "dist/index.js",
|
"main": "lib/srp.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prepare": "rm -rf dist && tsc",
|
"clean": "rm -rf lib",
|
||||||
"test": "vows dist/test/test_*.js --spec"
|
"build": "npm run clean && tsc",
|
||||||
|
"prepublishOnly": "npm run build",
|
||||||
|
"postpublish": "npm run clean",
|
||||||
|
"test": "vows lib/test/test_*.js --spec"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/zarmack/fast-srp"
|
"url": "https://github.com/homebridge/fast-srp-hap"
|
||||||
},
|
},
|
||||||
"author": "Zarmack Tanen",
|
"author": "Zarmack Tanen",
|
||||||
"licence": "MIT",
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.17.0"
|
||||||
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
"jsbn",
|
||||||
"lib",
|
"lib",
|
||||||
"dist/index.*",
|
"!lib/test",
|
||||||
"dist/lib"
|
"README.md",
|
||||||
|
"LICENSE"
|
||||||
],
|
],
|
||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^12.12.3",
|
"@types/node": "^10.17.19",
|
||||||
"typescript": "^3.6.4",
|
"typescript": "^3.8.3",
|
||||||
"vows": "^0.8.3"
|
"vows": "^0.8.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
export * from './lib/srp';
|
|
||||||
|
|
||||||
export {
|
|
||||||
default as params,
|
|
||||||
SrpParams,
|
|
||||||
} from './lib/params';
|
|
||||||
|
|
||||||
export default module.exports;
|
|
@ -14,7 +14,7 @@
|
|||||||
// since these are meant to be used internally, all values are numbers. If
|
// 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.
|
// 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) {
|
export function hex(s: string) {
|
||||||
return new BigInteger(s.split(/\s|\n/).join(''), 16);
|
return new BigInteger(s.split(/\s|\n/).join(''), 16);
|
||||||
@ -27,9 +27,7 @@ export interface SrpParams {
|
|||||||
hash: string;
|
hash: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const params: {
|
export const params = {
|
||||||
[n: string]: SrpParams;
|
|
||||||
} = {
|
|
||||||
1024: {
|
1024: {
|
||||||
N_length_bits: 1024,
|
N_length_bits: 1024,
|
||||||
N: hex(`
|
N: hex(`
|
@ -1,10 +1,11 @@
|
|||||||
import * as crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import * as assert from 'assert';
|
import assert from 'assert';
|
||||||
import BigInteger = require('../../lib/jsbn');
|
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) {
|
function assert_(val: any, msg: string) {
|
||||||
if (!val)
|
if (!val)
|
||||||
@ -34,7 +35,7 @@ function padTo(n: Buffer, len: number) {
|
|||||||
|
|
||||||
function padToN(number: BigInteger, params: SrpParams) {
|
function padToN(number: BigInteger, params: SrpParams) {
|
||||||
assertIsBigInteger(number);
|
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);
|
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)
|
const hashIP = crypto.createHash(params.hash)
|
||||||
.update(Buffer.concat([I, Buffer.from(':'), P]))
|
.update(Buffer.concat([I, Buffer.from(':'), P]))
|
||||||
.digest();
|
.digest();
|
||||||
const hashX = crypto.createHash(params.hash)
|
const hashX: Buffer = crypto.createHash(params.hash)
|
||||||
.update(salt)
|
.update(salt)
|
||||||
.update(hashIP)
|
.update(hashIP)
|
||||||
.digest();
|
.digest();
|
||||||
return new BigInteger(hashX);
|
return new BigInteger(hashX);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export type GenKeyCallback = (err: Error | null, data: Buffer | null) => void;
|
||||||
* The verifier is calculated as described in Section 3 of [SRP-RFC].
|
|
||||||
* We give the algorithm here for convenience.
|
export class SRP {
|
||||||
*
|
|
||||||
* The verifier (v) is computed based on the salt (s), user name (I),
|
public static readonly params = srpParams;
|
||||||
* password (P), and group parameters (N, g).
|
|
||||||
*
|
/**
|
||||||
* x = H(s | H(I | ":" | P))
|
* The verifier is calculated as described in Section 3 of [SRP-RFC].
|
||||||
* v = g^x % N
|
* We give the algorithm here for convenience.
|
||||||
*
|
*
|
||||||
* @param {object} params Group parameters, with .N, .g, .hash
|
* The verifier (v) is computed based on the salt (s), user name (I),
|
||||||
* @param {Buffer} salt
|
* password (P), and group parameters (N, g).
|
||||||
* @param {Buffer} I User identity
|
*
|
||||||
* @param {Buffer} P User password
|
* x = H(s | H(I | ":" | P))
|
||||||
* @return {Buffer}
|
* v = g^x % N
|
||||||
*/
|
*
|
||||||
export function computeVerifier(params: SrpParams, salt: Buffer, I: Buffer, P: Buffer) {
|
* @param {object} params Group parameters, with .N, .g, .hash
|
||||||
assertIsBuffer(salt, 'salt (salt)');
|
* @param {Buffer} salt
|
||||||
assertIsBuffer(I, 'identity (I)');
|
* @param {Buffer} I User identity
|
||||||
assertIsBuffer(P, 'password (P)');
|
* @param {Buffer} P User password
|
||||||
var v_num = params.g.modPow(getx(params, salt, I, P), params.N);
|
* @return {Buffer}
|
||||||
return v_num.toBuffer(params.N_length_bits / 8);
|
*/
|
||||||
|
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<Buffer>;
|
||||||
|
public static genKey(bytes: number | GenKeyCallback = 32, callback?: GenKeyCallback): Promise<Buffer> | 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);
|
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<Buffer>
|
|
||||||
export function genKey(bytes: number | GenKeyCallback = 32, callback?: GenKeyCallback): Promise<Buffer> | 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
|
* 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,
|
* 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.
|
* 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} v Verifier (stored)
|
||||||
* @param {BigInteger} b Server secret exponent
|
* @param {BigInteger} b Server secret exponent
|
||||||
* @return {Buffer} B - The server public message
|
* @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.
|
* Note: for this implementation, we take that to mean 256/8 bytes.
|
||||||
*
|
*
|
||||||
* @param {object} params Group parameters, with .N, .g, .hash
|
* @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
|
* @return {BigInteger} A - The client public message
|
||||||
*/
|
*/
|
||||||
function getA(params: SrpParams, a_num: BigInteger) {
|
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
|
* The TLS premastersecret as calculated by the server
|
||||||
*
|
*
|
||||||
* @param {BigInteger} params Group parameters, with .N, .g, .hash
|
* @param {BigInteger} params Group parameters, with .N, .g, .hash
|
||||||
* @param {BigInteger} v Verifier (stored on server)
|
* @param {BigInteger} v_num Verifier (stored on server)
|
||||||
* @param {BigInteger} A Ephemeral client public key (read from client)
|
* @param {BigInteger} A_num Ephemeral client public key (read from client)
|
||||||
* @param {BigInteger} b Server ephemeral private key (generated for session)
|
* @param {BigInteger} b_num Server ephemeral private key (generated for session)
|
||||||
* @param {BigInteger} u {@see getu}
|
* @param {BigInteger} u_num {@see getu}
|
||||||
* @return {Buffer}
|
* @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) {
|
||||||
@ -255,7 +264,7 @@ function server_getS(params: SrpParams, v_num: BigInteger, A_num: BigInteger, b_
|
|||||||
* Compute the shared session key K from S
|
* Compute the shared session key K from S
|
||||||
*
|
*
|
||||||
* @param {object} params Group parameters, with .N, .g, .hash
|
* @param {object} params Group parameters, with .N, .g, .hash
|
||||||
* @param {Buffer} S Session key
|
* @param {Buffer} S_buf Session key
|
||||||
* @return {Buffer}
|
* @return {Buffer}
|
||||||
*/
|
*/
|
||||||
function getK(params: SrpParams, S_buf: Buffer) {
|
function getK(params: SrpParams, S_buf: Buffer) {
|
||||||
@ -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(B_buf!, 'server public key (B)');
|
||||||
assertIsBuffer(K_buf!, 'session key (K)');
|
assertIsBuffer(K_buf!, 'session key (K)');
|
||||||
|
|
||||||
var hN = crypto.createHash(params.hash).update(params.N.toBuffer(true)).digest();
|
const hN = crypto.createHash(params.hash).update(params.N.toBuffer(true)).digest();
|
||||||
var hG = crypto.createHash(params.hash).update(params.g.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];
|
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)
|
return crypto.createHash(params.hash)
|
||||||
.update(hN).update(hU).update(s_buf)
|
.update(hN).update(hU).update(s_buf)
|
||||||
@ -332,19 +341,19 @@ function equal(buf1: Buffer, buf2: Buffer) {
|
|||||||
return buf1.toString('hex') === buf2.toString('hex');
|
return buf1.toString('hex') === buf2.toString('hex');
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Client {
|
export class SrpClient {
|
||||||
private _params: SrpParams;
|
private readonly _params: SrpParams;
|
||||||
private _k: BigInteger;
|
private readonly _k: BigInteger;
|
||||||
private _x: BigInteger;
|
private readonly _x: BigInteger;
|
||||||
/** Client private key */
|
/** Client private key */
|
||||||
private _a: BigInteger;
|
private readonly _a: BigInteger;
|
||||||
/** Client public key */
|
/** Client public key */
|
||||||
private _A: Buffer;
|
private readonly _A: Buffer;
|
||||||
|
|
||||||
/** User identity */
|
/** User identity */
|
||||||
private _I?: Buffer;
|
private readonly _I?: Buffer;
|
||||||
/** User salt */
|
/** User salt */
|
||||||
private _s?: Buffer;
|
private readonly _s?: Buffer;
|
||||||
|
|
||||||
/** Session key */
|
/** Session key */
|
||||||
private _K?: Buffer;
|
private _K?: Buffer;
|
||||||
@ -462,21 +471,21 @@ export type VerifierIdentity = BaseIdentity & {verifier: Buffer};
|
|||||||
|
|
||||||
export type Identity = PasswordIdentity | VerifierIdentity;
|
export type Identity = PasswordIdentity | VerifierIdentity;
|
||||||
|
|
||||||
export class Server {
|
export class SrpServer {
|
||||||
private _params: SrpParams;
|
private readonly _params: SrpParams;
|
||||||
/** Multiplier parameter (H(N, g)) */
|
/** Multiplier parameter (H(N, g)) */
|
||||||
private _k: BigInteger;
|
private readonly _k: BigInteger;
|
||||||
/** Server private key */
|
/** Server private key */
|
||||||
private _b: BigInteger;
|
private readonly _b: BigInteger;
|
||||||
/** Server public key */
|
/** Server public key */
|
||||||
private _B: Buffer;
|
private readonly _B: Buffer;
|
||||||
/** Verifier */
|
/** Verifier */
|
||||||
private _v: BigInteger;
|
private readonly _v: BigInteger;
|
||||||
|
|
||||||
/** User identity */
|
/** User identity */
|
||||||
private _I?: Buffer;
|
private readonly _I?: Buffer;
|
||||||
/** User salt */
|
/** User salt */
|
||||||
private _s?: Buffer;
|
private readonly _s?: Buffer;
|
||||||
|
|
||||||
/** Session key */
|
/** Session key */
|
||||||
_K?: Buffer;
|
_K?: Buffer;
|
||||||
@ -500,7 +509,7 @@ export class Server {
|
|||||||
* @param {Buffer} salt_buf User salt (from server)
|
* @param {Buffer} salt_buf User salt (from server)
|
||||||
* @param {Buffer} identity_buf Identity/username
|
* @param {Buffer} identity_buf Identity/username
|
||||||
* @param {Buffer} password_buf Password
|
* @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, salt_buf: Buffer, identity_buf: Buffer, password_buf: Buffer, secret2_buf: Buffer)
|
||||||
constructor(params: SrpParams, verifier_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');
|
assertIsBuffer(secret2_buf!, 'secret2');
|
||||||
|
|
||||||
this._b = new BigInteger(secret2_buf!);
|
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._I = identity_buf;
|
||||||
this._s = salt_buf as Buffer;
|
this._s = salt_buf as Buffer;
|
||||||
@ -533,6 +542,7 @@ export class Server {
|
|||||||
const identity = salt_buf as Identity;
|
const identity = salt_buf as Identity;
|
||||||
[secret2_buf, salt_buf, identity_buf, password_buf] = [identity_buf, undefined, undefined, undefined];
|
[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');
|
assert(identity.username instanceof Buffer || typeof identity.username === 'string', 'identity.username (I) must be a string or Buffer');
|
||||||
assertIsBuffer(identity.salt, 'identity.salt (s)');
|
assertIsBuffer(identity.salt, 'identity.salt (s)');
|
||||||
assert('password' in identity || 'verifier' in identity, 'identity requires a password or verifier');
|
assert('password' in identity || 'verifier' in identity, 'identity requires a password or verifier');
|
||||||
@ -546,7 +556,7 @@ export class Server {
|
|||||||
if ('verifier' in identity) {
|
if ('verifier' in identity) {
|
||||||
this._v = new BigInteger(identity.verifier);
|
this._v = new BigInteger(identity.verifier);
|
||||||
} else {
|
} else {
|
||||||
this._v = new BigInteger(computeVerifier(
|
this._v = new BigInteger(SRP.computeVerifier(
|
||||||
params, identity.salt, username,
|
params, identity.salt, username,
|
||||||
typeof identity.password === 'string' ? Buffer.from(identity.password) : identity.password
|
typeof identity.password === 'string' ? Buffer.from(identity.password) : identity.password
|
||||||
));
|
));
|
@ -1,5 +1,4 @@
|
|||||||
import {hex} from '../lib/params';
|
import {hex} from '../params';
|
||||||
import BigInteger = require('../../lib/jsbn');
|
|
||||||
|
|
||||||
// Modulus (N), as specified by the 3072-bit group of RFC 5054
|
// Modulus (N), as specified by the 3072-bit group of RFC 5054
|
||||||
export const N = hex(`
|
export const N = hex(`
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import * as vows from 'vows';
|
import vows from 'vows';
|
||||||
import * as assert from 'assert';
|
import assert from 'assert';
|
||||||
import * as srp from '..';
|
import {SRP, SrpClient, SrpParams, SrpServer} from "../srp";
|
||||||
import BigInteger = require('../../lib/jsbn');
|
import BigInteger = require('../../jsbn/jsbn');
|
||||||
|
|
||||||
delete exports.__esModule;
|
|
||||||
|
|
||||||
interface Input {
|
interface Input {
|
||||||
/** Identity */
|
/** 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';
|
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 = {
|
const inputs: Input = {
|
||||||
I: Buffer.from(I, 'ascii'),
|
I: Buffer.from(I, 'ascii'),
|
||||||
@ -77,14 +75,14 @@ function numequal(a: BigInteger, b: BigInteger, msg?: string) {
|
|||||||
assert(a.compareTo(b) === 0, msg);
|
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(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 ?
|
const server = useVerifier ?
|
||||||
new srp.Server(params, {username: inputs.I, salt: inputs.salt, verifier: expected.v}, inputs.b) :
|
new SrpServer(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, inputs.salt, inputs.I, inputs.P, inputs.b);
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
numequal(client._k, new BigInteger(expected.k.toString('hex'), 16), 'k');
|
numequal(client._k, new BigInteger(expected.k.toString('hex'), 16), 'k');
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import * as vows from 'vows';
|
import vows from 'vows';
|
||||||
import * as assert from 'assert';
|
import assert from 'assert';
|
||||||
import * as srp from '..';
|
import {SRP, SrpClient, SrpParams, SrpServer} from '../srp';
|
||||||
import BigInteger = require('../../lib/jsbn');
|
import BigInteger = require('../../jsbn/jsbn');
|
||||||
|
|
||||||
delete exports.__esModule;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Vectors from https://wiki.mozilla.org/Identity/AttachedServices/KeyServerProtocol
|
* 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');
|
return Buffer.from(s.split(/\s/).join(''), 'hex');
|
||||||
}
|
}
|
||||||
|
|
||||||
const params = srp.params[2048];
|
const params = SRP.params[2048];
|
||||||
|
|
||||||
interface Input {
|
interface Input {
|
||||||
/** Identity */
|
/** Identity */
|
||||||
@ -318,12 +316,12 @@ function numequal(a: BigInteger, b: BigInteger, msg?: string) {
|
|||||||
assert(a.compareTo(b) === 0, msg);
|
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(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 client = new SrpClient(params, inputs.salt, inputs.I, inputs.P, inputs.a, false);
|
||||||
const server = new srp.Server(params, expected.v, inputs.b);
|
const server = new SrpServer(params, expected.v, inputs.b);
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
numequal(client._k, new BigInteger(expected.k.toString('hex'), 16), 'k');
|
numequal(client._k, new BigInteger(expected.k.toString('hex'), 16), 'k');
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import * as vows from 'vows';
|
import vows from 'vows';
|
||||||
import * as assert from 'assert';
|
import assert from 'assert';
|
||||||
import * as srp from '..';
|
import {SRP, SrpClient, SrpServer} from '../srp';
|
||||||
import BigInteger = require('../../lib/jsbn');
|
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
|
* http://tools.ietf.org/html/rfc5054#appendix-B
|
||||||
@ -60,11 +58,11 @@ function asHex(num: number | BigInteger) {
|
|||||||
vows.describe('RFC 5054').addBatch({
|
vows.describe('RFC 5054').addBatch({
|
||||||
'Test vectors': {
|
'Test vectors': {
|
||||||
topic() {
|
topic() {
|
||||||
return srp.computeVerifier(params, s, I, P);
|
return SRP.computeVerifier(params, s, I, P);
|
||||||
},
|
},
|
||||||
|
|
||||||
'x'() {
|
'x'() {
|
||||||
const client = new srp.Client(params, s, I, P, a, false);
|
const client = new SrpClient(params, s, I, P, a, false);
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
assert.equal(asHex(client._x), x_expected);
|
assert.equal(asHex(client._x), x_expected);
|
||||||
},
|
},
|
||||||
@ -74,37 +72,37 @@ vows.describe('RFC 5054').addBatch({
|
|||||||
},
|
},
|
||||||
|
|
||||||
'k'() {
|
'k'() {
|
||||||
const client = new srp.Client(params, s, I, P, a, false);
|
const client = new SrpClient(params, s, I, P, a, false);
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
assert.equal(asHex(client._k), k_expected);
|
assert.equal(asHex(client._k), k_expected);
|
||||||
},
|
},
|
||||||
|
|
||||||
'A'() {
|
'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);
|
assert.equal(client.computeA().toString('hex'), A_expected);
|
||||||
},
|
},
|
||||||
|
|
||||||
'B'(v: Buffer) {
|
'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);
|
assert.equal(server.computeB().toString('hex'), B_expected);
|
||||||
},
|
},
|
||||||
|
|
||||||
'u'() {
|
'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'));
|
client.setB(Buffer.from(B_expected, 'hex'));
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
assert.equal(asHex(client._u), u_expected);
|
assert.equal(asHex(client._u), u_expected);
|
||||||
},
|
},
|
||||||
|
|
||||||
'S client'() {
|
'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'));
|
client.setB(Buffer.from(B_expected, 'hex'));
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
assert.equal(client._S.toString('hex'), S_expected);
|
assert.equal(client._S.toString('hex'), S_expected);
|
||||||
},
|
},
|
||||||
|
|
||||||
'S server'(v: Buffer) {
|
'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'));
|
server.setA(Buffer.from(A_expected, 'hex'));
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
assert.equal(server._S.toString('hex'), S_expected);
|
assert.equal(server._S.toString('hex'), S_expected);
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import * as vows from 'vows';
|
import vows from 'vows';
|
||||||
import * as assert from 'assert';
|
import assert from 'assert';
|
||||||
import * as srp from '..';
|
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 salt = Buffer.from('salty');
|
||||||
const identity = Buffer.from('alice');
|
const identity = Buffer.from('alice');
|
||||||
@ -13,7 +11,7 @@ const password = Buffer.from('password123');
|
|||||||
|
|
||||||
assert(params, 'missing parameters');
|
assert(params, 'missing parameters');
|
||||||
|
|
||||||
let client: srp.Client, server: srp.Server;
|
let client: SrpClient, server: SrpServer;
|
||||||
let a: Buffer, A: Buffer;
|
let a: Buffer, A: Buffer;
|
||||||
let b: Buffer, B: Buffer;
|
let b: Buffer, B: Buffer;
|
||||||
let verifier: Buffer;
|
let verifier: Buffer;
|
||||||
@ -21,25 +19,25 @@ let verifier: Buffer;
|
|||||||
|
|
||||||
vows.describe('srp.js').addBatch({
|
vows.describe('srp.js').addBatch({
|
||||||
'create Verifier'() {
|
'create Verifier'() {
|
||||||
verifier = srp.computeVerifier(params, salt, identity, password);
|
verifier = SRP.computeVerifier(params, salt, identity, password);
|
||||||
assert.equal(verifier.toString('hex'), 'f0e47f50f5dead8db8d93a279e3b62d6ff50854b31fbd3474a886bef916261717e84dd4fb8b4d27feaa5146db7b1cbbc274fdf96a132b5029c2cd72527427a9b9809d5a4d018252928b4fc343bc17ce63c1859d5806f5466014fc361002d8890aeb4d6316ff37331fc2761be0144c91cdd8e00ed0138c0ce51534d1b9a9ba629d7be34d2742dd4097daabc9ecb7aaad89e53c342b038f1d2adae1f2410b7884a3e9a124c357e421bccd4524467e1922660e0a4460c5f7c38c0877b65f6e32f28296282a93fc11bbabb7bb69bf1b3f9391991d8a86dd05e15000b7e38ba38a536bb0bf59c808ec25e791b8944719488b8087df8bfd7ff20822997a53f6c86f3d45d004476d6303301376bb25a9f94b552cce5ed40de5dd7da8027d754fa5f66738c7e3fc4ef3e20d625df62cbe6e7adfc21e47880d8a6ada37e60370fd4d8fc82672a90c29f2e72f35652649d68348de6f36d0e435c8bd42dd00155d35d501becc0661b43e04cdb2da84ce92b8bf49935d73d75efcbd1176d7bbccc3cc4d4b5fefcc02d478614ee1681d2ff3c711a61a7686eb852ae06fb8227be21fb8802719b1271ba1c02b13bbf0a2c2e459d9bedcc8d1269f6a785cb4563aa791b38fb038269f63f58f47e9051499549789269cc7b8ec7026fc34ba73289c4af829d5a532e723967ce9b6c023ef0fd0cfe37f51f10f19463b6534159a09ddd2f51f3b30033');
|
assert.equal(verifier.toString('hex'), 'f0e47f50f5dead8db8d93a279e3b62d6ff50854b31fbd3474a886bef916261717e84dd4fb8b4d27feaa5146db7b1cbbc274fdf96a132b5029c2cd72527427a9b9809d5a4d018252928b4fc343bc17ce63c1859d5806f5466014fc361002d8890aeb4d6316ff37331fc2761be0144c91cdd8e00ed0138c0ce51534d1b9a9ba629d7be34d2742dd4097daabc9ecb7aaad89e53c342b038f1d2adae1f2410b7884a3e9a124c357e421bccd4524467e1922660e0a4460c5f7c38c0877b65f6e32f28296282a93fc11bbabb7bb69bf1b3f9391991d8a86dd05e15000b7e38ba38a536bb0bf59c808ec25e791b8944719488b8087df8bfd7ff20822997a53f6c86f3d45d004476d6303301376bb25a9f94b552cce5ed40de5dd7da8027d754fa5f66738c7e3fc4ef3e20d625df62cbe6e7adfc21e47880d8a6ada37e60370fd4d8fc82672a90c29f2e72f35652649d68348de6f36d0e435c8bd42dd00155d35d501becc0661b43e04cdb2da84ce92b8bf49935d73d75efcbd1176d7bbccc3cc4d4b5fefcc02d478614ee1681d2ff3c711a61a7686eb852ae06fb8227be21fb8802719b1271ba1c02b13bbf0a2c2e459d9bedcc8d1269f6a785cb4563aa791b38fb038269f63f58f47e9051499549789269cc7b8ec7026fc34ba73289c4af829d5a532e723967ce9b6c023ef0fd0cfe37f51f10f19463b6534159a09ddd2f51f3b30033');
|
||||||
},
|
},
|
||||||
|
|
||||||
'create a and b': {
|
'create a and b': {
|
||||||
topic(this: any) {(async () => {
|
topic(this: any) {(async () => {
|
||||||
a = await srp.genKey(64);
|
a = await SRP.genKey(64);
|
||||||
b = await srp.genKey(32);
|
b = await SRP.genKey(32);
|
||||||
this.callback();
|
this.callback();
|
||||||
})()},
|
})()},
|
||||||
|
|
||||||
'use a and b'() {
|
'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
|
// client produces A
|
||||||
A = client.computeA();
|
A = client.computeA();
|
||||||
|
|
||||||
// create server
|
// create server
|
||||||
server = new srp.Server(params, verifier, b);
|
server = new SrpServer(params, verifier, b);
|
||||||
|
|
||||||
// server produces B
|
// server produces B
|
||||||
B = server.computeB();
|
B = server.computeB();
|
||||||
@ -70,8 +68,8 @@ vows.describe('srp.js').addBatch({
|
|||||||
},
|
},
|
||||||
|
|
||||||
'server rejects wrong M1'() {
|
'server rejects wrong M1'() {
|
||||||
const bad_client = new srp.Client(params, salt, identity, Buffer.from('bad'), a, false);
|
const bad_client = new SrpClient(params, salt, identity, Buffer.from('bad'), a, false);
|
||||||
const server2 = new srp.Server(params, verifier, b);
|
const server2 = new SrpServer(params, verifier, b);
|
||||||
bad_client.setB(server2.computeB());
|
bad_client.setB(server2.computeB());
|
||||||
assert.throws(() => server.checkM1(bad_client.computeM1()), /client did not use the same password/);
|
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
|
// reject 2*N too, but our Buffer-length checks reject it before the
|
||||||
// number itself is examined.
|
// 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);
|
var Azero = Buffer.alloc(params.N_length_bits / 8);
|
||||||
Azero.fill(0);
|
Azero.fill(0);
|
||||||
//! var AN = params.N.toBuffer();
|
//! var AN = params.N.toBuffer();
|
||||||
@ -95,7 +93,7 @@ vows.describe('srp.js').addBatch({
|
|||||||
|
|
||||||
'client rejects bad B'() {
|
'client rejects bad B'() {
|
||||||
// server's "B" must be 1..N-1 . Reject 0 and N and N+1
|
// 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);
|
var Bzero = Buffer.alloc(params.N_length_bits / 8);
|
||||||
Bzero.fill(0, 0, params.N_length_bits / 8);
|
Bzero.fill(0, 0, params.N_length_bits / 8);
|
||||||
//! var BN = params.N.toBuffer();
|
//! var BN = params.N.toBuffer();
|
||||||
@ -108,13 +106,13 @@ vows.describe('srp.js').addBatch({
|
|||||||
},
|
},
|
||||||
|
|
||||||
'client rejects bad M2'() {
|
'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
|
// client produces A
|
||||||
A = client.computeA();
|
A = client.computeA();
|
||||||
|
|
||||||
// create server
|
// create server
|
||||||
server = new srp.Server(params, verifier, b);
|
server = new SrpServer(params, verifier, b);
|
||||||
|
|
||||||
// server produces B
|
// server produces B
|
||||||
B = server.computeB();
|
B = server.computeB();
|
||||||
|
@ -1,12 +1,22 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"strict": true,
|
"target": "ES2018",
|
||||||
|
"module": "commonjs",
|
||||||
|
"lib": [
|
||||||
|
"es2015",
|
||||||
|
"es2016",
|
||||||
|
"es2017",
|
||||||
|
"es2018"
|
||||||
|
],
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
|
"declarationMap": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
|
"outDir": "lib",
|
||||||
"rootDir": "src",
|
"rootDir": "src",
|
||||||
"outDir": "dist"
|
"strict": true,
|
||||||
|
"esModuleInterop": true
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src/**/*"
|
"src/"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user