library impl.srp_server; import 'package:pointycastle/api.dart'; import 'package:pointycastle/srp/srp6_standard_groups.dart'; import 'package:pointycastle/srp/srp6_util.dart'; class SRP6Server implements SRPServer { late BigInt N; late BigInt g; BigInt v; SecureRandom random; Digest digest; BigInt? A; BigInt? b; BigInt? B; BigInt? u; BigInt? S; BigInt? M1; BigInt? M2; BigInt? Key; SRP6Server( {required SRP6GroupParameters group, required this.v, required this.digest, required this.random}) { g = group.g; N = group.N; } @override BigInt? calculateSecret(BigInt clientA) { A = SRP6Util.validatePublicValue(N, clientA); u = SRP6Util.calculateU(digest, N, A, B); S = _calculateS(); return S; } @override BigInt? calculateServerEvidenceMessage() { // Verify pre-requirements if (A == null || M1 == null || S == null) { throw Exception( 'Impossible to compute M2: some data are missing from the previous operations (A,M1,S)'); } // Compute the server evidence message 'M2' M2 = SRP6Util.calculateM2(digest, N, A!, M1!, S!); return M2; } @override BigInt? calculateSessionKey() { // Verify pre-requirements 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? generateServerCredentials() { var k = SRP6Util.calculateK(digest, N, g); b = selectPrivateValue(); B = (k * v + g.modPow(b!, N)) % N; return B; } BigInt? selectPrivateValue() { return SRP6Util.generatePrivateValue(digest, N, g, random); } @override bool verifyClientEvidenceMessage(BigInt clientM1) { // Verify pre-requirements if (A == null || B == null || S == null) { throw Exception( 'Impossible to compute and verify M1: some data are missing from the previous operations (A,B,S)'); } // Compute the own client evidence message 'M1' var computedM1 = SRP6Util.calculateM1(digest, N, A, B, S); if (computedM1.compareTo(clientM1) == 0) { M1 = clientM1; return true; } return false; } BigInt _calculateS() { return ((v.modPow(u!, N) * A!) % N).modPow(b!, N); } }