-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #38 from HLRichardson-Git/RSA
Adds RSA key encryption and signature scheme
- Loading branch information
Showing
39 changed files
with
2,413 additions
and
106 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,4 +17,5 @@ | |
#include "hmac_sha1.h" | ||
#include "hmac_sha2.h" | ||
#include "ecdsa.h" | ||
#include "rsa.h" | ||
#include "ecdh.h" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/* | ||
* Copyright 2023-2024 The Gestalt Project Authors. All Rights Reserved. | ||
* | ||
* Licensed under the MIT License. See the file LICENSE for the full text. | ||
*/ | ||
|
||
/* | ||
* rsa.h | ||
* | ||
* RSA is a widely used asymmetric encryption algorithm that relies on the difficulty of factoring | ||
* large numbers. The class provides both basic RSA operations (without padding) and secure | ||
* operations with padding schemes for enhanced security. | ||
* | ||
* This file defines the RSA class, which provides functionality for RSA encryption, | ||
* decryption, digital signatures, and signature verification. The RSA class supports | ||
* both raw RSA operations and padded encryption/signature schemes (e.g., OAEP and PSS). | ||
* | ||
*/ | ||
|
||
# pragma once | ||
|
||
#include "rsa/rsa_key_generation/rsaKeyGen.h" | ||
#include "rsa/padding_schemes/rsa_padding.h" | ||
|
||
class RSA { | ||
private: | ||
RSAKeyPair keyPair; | ||
|
||
BigInt rawEncrypt(const BigInt& plaintext, const RSAPublicKey& recipientPublicKey) const; | ||
BigInt rawDecrypt(const BigInt& ciphertext) const; | ||
|
||
BigInt rawSignatureGen(const BigInt& messageHash) const; | ||
BigInt rawSignatureVer(const BigInt& signature, const RSAPublicKey& recipientPublicKey) const; | ||
|
||
public: | ||
RSA() {}; | ||
RSA(RSAKeyGenOptions keyGenerationOptions) // TODO: Make a unit test for this constructor | ||
: keyPair(keyGenerationOptions) {} | ||
RSA(RSASecurityStrength specifiedStength, const RSAPrivateKey& privateKey, const RSAPublicKey& publicKey) | ||
: keyPair(specifiedStength, privateKey, publicKey) {} | ||
|
||
RSAPrivateKey getPrivateKey() const { return keyPair.getPrivateKey(); }; | ||
RSAPublicKey getPublicKey() const { return keyPair.getPublicKey(); }; | ||
|
||
std::string encrypt(const std::string& plaintext, const RSAPublicKey& recipientPublicKey); | ||
std::string encrypt(const std::string& plaintext, const RSAPublicKey& recipientPublicKey, const OAEPParams& parameters); | ||
|
||
std::string decrypt(const std::string& ciphertext); | ||
std::string decrypt(const std::string& ciphertext, const OAEPParams& parameters); | ||
|
||
std::string signMessage(const std::string& message, HashAlgorithm hashAlg = HashAlgorithm::None); | ||
std::string signMessage(const std::string& message, const PSSParams& parameters, HashAlgorithm hashAlg = HashAlgorithm::None); | ||
|
||
bool verifySignature(const std::string& message, const std::string& signature, const RSAPublicKey& recipientPublicKey, HashAlgorithm hashAlg = HashAlgorithm::None); | ||
bool verifySignature(const std::string& message, const std::string& signature, const RSAPublicKey& recipientPublicKey, const PSSParams& parameters, HashAlgorithm hashAlg = HashAlgorithm::None); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/* | ||
* Copyright 2023-2024 The Gestalt Project Authors. All Rights Reserved. | ||
* | ||
* Licensed under the MIT License. See the file LICENSE for the full text. | ||
*/ | ||
|
||
/* | ||
* oaep.cpp | ||
* | ||
* This file provides the implementation for the Optimal Asymmetric Encryption Padding (OAEP) scheme used in RSA | ||
* encryption. It includes functions for applying and removing OAEP padding with configurable hash functions and mask | ||
* generation functions (MGF1). | ||
* | ||
* This file provides functions for applying and removing OAEP padding, based on PKCS #1 v2.2 | ||
* (see https://tools.ietf.org/html/rfc8017). The implementation includes hash-based mask generation using MGF1, | ||
* supporting configurable hash functions and label handling. | ||
* | ||
*/ | ||
|
||
#include <iostream> | ||
#include <string> | ||
|
||
#include "oaep.h" | ||
#include <gestalt/sha1.h> | ||
#include <gestalt/sha2.h> | ||
#include "utils.h" | ||
|
||
std::string applyOAEP_Padding(const std::string& input, const OAEPParams& params, unsigned int modulusSizeBytes) { | ||
unsigned int hashLength = static_cast<unsigned int>(params.hashFunc); | ||
unsigned int inputLength = input.length(); // This inheriently means it can only handle ASCII for now | ||
int psLen = modulusSizeBytes - inputLength - (2 * hashLength) - 2; | ||
|
||
if (psLen < 0) { | ||
throw std::invalid_argument("Message too long for RSA modulus"); | ||
} | ||
std::string PS(psLen, 0x00); | ||
|
||
// TODO: convert the output of hashSHA256 to bytes because you will find that the DB length is 255 | ||
// because it is doing it correctly, but since the output of hashSHA256 is in hex, and the length of DB | ||
// is expected as bytes its "counting the byte twice", so its adding 32 to the length | ||
// Maybe this is an overall flaw of the SHA implementations I have... | ||
std::string DB = hexToBytes(hash(params.hashFunc)(params.label)) + PS + "\x01" + input; | ||
|
||
std::string seed = params.seed; | ||
if (seed.empty()) { | ||
seed = generateRandomHexData(hashLength); | ||
} | ||
|
||
std::string dbMask = hexToBytes(mgf1(hexToBytes(seed), modulusSizeBytes - hashLength - 1, params.hashFunc)); | ||
std::string maskedDB; | ||
for (size_t i = 0; i < DB.length(); ++i) { | ||
maskedDB += DB[i] ^ dbMask[i]; | ||
} | ||
|
||
std::string seedMask = hexToBytes(mgf1(maskedDB, hashLength, params.hashFunc)); | ||
std::string maskedSeed; | ||
seed = hexToBytes(seed); | ||
for (size_t i = 0; i < hashLength; ++i) { | ||
maskedSeed += seed[i] ^ seedMask[i]; | ||
} | ||
|
||
return std::string(1, 0x00) + maskedSeed + maskedDB; // EM | ||
} | ||
|
||
std::string removeOAEP_Padding(const std::string& input, const OAEPParams& params, unsigned int modulusSizeBytes) { | ||
if (static_cast<unsigned char>(input[0]) != 0x00) { | ||
throw std::invalid_argument("Given OAEP message does not begin with 0x00"); | ||
} | ||
|
||
unsigned int hashLength = static_cast<unsigned int>(params.hashFunc); | ||
|
||
std::string maskedSeed = input.substr(1, hashLength); | ||
std::string maskedDB = input.substr(hashLength + 1, input.length()); | ||
|
||
std::string seedMask = hexToBytes(mgf1(maskedDB, hashLength, params.hashFunc)); | ||
std::string seed; | ||
for (size_t i = 0; i < seedMask.length(); ++i) { | ||
seed += maskedSeed[i] ^ seedMask[i]; | ||
} | ||
|
||
std::string dbMask = hexToBytes(mgf1(seed, modulusSizeBytes - hashLength - 1, params.hashFunc)); | ||
|
||
std::string DB; | ||
for (size_t i = 0; i < maskedDB.length(); ++i) { | ||
DB += maskedDB[i] ^ dbMask[i]; | ||
} | ||
|
||
std::string lhash = hexToBytes(hash(params.hashFunc)(params.label)); | ||
if (DB.substr(0, hashLength) != lhash) { | ||
throw std::invalid_argument("OAEP Decode Error: The encoded lhash and computed lhash are not the same."); | ||
} | ||
|
||
int psStartPos = hashLength + 1; // Padding starts after lhash and the 0x01 delimiter | ||
int psEndPos = DB.find(0x01, psStartPos); // Look for the 0x01 byte which ends PS | ||
|
||
if (psEndPos == std::string::npos || psEndPos <= psStartPos) { | ||
throw std::invalid_argument("OAEP Decode Error: Padding 0x01 byte not found."); | ||
} | ||
|
||
// Ensure all bytes from psStartPos to psEndPos-1 are zero (the PS) | ||
for (int i = psStartPos; i < psEndPos; i++) { | ||
if (DB[i] != 0x00) { | ||
throw std::invalid_argument("OAEP Decode Error: Non-zero byte found in padding (PS)."); | ||
} | ||
} | ||
|
||
return DB.substr(psEndPos + 1, DB.length()); | ||
} |
Oops, something went wrong.