UNPKG

bsrp

Version:

Secure Remote Password Protocol (SRP-6a) Implementation

121 lines (120 loc) 9.01 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; exports.__esModule = true; var jsbn_1 = require("jsbn"); var index_1 = require("./index"); var crypto_1 = __importDefault(require("crypto")); Object.defineProperty(global, "crypto", { value: { getRandomValues: function (arr) { return new Uint8Array(crypto_1["default"].randomBytes(arr.length)); } } }); test("should generate distinct ephemeral A pairs on subsequent calls", function () { var firstAPair = index_1.generateAPair(); var secondAPair = index_1.generateAPair(); expect(firstAPair.ephemeralA.equals(secondAPair.ephemeralA)).toBeFalsy(); expect(firstAPair.publicA.equals(secondAPair.publicA)).toBeFalsy(); }); describe("should process the challenge and ", function () { var mockIdentity = "test"; var mockPassword = "#yoloswag"; var mockSalt = new jsbn_1.BigInteger("82309018978721799953398513360460893179767695404873354411100056397421052845665"); var mockPublicB = new jsbn_1.BigInteger("\n 2168633872370722745670231052464515298895652280466586654940561279418192885446\n 5569815697827449086706130654556981842259346317901572319578127690722060828257\n 3518553531735879868022446812124213772126832091842123960193172642571089048102\n 1733289687022334152421632949742565001244773176944756872042436192195957381164\n 3090658931531623031352514968292009353084810965494415056390874498442382477900\n 5882353129578106468292270918741874924193460980087907520441982126932668030685\n 0090969045828991711574270619272362170264839084534189611581461513287496008879\n 4917135704491740168013752189651036694080408335025658762869099665070041969775\n 98773447"); var mockEphemeralA = new jsbn_1.BigInteger("\n 4511537769169629456932317311882933072389518195547222946095076177846929590195\n 1371663079183837225894296915421325322153782291026063288897303615301028637536\n 4456708100501196659474191428313993281737569455237451851801736494448257151040\n 4365649028849103887131660619405196304102087967082694857865126560813264823405\n 2896370620643251731159847597082454921230612553999232050453350061287212947114\n 3468309214437185337349903617563711682323708858174186538383127890364117859261\n 0235971430683027990812743687636354509374067537368960261011404677986671649957\n 1557511465995246567919633908251275514634723736321964939491245041138953850276\n 87951603"); var mockPublicA = new jsbn_1.BigInteger("\n 7723050516275197268596595028736303071422024349483662336212921812048310033512\n 6572244050991069989463201236543019478742255154255342629510064426510389492901\n 5314632288491039186285275840080928643682068266242876368549903623900851264362\n 7570310166999141108388337926675047366656403001872884373870424306058994437632\n 6182236026078347522175520387250862728453632132151431118882482079388402701874\n 1521703855998269888412158021986972606977074552546346835095695193183456199335\n 2853623091631714197790513583278068216773290743046592802328988338075991944028\n 1512937113784396196375280239379337167801926867954676026661710324701047040250\n 3411593"); var mockM = new jsbn_1.BigInteger("47331452883524291432813240675074597019503107827225066688099958715824381672937"); var mockSessionKey = new jsbn_1.BigInteger("56698353699494108654378460060782330526832508847563378289382973830724156337149"); var mockServerHAMK = new jsbn_1.BigInteger("112019802657940577633183024678428984798515249411730363524477901544479122837941"); test("respond with the expected message M to the server", function () { return __awaiter(void 0, void 0, void 0, function () { var processedChallenge, message, sessionKey, clientHAMK; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4, index_1.processChallenge(mockIdentity, mockPassword, mockSalt, mockEphemeralA, mockPublicA, mockPublicB)]; case 1: processedChallenge = _a.sent(); message = processedChallenge.message, sessionKey = processedChallenge.sessionKey; expect(message.equals(mockM)).toBeTruthy(); expect(sessionKey.equals(mockSessionKey)).toBeTruthy(); return [4, index_1.verifySession(mockPublicA, message, sessionKey, mockServerHAMK)]; case 2: clientHAMK = _a.sent(); expect(clientHAMK.equals(mockServerHAMK)).toBeTruthy(); return [2]; } }); }); }); test("fail (SRP6a safety check) since B % prime = 0", function () { return __awaiter(void 0, void 0, void 0, function () { var mockZeroPublicB, processedChallenge; return __generator(this, function (_a) { switch (_a.label) { case 0: mockZeroPublicB = new jsbn_1.BigInteger("0"); return [4, index_1.processChallenge(mockIdentity, mockPassword, mockSalt, mockEphemeralA, mockPublicA, mockZeroPublicB)]; case 1: processedChallenge = _a.sent(); expect(processedChallenge).toBeNull(); return [2]; } }); }); }); test("fail to mutually authenticate the server", function () { return __awaiter(void 0, void 0, void 0, function () { var mockWrongServerHAMK, processedChallenge, message, sessionKey, clientHAMK; return __generator(this, function (_a) { switch (_a.label) { case 0: mockWrongServerHAMK = new jsbn_1.BigInteger("482758924758974325893457983478954"); return [4, index_1.processChallenge(mockIdentity, mockPassword, mockSalt, mockEphemeralA, mockPublicA, mockPublicB)]; case 1: processedChallenge = _a.sent(); message = processedChallenge.message, sessionKey = processedChallenge.sessionKey; expect(message.equals(mockM)).toBeTruthy(); expect(sessionKey.equals(mockSessionKey)).toBeTruthy(); return [4, index_1.verifySession(mockPublicA, message, sessionKey, mockWrongServerHAMK)]; case 2: clientHAMK = _a.sent(); expect(clientHAMK).toBeNull(); return [2]; } }); }); }); });