/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: RSAPublic.cpp Date: 2021-6-12 Author: Reece ***/ #include #include "../Crypto.hpp" #include "RSA.hpp" #include "RSAPublic.hpp" namespace Aurora::Crypto::RSA { PublicRSA::PublicRSA(rsa_key &key, bool owned) : key_(key), owned_(owned) { } PublicRSA::~PublicRSA() { if (this->owned_) { ::rsa_free(&this->key_); } } bool PublicRSA::Verify(const AuMemoryViewRead &payload, const AuMemoryViewRead &signature, EHashType method, EPaddingType type) { if (!payload.HasMemory()) { SysPushErrorParam(); return {}; } if (!signature.HasMemory()) { SysPushErrorParam(); return {}; } int padding = PaddingToType(type); if (padding == 0xFF) { SysPushErrorCrypt("invalid pad {}", type); return false; } int hash = HashMethodToId(method); if (hash == 0xFF) { SysPushErrorCrypt("invalid hash {}", method); return false; } AuByteBuffer hashVec; if (!AuTryResize(hashVec, 128)) { SysPushErrorMem(); return false; } unsigned long hashSize = hashVec.size(); auto iRet = ::hash_memory(hash, AuReinterpretCast(payload.ptr), payload.length, AuReinterpretCast(hashVec.data()), &hashSize); if (iRet != CRYPT_OK) { SysPushErrorCrypt("{}", iRet); return false; } int ok = 0; iRet = ::rsa_verify_hash_ex(AuReinterpretCast(signature.ptr), signature.length, AuReinterpretCast(hashVec.data()), hashSize, padding, hash, 0, &ok, &this->key_); if (iRet != CRYPT_OK) { SysPushErrorCrypt("{}", iRet); return false; } return ok == 1; } bool PublicRSA::Encrypt(const Memory::MemoryViewRead &plainText, EPaddingType type, AuMemory::ByteBuffer &out) { prng_state yarrow_prng; if (!plainText.HasMemory()) { SysPushErrorParam(); return {}; } int padding = PaddingToType(type); if (padding == 0xFF) { SysPushErrorCrypt("invalid pad {}", type); return false; } const int prng_idx = padding == LTC_PKCS_1_PSS ? ::Crypto::gPrngYarrow : 0; if (prng_idx < 0) { SysPushErrorCrypt("{}", prng_idx); return false; } auto writeView = out.GetOrAllocateLinearWriteable(plainText.length + 1024); if (!writeView) { SysPushErrorMem(); return {}; } unsigned long len = out.size(); auto iREt = ::rsa_encrypt_key_ex(AuReinterpretCast(plainText.ptr), plainText.length, out.writePtr, &len, NULL, 0, &yarrow_prng, prng_idx, 0, padding, &this->key_); if (iREt != CRYPT_OK) { SysPushErrorCrypt("{}", iREt); return false; } out.writePtr += len; return true; } bool PublicRSA::ToKey(ERSAKeyType type, AuByteBuffer &out) { return ExportRSAKey(this->key_, EKeyType::eKeyPublic, type, out); } AUKN_SYM IRSAPublic *OpenRSAPublicNew(const RSAKey &key) { rsa_key in {}; if (!ImportRSAKey(in, key)) { return nullptr; } auto pPublic = _new PublicRSA(in, true); if (!pPublic) { ::rsa_free(&in); return nullptr; } return pPublic; } AUKN_SYM void OpenRSAPublicRelease(IRSAPublic *pPublic) { AuSafeDelete(pPublic); } }