library impl.srp_client; import 'dart:typed_data'; import 'package:pointycastle/api.dart'; import 'package:pointycastle/srp/srp6_standard_groups.dart'; import 'package:pointycastle/srp/srp6_util.dart'; class SRP6Client implements SRPClient { late BigInt N; late BigInt g; BigInt? a; BigInt? A; BigInt? B; BigInt? x; BigInt? u; BigInt? S; BigInt? M1; BigInt? M2; BigInt? Key; Digest digest; SecureRandom random; SRP6GroupParameters group; SRP6Client( {required this.group, required this.digest, required this.random}) { g = group.g; N = group.N; } @override BigInt? calculateClientEvidenceMessage() { // Verify pre-requirements if (A == null || B == null || S == null) { throw Exception( 'Impossible to compute M1: some data are missing from the previous operations (A,B,S)'); } // compute the client evidence message 'M1' M1 = SRP6Util.calculateM1(digest, N, A, B, S); return M1; } ///S = (B - kg^x) ^ (a + ux) BigInt? calculateS() { var k = SRP6Util.calculateK(digest, N, g); var exp = (u! * x!) + a!; var tmp = g.modPow(x!, N) * (k % N); return (B! - (tmp % N)).modPow(exp, N); } @override BigInt? calculateSecret(BigInt serverB) { B = SRP6Util.validatePublicValue(N, serverB); u = SRP6Util.calculateU(digest, N, A, B); S = calculateS(); return S; } @override BigInt? calculateSessionKey() { // Verify pre-requirements (here we enforce a previous calculation of M1 and M2) if (S == null || M1 == null || M2 == null) { throw Exception( 'Impossible to compute Key: some data are missing from the previous operations (S,M1,M2)'); } Key = SRP6Util.calculateKey(digest, N, S!); return Key; } @override BigInt? generateClientCredentials( Uint8List salt, Uint8List identity, Uint8List password) { x = SRP6Util.calculateX(digest, N, salt, identity, password); a = selectPrivateValue(); A = g.modPow(a!, N); return A; } BigInt? selectPrivateValue() { return SRP6Util.generatePrivateValue(digest, N, g, random); } @override bool verifyServerEvidenceMessage(BigInt serverM2) { // Verify pre-requirements if (A == null || M1 == null || S == null) { throw Exception('Impossible to compute and verify M2: ' 'some data are missing from the previous operations (A,M1,S)'); } // Compute the own server evidence message 'M2' var computedM2 = SRP6Util.calculateM2(digest, N, A, M1, S); if (computedM2.compareTo(serverM2) == 0) { M2 = serverM2; return true; } return false; } }