/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: PrivateECCImpl.cpp File: ECCGeneric.cpp Date: 2021-9-17 File: KCryptoECC.cpp Date: 2021-1-15 Author: Reece ***/ #include #include "ECC.hpp" #include "ECCGeneric.hpp" #include "ECCCurves.hpp" #include "PrivateECCImpl.hpp" #include "PublicECCImpl.hpp" namespace Aurora::Crypto::ECC { PrivateECCImpl::PrivateECCImpl(EECCCurve type, ecc_key &key) : _key(key), _type(type) { } PrivateECCImpl::~PrivateECCImpl() { ecc_free(&this->_key); } EECCCurve PrivateECCImpl::GetType() { return this->_type; } bool PrivateECCImpl::Sign(const AuMemoryViewRead &plainText, AuHashing::EHashType method, AuByteBuffer &out) { const int salt = 0; if (!plainText.HasMemory()) { SysPushErrorParam(); return {}; } int hash = ::Crypto::HashMethodToId(method); if (hash == 0xFF) { SysPushErrorCrypt("invalid hash {}", AuUInt(method)); return false; } if (!AuTryResize(out, 1024)) { SysPushErrorMem(); return false; } AuByteBuffer hashVec; if (!AuTryResize(hashVec, 128)) { SysPushErrorMem(); return false; } unsigned long hashSize = hashVec.size(); auto ret = ::hash_memory(hash, AuReinterpretCast(plainText.ptr), plainText.length, AuReinterpretCast(hashVec.data()), &hashSize); if (ret != CRYPT_OK) { SysPushErrorCrypt("{}", ret); return false; } return Sign(hashVec, out); } bool PrivateECCImpl::Sign(const AuMemoryViewRead &hash, AuByteBuffer &out) { int iRet; prng_state yarrow_prng; if (!hash.HasMemory()) { SysPushErrorParam(); return {}; } if (!out.GetOrAllocateLinearWriteable(1024)) { SysPushErrorMem(); return {}; } iRet = yarrow_start(&yarrow_prng); if (iRet != CRYPT_OK) { SysPushErrorCrypt("{}", iRet); return false; } unsigned long len = 1024; iRet = ::ecc_sign_hash_ex(AuReinterpretCast(hash.ptr), hash.length, out.writePtr, &len, &yarrow_prng, ::Crypto::gPrngYarrow, LTC_ECCSIG_ETH27, nullptr, &this->_key); if (iRet != CRYPT_OK) { SysPushErrorCrypt("{}", iRet); return false; } out.writePtr += len; return true; } bool PrivateECCImpl::ECDH(const AuSPtr &partnerPublic, AuByteBuffer &sharedKey) { auto writeView = sharedKey.GetOrAllocateLinearWriteable(128); if (!writeView) { SysPushErrorMem(); return {}; } if (partnerPublic->GetType() != this->GetType()) { SysPushErrorCrypto("Can not EDCH with incompatible curve type (noting ed25519 requires translation to x25519)"); return false; } unsigned long actualSize = 128; auto ret = ::ecc_shared_secret(&this->_key, &(AuReinterpretCast(partnerPublic)->GetKey()), sharedKey.writePtr, &actualSize); if (ret != CRYPT_OK) { SysPushErrorCrypt("{}", ret); return false; } sharedKey.writePtr += actualSize; return true; } bool PrivateECCImpl::AsPublicECC(AuByteBuffer &out) { return ExportECCKey(this->_key, true, out); } bool PrivateECCImpl::AsPrivateECC(AuByteBuffer &out) { return ExportECCKey(this->_key, false, out); } }