wallet/src/secrets.cpp

57 lines
1.7 KiB
C++
Raw Normal View History

#include "stdafx.h"
#include "secrets.h"
//Derive a Short text Secret from a 256 bit random value and a sixty four bit integer
using ristretto255::scalar, ristretto255::hash, ristretto255::hsh;
std::array<char, 27> DeriveTextSecret(const scalar & blob, uint_fast64_t i){
static constexpr std::array<uint8_t, crypto_pwhash_SALTBYTES> salt{0};
std::array<char, 27> txt;
unsigned int n{ 3 };
unsigned int m{ 3 };
hash rand(blob,i);
uint8_t* p{ &rand.blob[0] };
char* q = &txt[0];
while (n || m) {
if (*p++ < ((n * 0x100) / (n + m))) {
n--;
bits2base64(p, 0, 18, std::span(q, 4));
q+=3;
}
else {
m--;
bits2base64(p, 0, 24, std::span(q, 5));
q+=4;
}
*q++ = ' ';
p += 3;
}
assert(q == sizeof(txt) + &txt[0]);
assert(p == &rand.blob[24]);
txt[sizeof(txt)-1]='\0';
return txt;
}
//Derive a strong scalar secret from a string with password strengthening.
//Net effect is convert one scalar into another by a process that is lengthy and costly.
ristretto255::scalar DeriveStrongSecret(const char* const passwd){
static std::array<uint8_t, crypto_pwhash_SALTBYTES> salt{ 0 };
std::array<uint8_t, sizeof(ristretto255::hash<512>)>randb;
int i{
crypto_pwhash(
&randb[0],
sizeof(randb),
passwd,
strlen(passwd)+1,
&salt[0],
2, 0x10000000,
crypto_pwhash_ALG_ARGON2ID13
)
};
static_assert(crypto_pwhash_OPSLIMIT_MODERATE == 0x00000003 && crypto_pwhash_MEMLIMIT_MODERATE == 0x10000000, "Argon changed, likely breaking all passphrases");
assert(i == 0);
return scalar(hash<512>(randb));
}
//Derive scalar secret from another quickly.
ristretto255::scalar DeriveSecret(const scalar &sc, uint_fast64_t i) {
return ristretto255::scalar(ristretto255::hash<512>(sc, i));
}