mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
add KeyPairHedera mostly copied from KeyPairEd25519 but not testet yet. Maybe I must use the iroha ed25519 implementation because in the past sodium don't work together with hedera
This commit is contained in:
parent
cb86ed9422
commit
ba23cf7e37
148
src/cpp/Crypto/KeyPairHedera.cpp
Normal file
148
src/cpp/Crypto/KeyPairHedera.cpp
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
#include "KeyPairHedera.h"
|
||||||
|
#include "../lib/DataTypeConverter.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "../SingletonManager/ErrorManager.h"
|
||||||
|
|
||||||
|
KeyPairHedera::KeyPairHedera()
|
||||||
|
: mPrivateKey(nullptr)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KeyPairHedera::KeyPairHedera(const MemoryBin* privateKey, const MemoryBin* publicKey /* = nullptr*/)
|
||||||
|
: mPrivateKey(nullptr)
|
||||||
|
{
|
||||||
|
auto derPrefixPriv = DataTypeConverter::hexToBin("302e020100300506032b657004220420");
|
||||||
|
auto derPrefixPub = DataTypeConverter::hexToBin("302a300506032b6570032100");
|
||||||
|
|
||||||
|
auto mm = MemoryManager::getInstance();
|
||||||
|
|
||||||
|
if (privateKey) {
|
||||||
|
switch (privateKey->size()) {
|
||||||
|
case 48:
|
||||||
|
// key with prefix
|
||||||
|
if (0 == sodium_memcmp(*privateKey, *derPrefixPriv, derPrefixPriv->size())) {
|
||||||
|
//int crypto_sign_seed_keypair(unsigned char *pk, unsigned char *sk, const unsigned char *seed);
|
||||||
|
auto seed = mm->getFreeMemory(crypto_sign_ed25519_SEEDBYTES);
|
||||||
|
memcpy(*seed, privateKey->data(derPrefixPriv->size()), crypto_sign_ed25519_SEEDBYTES);
|
||||||
|
createKeyFromSeed(seed);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 32:
|
||||||
|
createKeyFromSeed(privateKey);
|
||||||
|
break;
|
||||||
|
case 64:
|
||||||
|
//mPrivateKey = privateKey;
|
||||||
|
if (!mPrivateKey || mPrivateKey->size() != privateKey->size()) {
|
||||||
|
if (mPrivateKey) {
|
||||||
|
mm->releaseMemory(mPrivateKey);
|
||||||
|
}
|
||||||
|
mPrivateKey = mm->getFreeMemory(privateKey->size());
|
||||||
|
memcpy(*mPrivateKey, *privateKey, privateKey->size());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw std::exception("[KeyPairHedera] invalid private key");
|
||||||
|
}
|
||||||
|
crypto_sign_ed25519_sk_to_pk(mPublicKey, *mPrivateKey);
|
||||||
|
}
|
||||||
|
else if (publicKey) {
|
||||||
|
switch (publicKey->size())
|
||||||
|
{
|
||||||
|
case 32: { // raw public key
|
||||||
|
memcpy(mPublicKey, *publicKey, publicKey->size());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 44: // DER encoded public key
|
||||||
|
if (0 == sodium_memcmp(*publicKey, *derPrefixPub, derPrefixPub->size())) {
|
||||||
|
memcpy(mPublicKey, publicKey->data(derPrefixPub->size()), ed25519_pubkey_SIZE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw std::exception("[KeyPairHedera] invalid public key");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mm->releaseMemory(derPrefixPriv);
|
||||||
|
mm->releaseMemory(derPrefixPub);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyPairHedera::~KeyPairHedera()
|
||||||
|
{
|
||||||
|
auto mm = MemoryManager::getInstance();
|
||||||
|
if (mPrivateKey) {
|
||||||
|
mm->releaseMemory(mPrivateKey);
|
||||||
|
mPrivateKey = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KeyPairHedera::createKeyFromSeed(const MemoryBin* seed)
|
||||||
|
{
|
||||||
|
assert(seed && seed->size() == crypto_sign_ed25519_SEEDBYTES);
|
||||||
|
|
||||||
|
auto mm = MemoryManager::getInstance();
|
||||||
|
auto secret_key = mm->getFreeMemory(crypto_sign_SECRETKEYBYTES);
|
||||||
|
crypto_sign_seed_keypair(mPublicKey, *secret_key, *seed);
|
||||||
|
|
||||||
|
if (mPrivateKey) {
|
||||||
|
mm->releaseMemory(mPrivateKey);
|
||||||
|
}
|
||||||
|
mPrivateKey = secret_key;
|
||||||
|
|
||||||
|
// iroha
|
||||||
|
//ed25519_privkey_SIZE
|
||||||
|
//ed25519_derive_public_key(const private_key_t* sk,public_key_t* pk);
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryBin* KeyPairHedera::sign(const unsigned char* message, size_t messageSize) const
|
||||||
|
{
|
||||||
|
if (!message || !messageSize) return nullptr;
|
||||||
|
if (!mPrivateKey) return nullptr;
|
||||||
|
auto mm = MemoryManager::getInstance();
|
||||||
|
auto em = ErrorManager::getInstance();
|
||||||
|
|
||||||
|
const static char functionName[] = "KeyPairHedera::sign";
|
||||||
|
|
||||||
|
auto signBinBuffer = mm->getFreeMemory(crypto_sign_BYTES);
|
||||||
|
unsigned long long actualSignLength = 0;
|
||||||
|
|
||||||
|
if (crypto_sign_detached(*signBinBuffer, &actualSignLength, message, messageSize, *mPrivateKey)) {
|
||||||
|
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, mPublicKey) != 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 KeyPairHedera::verify(const unsigned char* message, size_t messageSize, MemoryBin* signature) const
|
||||||
|
{
|
||||||
|
if (crypto_sign_verify_detached(*signature, message, messageSize, mPublicKey) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
82
src/cpp/Crypto/KeyPairHedera.h
Normal file
82
src/cpp/Crypto/KeyPairHedera.h
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#ifndef __GRADIDO_LOGIN_SERVER_CRYPTO_HEDERA_KEYS_H
|
||||||
|
#define __GRADIDO_LOGIN_SERVER_CRYPTO_HEDERA_KEYS_H
|
||||||
|
|
||||||
|
#include "IKeyPair.h"
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \author: Dario Rekowski
|
||||||
|
*
|
||||||
|
* \date: 2020-08-28
|
||||||
|
*
|
||||||
|
* \brief: Key Pairs class for ed25519 keys, used by hedera for transaction sign
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "sodium.h"
|
||||||
|
#include "iroha-ed25519/include/ed25519/ed25519.h"
|
||||||
|
|
||||||
|
class KeyPairHedera : public IKeyPair
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! \param privateKey: copy
|
||||||
|
//! \param publicKey: copy
|
||||||
|
//!
|
||||||
|
KeyPairHedera(const MemoryBin* privateKey, const MemoryBin* publicKey = nullptr);
|
||||||
|
|
||||||
|
~KeyPairHedera();
|
||||||
|
|
||||||
|
|
||||||
|
//! \return caller take ownership of return value
|
||||||
|
MemoryBin* sign(const MemoryBin* message) const { return sign(message->data(), message->size()); }
|
||||||
|
inline MemoryBin* sign(const std::string& bodyBytes) const { return sign((const unsigned char*)bodyBytes.data(), bodyBytes.size()); }
|
||||||
|
MemoryBin* sign(const unsigned char* message, size_t messageSize) const;
|
||||||
|
|
||||||
|
bool verify(const unsigned char* message, size_t messageSize, MemoryBin* signature) const;
|
||||||
|
|
||||||
|
inline const unsigned char* getPublicKey() const { return mPublicKey; }
|
||||||
|
|
||||||
|
inline bool isTheSame(const KeyPairHedera& b) const {
|
||||||
|
return 0 == sodium_memcmp(mPublicKey, b.mPublicKey, ed25519_pubkey_SIZE);
|
||||||
|
}
|
||||||
|
inline bool isTheSame(const unsigned char* pubkey) const {
|
||||||
|
if (!pubkey)
|
||||||
|
return false;
|
||||||
|
return 0 == sodium_memcmp(mPublicKey, pubkey, ed25519_pubkey_SIZE);
|
||||||
|
}
|
||||||
|
//! \return 0 if the same
|
||||||
|
//! \return -1 if not the same
|
||||||
|
//! \return 1 if hasn't private key
|
||||||
|
inline int isTheSame(const MemoryBin* privkey) const {
|
||||||
|
if (!mPrivateKey) return 1;
|
||||||
|
if (privkey->size() != mPrivateKey->size()) return -1;
|
||||||
|
return sodium_memcmp(*mPrivateKey, *privkey, privkey->size());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator == (const KeyPairHedera& b) const { return isTheSame(b); }
|
||||||
|
inline bool operator != (const KeyPairHedera& b) const { return !isTheSame(b); }
|
||||||
|
|
||||||
|
inline bool operator == (const unsigned char* b) const { return isTheSame(b); }
|
||||||
|
inline bool operator != (const unsigned char* b) const { return !isTheSame(b); }
|
||||||
|
|
||||||
|
inline bool hasPrivateKey() const { return mPrivateKey != nullptr; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
KeyPairHedera();
|
||||||
|
void createKeyFromSeed(const MemoryBin* seed);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// 64 Byte
|
||||||
|
//! \brief ed25519 libsodium private key
|
||||||
|
//!
|
||||||
|
//! TODO: replace MemoryBin by a memory obfuscation class which make it hard to steal the private key from memory
|
||||||
|
MemoryBin* mPrivateKey;
|
||||||
|
|
||||||
|
// 32 Byte
|
||||||
|
//! \brief ed25519 libsodium public key
|
||||||
|
unsigned char mPublicKey[ed25519_pubkey_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //__GRADIDO_LOGIN_SERVER_CRYPTO_HEDERA_KEYS_H
|
||||||
Loading…
x
Reference in New Issue
Block a user