blob: 4ed9dc7b42b0e3a151562de00279c09af538e0d9 [file] [log] [blame]
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;
}
}