diff --git a/server/domain/user/service/srp/calcSessionKey.ts b/server/domain/user/service/srp/calcSessionKey.ts index 3c7e263..0afcdff 100644 --- a/server/domain/user/service/srp/calcSessionKey.ts +++ b/server/domain/user/service/srp/calcSessionKey.ts @@ -1,4 +1,3 @@ -import assert from 'assert'; import crypto from 'crypto'; import { BigInteger } from 'jsbn'; import { N, Nbytes } from './constants'; @@ -19,15 +18,9 @@ export const calculateSessionKey = (params: { v: string; }): Buffer => { const Aint = new BigInteger(padHex(params.A), 16); - const Bint = new BigInteger(padHex(params.B), 16); const bInt = new BigInteger(padHex(params.b), 16); const vInt = new BigInteger(params.v, 16); - assert(Aint.compareTo(BigInteger.ZERO) > 0, 'A should be greater than 0'); - assert(Aint.compareTo(N) < 0, 'A should be less than N'); - assert(Bint.compareTo(BigInteger.ZERO) > 0, 'B should be greater than 0'); - assert(Bint.compareTo(N) < 0, 'A should be less than N'); - const scramblingParameter = calculateScramblingParameter(params.A, params.B); // u = H(A,B) % N diff --git a/server/domain/user/service/srp/calcSrpA.ts b/server/domain/user/service/srp/calcSrpA.ts new file mode 100644 index 0000000..152627c --- /dev/null +++ b/server/domain/user/service/srp/calcSrpA.ts @@ -0,0 +1,15 @@ +import { Buffer } from 'buffer'; +import crypto from 'crypto'; +import { N, g } from 'domain/user/service/srp/constants'; +import { fromBuffer, toBuffer } from 'domain/user/service/srp/util'; +import { BigInteger } from 'jsbn'; + +export const calculateSrpA = (): { a: Buffer; A: Buffer } => { + let a = Buffer.from([0]); + let AInt = BigInteger.ZERO; + while (AInt === BigInteger.ZERO) { + a = crypto.randomBytes(32); + AInt = g.modPow(fromBuffer(a), N); + } + return { a, A: toBuffer(AInt) }; +}; diff --git a/server/domain/user/service/srp/calcSrpB.ts b/server/domain/user/service/srp/calcSrpB.ts index d15b313..1bed68f 100644 --- a/server/domain/user/service/srp/calcSrpB.ts +++ b/server/domain/user/service/srp/calcSrpB.ts @@ -9,10 +9,17 @@ export const calculateSrpB = ( b: string; B: string; } => { - const b = crypto.randomBytes(32); - const bInt = fromBuffer(b); + let BInt = BigInteger.ZERO; + let b = Buffer.from([0]); const vInt = new BigInteger(v, 16); + + while (BInt === BigInteger.ZERO) { + b = crypto.randomBytes(32); + const bInt = fromBuffer(b); + BInt = multiplierParam.multiply(vInt).add(g.modPow(bInt, N)).mod(N); + } + // kv + g^b - const B = toBuffer(multiplierParam.multiply(vInt).add(g.modPow(bInt, N)).mod(N)); + const B = toBuffer(BInt); return { b: b.toString('hex'), B: B.toString('hex') }; }; diff --git a/server/domain/user/service/srp/util.ts b/server/domain/user/service/srp/util.ts index fec121f..078f691 100644 --- a/server/domain/user/service/srp/util.ts +++ b/server/domain/user/service/srp/util.ts @@ -30,7 +30,7 @@ export const padBufferToHex = (buffer: Buffer): string => { export const toBuffer = (bigInt: BigInteger): Buffer => { const str = bigInt.toString(16); - return Buffer.from(str, 'hex'); + return Buffer.from(str.padStart(str.length + (str.length % 2), '0'), 'hex'); }; export const toBufferWithLength = (bigInt: BigInteger, length: number): Buffer => { diff --git a/server/tests/api/changePassword.test.ts b/server/tests/api/changePassword.test.ts index b0e6a29..87d96ec 100644 --- a/server/tests/api/changePassword.test.ts +++ b/server/tests/api/changePassword.test.ts @@ -1,8 +1,7 @@ import assert from 'assert'; -import crypto from 'crypto'; import { calcClientSignature } from 'domain/user/service/srp/calcClientSignature'; -import { N, g } from 'domain/user/service/srp/constants'; -import { fromBuffer, toBuffer } from 'domain/user/service/srp/util'; +import { calculateSrpA } from 'domain/user/service/srp/calcSrpA'; +import { fromBuffer } from 'domain/user/service/srp/util'; import { DEFAULT_USER_POOL_CLIENT_ID } from 'service/envValues'; import { test } from 'vitest'; import { @@ -15,8 +14,7 @@ import { test('changePassword', async () => { await createUserClient(); - const a = crypto.randomBytes(32); - const A = toBuffer(g.modPow(fromBuffer(a), N)); + const { a, A } = calculateSrpA(); const res1 = await noCookieClient.$post({ headers: { 'x-amz-target': 'AWSCognitoIdentityProviderService.InitiateAuth' }, body: { diff --git a/server/tests/api/signIn.test.ts b/server/tests/api/signIn.test.ts index 63f362c..ea5fbee 100644 --- a/server/tests/api/signIn.test.ts +++ b/server/tests/api/signIn.test.ts @@ -1,8 +1,7 @@ import assert from 'assert'; -import crypto from 'crypto'; import { calcClientSignature } from 'domain/user/service/srp/calcClientSignature'; -import { N, g } from 'domain/user/service/srp/constants'; -import { fromBuffer, toBuffer } from 'domain/user/service/srp/util'; +import { calculateSrpA } from 'domain/user/service/srp/calcSrpA'; +import { fromBuffer } from 'domain/user/service/srp/util'; import { DEFAULT_USER_POOL_CLIENT_ID } from 'service/envValues'; import { expect, test } from 'vitest'; import { @@ -16,8 +15,7 @@ import { test('signIn', async () => { await createUserClient(); - const a = crypto.randomBytes(32); - const A = toBuffer(g.modPow(fromBuffer(a), N)); + const { a, A } = calculateSrpA(); const res1 = await noCookieClient.$post({ headers: { 'x-amz-target': 'AWSCognitoIdentityProviderService.InitiateAuth' }, body: {