feat(net): implement SRP6_Client::CalculateProof

This commit is contained in:
fallenoak 2023-02-06 22:31:15 -06:00
parent e7491b327c
commit 25bd29c45f
No known key found for this signature in database
GPG Key ID: 7628F8E61AEA070D
2 changed files with 149 additions and 2 deletions

View File

@ -1,5 +1,7 @@
#include "net/srp/SRP6_Client.hpp"
#include "net/srp/SRP6_Random.hpp"
#include <cstring>
#include <common/BigInteger.hpp>
int32_t SRP6_Client::BeginAuthentication(const char* accountName, const char* password) {
if (!accountName || !password) {
@ -24,7 +26,151 @@ int32_t SRP6_Client::BeginAuthentication(const char* accountName, const char* pa
}
int32_t SRP6_Client::CalculateProof(const uint8_t* largeSafePrime, uint32_t largeSafePrimeLen, const uint8_t* generator, uint32_t generatorLen, const uint8_t* salt, uint32_t saltLen, const uint8_t* publicKey, uint32_t publicKeyLen, SRP6_Random& random) {
// TODO
auto N = BigIntegerFromBytes(largeSafePrime, largeSafePrimeLen);
auto g = BigIntegerFromBytes(generator, generatorLen);
auto x = BigIntegerFromInt(0);
auto v = BigIntegerFromInt(0);
auto v24 = BigIntegerFromInt(0);
auto v25 = BigIntegerFromInt(0);
auto a = BigIntegerFromInt(0);
auto A = BigIntegerFromInt(0);
auto u = BigIntegerFromInt(0);
auto B = BigIntegerFromBytes(publicKey, publicKeyLen);
auto k = BigIntegerFromInt(0);
auto S = BigIntegerFromInt(0);
return 0;
int32_t result = 0;
if (!largeSafePrime || largeSafePrimeLen - 1 > 31) {
result = -1;
goto cleanup;
}
if (!generator || generatorLen - 1 > 31) {
result = -1;
goto cleanup;
}
if (!salt || saltLen - 1 > 31) {
result = -1;
goto cleanup;
}
if (!publicKey || publicKeyLen < 31) {
result = -1;
goto cleanup;
}
SHA1_CONTEXT ctx1;
SHA1_Init(&ctx1);
SHA1_Update(&ctx1, salt, saltLen);
SHA1_Update(&ctx1, this->interimDigest, sizeof(this->interimDigest));
uint8_t v21[SHA1_DIGEST_SIZE];
SHA1_Final(v21, &ctx1);
BigIntegerFree(x);
x = BigIntegerFromBytes(v21, sizeof(v21));
BigIntegerModExp(v, g, x, N);
SHA1_Init(&ctx1);
SHA1_Update(&ctx1, largeSafePrime, largeSafePrimeLen);
uint8_t v26[SHA1_DIGEST_SIZE];
SHA1_Final(v26, &ctx1);
SHA1_Init(&ctx1);
SHA1_Update(&ctx1, generator, generatorLen);
uint8_t v23[SHA1_DIGEST_SIZE];
SHA1_Final(v23, &ctx1);
for (int32_t i = 0; i < sizeof(v23); i += 5) {
v26[i] ^= v23[i];
auto v14 = v23[i + 2];
v26[i + 1] ^= v23[i + 1];
v26[i + 2] ^= v14;
auto v15 = v23[i + 4];
v26[i + 3] ^= v23[i + 3];
v26[i + 4] ^= v15;
}
SHA1_CONTEXT ctx2;
SHA1_Init(&ctx2);
SHA1_Update(&ctx2, v26, sizeof(v26));
SHA1_Update(&ctx2, this->accountNameDigest, sizeof(this->accountNameDigest));
SHA1_Update(&ctx2, salt, saltLen);
if (BigIntegerBitLen(N) >= 256) {
uint8_t v19[32];
// TODO
// random.GenerateRandomBytes(v19, sizeof(v19));
BigIntegerFree(a);
a = BigIntegerFromBytes(v19, sizeof(v19));
auto v16 = BigIntegerBitLen(N);
BigIntegerAddInt(a, a, v16);
BigIntegerModExp(A, g, a, N);
BigIntegerToBytes(A, this->clientPublicKey, sizeof(this->clientPublicKey));
SHA1_Update(&ctx2, this->clientPublicKey, sizeof(clientPublicKey));
SHA1_Update(&ctx2, publicKey, publicKeyLen);
SHA1_Update(&this->ctx, this->clientPublicKey, sizeof(clientPublicKey));
SHA1_Init(&ctx1);
SHA1_Update(&ctx1, this->clientPublicKey, sizeof(this->clientPublicKey));
SHA1_Update(&ctx1, publicKey, publicKeyLen);
SHA1_Final(v26, &ctx1);
BigIntegerFree(u);
u = BigIntegerFromBytes(v26, sizeof(v26));
if (BigIntegerCmp(B, N) < 0 && BigIntegerCmpInt(B, 0)) {
// Formula: S = (B - k*v)^(a + u*x) % N
BigIntegerSub(k, N, v);
BigIntegerAdd(B, B, k);
BigIntegerAdd(B, B, k);
BigIntegerAdd(B, B, k);
BigIntegerMod(B, B, N);
BigIntegerMul(k, x, u);
BigIntegerAdd(k, k, a);
BigIntegerModExp(S, B, k, N);
uint8_t v18[32];
BigIntegerToBytes(S, v18, sizeof(v18));
SHA1_InterleaveHash(this->sessionKey, v18, sizeof(v18));
SHA1_Update(&ctx2, this->sessionKey, sizeof(this->sessionKey));
SHA1_Final(this->clientProof, &ctx2);
SHA1_Update(&this->ctx, this->clientProof, sizeof(this->clientProof));
SHA1_Update(&this->ctx, this->sessionKey, sizeof(this->sessionKey));
result = 0;
} else {
result = -2;
}
} else {
result = -1;
}
cleanup:
BigIntegerFree(S);
BigIntegerFree(k);
BigIntegerFree(B);
BigIntegerFree(u);
BigIntegerFree(A);
BigIntegerFree(a);
BigIntegerFree(v25);
BigIntegerFree(v24);
BigIntegerFree(v);
BigIntegerFree(x);
BigIntegerFree(g);
BigIntegerFree(N);
return result;
}

View File

@ -9,6 +9,7 @@ class SRP6_Client {
public:
// Member variables
uint8_t clientPublicKey[32];
uint8_t sessionKey[40];
uint8_t clientProof[20];
uint8_t accountNameDigest[SHA1_DIGEST_SIZE];
uint8_t interimDigest[SHA1_DIGEST_SIZE];