UNPKG

bsrp

Version:

Secure Remote Password Protocol (SRP-6a) Implementation

156 lines (134 loc) 5.53 kB
import { BigInteger } from "jsbn"; import { APair, generateAPair, processChallenge, verifySession } from "./index"; import crypto from "crypto"; Object.defineProperty(global, "crypto", { value: { getRandomValues: (arr: Uint8Array): Uint8Array => new Uint8Array(crypto.randomBytes(arr.length)), }, }); test("should generate distinct ephemeral A pairs on subsequent calls", () => { const firstAPair: APair = generateAPair(); const secondAPair: APair = generateAPair(); expect(firstAPair.ephemeralA.equals(secondAPair.ephemeralA)).toBeFalsy(); expect(firstAPair.publicA.equals(secondAPair.publicA)).toBeFalsy(); }); /* The following test against data generated by our backend secure remote password (SRP) library found at common.capitalrx.com/python/capitalrx_srp/lib/capitalrx_srp/server.py */ describe("should process the challenge and ", () => { const mockIdentity = "test"; const mockPassword = "#yoloswag"; const mockSalt = new BigInteger( "82309018978721799953398513360460893179767695404873354411100056397421052845665" ); const mockPublicB = new BigInteger( ` 2168633872370722745670231052464515298895652280466586654940561279418192885446 5569815697827449086706130654556981842259346317901572319578127690722060828257 3518553531735879868022446812124213772126832091842123960193172642571089048102 1733289687022334152421632949742565001244773176944756872042436192195957381164 3090658931531623031352514968292009353084810965494415056390874498442382477900 5882353129578106468292270918741874924193460980087907520441982126932668030685 0090969045828991711574270619272362170264839084534189611581461513287496008879 4917135704491740168013752189651036694080408335025658762869099665070041969775 98773447` ); const mockEphemeralA = new BigInteger( ` 4511537769169629456932317311882933072389518195547222946095076177846929590195 1371663079183837225894296915421325322153782291026063288897303615301028637536 4456708100501196659474191428313993281737569455237451851801736494448257151040 4365649028849103887131660619405196304102087967082694857865126560813264823405 2896370620643251731159847597082454921230612553999232050453350061287212947114 3468309214437185337349903617563711682323708858174186538383127890364117859261 0235971430683027990812743687636354509374067537368960261011404677986671649957 1557511465995246567919633908251275514634723736321964939491245041138953850276 87951603` ); const mockPublicA = new BigInteger( ` 7723050516275197268596595028736303071422024349483662336212921812048310033512 6572244050991069989463201236543019478742255154255342629510064426510389492901 5314632288491039186285275840080928643682068266242876368549903623900851264362 7570310166999141108388337926675047366656403001872884373870424306058994437632 6182236026078347522175520387250862728453632132151431118882482079388402701874 1521703855998269888412158021986972606977074552546346835095695193183456199335 2853623091631714197790513583278068216773290743046592802328988338075991944028 1512937113784396196375280239379337167801926867954676026661710324701047040250 3411593` ); const mockM = new BigInteger( "47331452883524291432813240675074597019503107827225066688099958715824381672937" ); const mockSessionKey = new BigInteger( "56698353699494108654378460060782330526832508847563378289382973830724156337149" ); const mockServerHAMK = new BigInteger( "112019802657940577633183024678428984798515249411730363524477901544479122837941" ); test("respond with the expected message M to the server", async () => { const processedChallenge = await processChallenge( mockIdentity, mockPassword, mockSalt, mockEphemeralA, mockPublicA, mockPublicB ); const { message, sessionKey } = processedChallenge; expect(message.equals(mockM)).toBeTruthy(); expect(sessionKey.equals(mockSessionKey)).toBeTruthy(); // Mutual authentication const clientHAMK = await verifySession( mockPublicA, message, sessionKey, mockServerHAMK ); // verifySession already performs this check and will return null if verification fails, but alas do it here expect(clientHAMK.equals(mockServerHAMK)).toBeTruthy(); }); test("fail (SRP6a safety check) since B % prime = 0", async () => { // Causes the safety to fail const mockZeroPublicB = new BigInteger("0"); const processedChallenge = await processChallenge( mockIdentity, mockPassword, mockSalt, mockEphemeralA, mockPublicA, mockZeroPublicB ); // Safety failed expect(processedChallenge).toBeNull(); }); test("fail to mutually authenticate the server", async () => { // Causes the mutual auth to fail const mockWrongServerHAMK = new BigInteger( "482758924758974325893457983478954" ); const processedChallenge = await processChallenge( mockIdentity, mockPassword, mockSalt, mockEphemeralA, mockPublicA, mockPublicB ); const { message, sessionKey } = processedChallenge; expect(message.equals(mockM)).toBeTruthy(); expect(sessionKey.equals(mockSessionKey)).toBeTruthy(); // Mutual authentication const clientHAMK = await verifySession( mockPublicA, message, sessionKey, mockWrongServerHAMK ); // Authentication of server failed expect(clientHAMK).toBeNull(); }); });