mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
176 lines
5.7 KiB
C++
176 lines
5.7 KiB
C++
|
|
#include "KeyPairEd25519.h"
|
|
#include <assert.h>
|
|
|
|
#include "../SingletonManager/ErrorManager.h"
|
|
|
|
#include "../lib/DataTypeConverter.h"
|
|
|
|
|
|
|
|
KeyPairEd25519::KeyPairEd25519(MemoryBin* privateKey)
|
|
: mSodiumSecret(privateKey)
|
|
{
|
|
//memcpy(mSodiumPublic, publicKey, crypto_sign_PUBLICKEYBYTES);
|
|
// read pubkey from private key, so we are sure it is the correct pubkey for the private key
|
|
|
|
crypto_sign_ed25519_sk_to_pk(mSodiumPublic, *privateKey);
|
|
}
|
|
|
|
KeyPairEd25519::KeyPairEd25519(const unsigned char* publicKey)
|
|
: mSodiumSecret(nullptr)
|
|
{
|
|
memcpy(mSodiumPublic, publicKey, crypto_sign_PUBLICKEYBYTES);
|
|
}
|
|
|
|
KeyPairEd25519::KeyPairEd25519()
|
|
: mSodiumSecret(nullptr)
|
|
{
|
|
memset(mSodiumPublic, 0, crypto_sign_PUBLICKEYBYTES);
|
|
}
|
|
|
|
KeyPairEd25519::~KeyPairEd25519()
|
|
{
|
|
if (mSodiumSecret) {
|
|
MemoryManager::getInstance()->releaseMemory(mSodiumSecret);
|
|
mSodiumSecret = nullptr;
|
|
}
|
|
}
|
|
|
|
KeyPairEd25519* KeyPairEd25519::create(const Poco::AutoPtr<Passphrase> passphrase)
|
|
{
|
|
//auto er = ErrorManager::getInstance();
|
|
auto mm = MemoryManager::getInstance();
|
|
assert(!passphrase.isNull());
|
|
// libsodium doc: https://libsodium.gitbook.io/doc/advanced/hmac-sha2
|
|
// https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
|
|
|
|
auto word_indices = passphrase->getWordIndices();
|
|
|
|
if (!word_indices || (!word_indices[0] && !word_indices[1] && !word_indices[2] && !word_indices[3])) {
|
|
return nullptr;
|
|
}
|
|
std::string clear_passphrase = passphrase->createClearPassphrase();
|
|
|
|
|
|
unsigned char hash[crypto_hash_sha512_BYTES];
|
|
|
|
crypto_hash_sha512_state state;
|
|
crypto_hash_sha512_init(&state);
|
|
|
|
// **** convert word indices into uint64 ****
|
|
// To prevent breaking existing passphrase-hash combinations word indices will be put into 64 Bit Variable to mimic first implementation of algorithms
|
|
auto valueSize = sizeof(Poco::UInt64);
|
|
Poco::UInt64 value = 0;
|
|
for (int i = 0; i < PHRASE_WORD_COUNT; i++) {
|
|
value = word_indices[i];
|
|
crypto_hash_sha512_update(&state, (const unsigned char*)&value, valueSize);
|
|
}
|
|
// **** end converting into uint64 *****
|
|
crypto_hash_sha512_update(&state, (unsigned char*)clear_passphrase.data(), clear_passphrase.size());
|
|
crypto_hash_sha512_final(&state, hash);
|
|
|
|
/*
|
|
// debug passphrase
|
|
printf("\passsphrase: <%s>\n", passphrase);
|
|
printf("size word indices: %u\n", word_indices->size());
|
|
std::string word_indicesHex = getHex(*word_indices, word_indices->size());
|
|
printf("word_indices: \n%s\n", word_indicesHex.data());
|
|
printf("word_indices: \n");
|
|
Poco::UInt64* word_indices_p = (Poco::UInt64*)(word_indices->data());
|
|
for (int i = 0; i < PHRASE_WORD_COUNT; i++) {
|
|
if (i > 0) printf(" ");
|
|
printf("%4hu", word_indices_p[i]);
|
|
}
|
|
printf("\n");
|
|
|
|
printf("\nclear passphrase: \n%s\n", clearPassphrase.data());
|
|
std::string hex_clearPassphrase = getHex((const unsigned char*)clearPassphrase.data(), clearPassphrase.size());
|
|
printf("passphrase bin: \n%s\n\n", hex_clearPassphrase.data());
|
|
|
|
//*/
|
|
|
|
KeyPairEd25519* key_pair = new KeyPairEd25519;
|
|
if (!key_pair->mSodiumSecret) {
|
|
key_pair->mSodiumSecret = mm->getFreeMemory(crypto_sign_SECRETKEYBYTES);
|
|
}
|
|
|
|
crypto_sign_seed_keypair(key_pair->mSodiumPublic, *key_pair->mSodiumSecret, hash);
|
|
|
|
return key_pair;
|
|
|
|
// print hex for all keys for debugging
|
|
/* printf("// ********** Keys ************* //\n");
|
|
printf("Sodium Public: \t%s\n", getHex(mSodiumPublic, crypto_sign_PUBLICKEYBYTES).data());
|
|
printf("Sodium Private: \t%s\n", getHex(*mSodiumSecret, mSodiumSecret->size()).data());
|
|
printf("// ********* Keys End ************ //\n");
|
|
*/
|
|
//printf("[KeyPair::generateFromPassphrase] finished!\n");
|
|
// using
|
|
}
|
|
MemoryBin* KeyPairEd25519::sign(const unsigned char* message, size_t messageSize) const
|
|
//MemoryBin* KeyPairEd25519::sign(const MemoryBin* message) const
|
|
{
|
|
|
|
if (!message || !messageSize) return nullptr;
|
|
if (!mSodiumSecret) return nullptr;
|
|
auto mm = MemoryManager::getInstance();
|
|
auto em = ErrorManager::getInstance();
|
|
|
|
const static char functionName[] = "KeyPairEd25519::sign";
|
|
|
|
auto signBinBuffer = mm->getFreeMemory(crypto_sign_BYTES);
|
|
unsigned long long actualSignLength = 0;
|
|
|
|
if (crypto_sign_detached(*signBinBuffer, &actualSignLength, message, messageSize, *mSodiumSecret)) {
|
|
em->addError(new Error(functionName, "sign failed"));
|
|
auto messageHex = DataTypeConverter::binToHex(message, messageSize);
|
|
em->addError(new ParamError(functionName, "message as hex", messageHex));
|
|
mm->releaseMemory(signBinBuffer);
|
|
return nullptr;
|
|
}
|
|
|
|
if (crypto_sign_verify_detached(*signBinBuffer, message, messageSize, mSodiumPublic) != 0) {
|
|
// Incorrect signature!
|
|
//printf("c[KeyBuffer::%s] sign verify failed\n", __FUNCTION__);
|
|
em->addError(new Error(functionName, "sign verify failed"));
|
|
auto messageHex = DataTypeConverter::binToHex(message, messageSize);
|
|
em->addError(new ParamError(functionName, "message as hex", messageHex));
|
|
mm->releaseMemory(signBinBuffer);
|
|
return nullptr;
|
|
}
|
|
|
|
// debug
|
|
/*const size_t hex_sig_size = crypto_sign_BYTES * 2 + 1;
|
|
char sig_hex[hex_sig_size];
|
|
sodium_bin2hex(sig_hex, hex_sig_size, *signBinBuffer, crypto_sign_BYTES);
|
|
printf("[User::sign] signature hex: %s\n", sig_hex);
|
|
*/
|
|
|
|
return signBinBuffer;
|
|
|
|
}
|
|
|
|
bool KeyPairEd25519::verify(const std::string& message, const std::string& signature) const
|
|
{
|
|
if (message == "" || signature == "") return false;
|
|
if (crypto_sign_verify_detached((const unsigned char*)signature.data(), (const unsigned char*)message.data(), message.size(), mSodiumPublic) != 0) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
MemoryBin* KeyPairEd25519::getCryptedPrivKey(const Poco::AutoPtr<SecretKeyCryptography> password) const
|
|
{
|
|
if (password.isNull()) return nullptr;
|
|
if (!mSodiumSecret) return nullptr;
|
|
|
|
MemoryBin* encryptedKey = nullptr;
|
|
if (SecretKeyCryptography::AUTH_ENCRYPT_OK == password->encrypt(mSodiumSecret, &encryptedKey)) {
|
|
return encryptedKey;
|
|
}
|
|
else {
|
|
return nullptr;
|
|
}
|
|
|
|
} |