Ali Hatami Tajik
2 years ago
2 changed files with 183 additions and 0 deletions
@ -0,0 +1,156 @@ |
|||
#include "rsa.h" |
|||
|
|||
#include <iostream> |
|||
#include <openssl/aes.h> |
|||
#include <openssl/evp.h> |
|||
#include <openssl/rsa.h> |
|||
#include <openssl/pem.h> |
|||
#include <openssl/ssl.h> |
|||
#include <openssl/bio.h> |
|||
#include <openssl/err.h> |
|||
|
|||
RSA* createPrivateRSA(std::string key) { |
|||
RSA *rsa = NULL; |
|||
const char* c_string = key.c_str(); |
|||
BIO * keybio = BIO_new_mem_buf((void*)c_string, -1); |
|||
if (keybio==NULL) { |
|||
return 0; |
|||
} |
|||
rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULL, NULL); |
|||
return rsa; |
|||
} |
|||
|
|||
RSA* createPublicRSA(std::string key) { |
|||
RSA *rsa = NULL; |
|||
BIO *keybio; |
|||
const char* c_string = key.c_str(); |
|||
keybio = BIO_new_mem_buf((void*)c_string, -1); |
|||
if (keybio==NULL) { |
|||
return 0; |
|||
} |
|||
rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa,NULL, NULL); |
|||
return rsa; |
|||
} |
|||
|
|||
bool RSASign( RSA* rsa, |
|||
const unsigned char* Msg, |
|||
size_t MsgLen, |
|||
unsigned char** EncMsg, |
|||
size_t* MsgLenEnc) { |
|||
EVP_MD_CTX* m_RSASignCtx = EVP_MD_CTX_create(); |
|||
EVP_PKEY* priKey = EVP_PKEY_new(); |
|||
EVP_PKEY_assign_RSA(priKey, rsa); |
|||
if (EVP_DigestSignInit(m_RSASignCtx,NULL, EVP_sha256(), NULL,priKey)<=0) { |
|||
return false; |
|||
} |
|||
if (EVP_DigestSignUpdate(m_RSASignCtx, Msg, MsgLen) <= 0) { |
|||
return false; |
|||
} |
|||
if (EVP_DigestSignFinal(m_RSASignCtx, NULL, MsgLenEnc) <=0) { |
|||
return false; |
|||
} |
|||
*EncMsg = (unsigned char*)malloc(*MsgLenEnc); |
|||
if (EVP_DigestSignFinal(m_RSASignCtx, *EncMsg, MsgLenEnc) <= 0) { |
|||
return false; |
|||
} |
|||
EVP_MD_CTX_free(m_RSASignCtx); |
|||
return true; |
|||
} |
|||
|
|||
bool RSAVerifySignature( RSA* rsa, |
|||
unsigned char* MsgHash, |
|||
size_t MsgHashLen, |
|||
const char* Msg, |
|||
size_t MsgLen, |
|||
bool* Authentic) { |
|||
*Authentic = false; |
|||
EVP_PKEY* pubKey = EVP_PKEY_new(); |
|||
EVP_PKEY_assign_RSA(pubKey, rsa); |
|||
EVP_MD_CTX* m_RSAVerifyCtx = EVP_MD_CTX_create(); |
|||
|
|||
if (EVP_DigestVerifyInit(m_RSAVerifyCtx,NULL, EVP_sha256(),NULL,pubKey)<=0) { |
|||
return false; |
|||
} |
|||
if (EVP_DigestVerifyUpdate(m_RSAVerifyCtx, Msg, MsgLen) <= 0) { |
|||
return false; |
|||
} |
|||
int AuthStatus = EVP_DigestVerifyFinal(m_RSAVerifyCtx, MsgHash, MsgHashLen); |
|||
if (AuthStatus==1) { |
|||
*Authentic = true; |
|||
EVP_MD_CTX_free(m_RSAVerifyCtx); |
|||
return true; |
|||
} else if(AuthStatus==0){ |
|||
*Authentic = false; |
|||
EVP_MD_CTX_free(m_RSAVerifyCtx); |
|||
return true; |
|||
} else{ |
|||
*Authentic = false; |
|||
EVP_MD_CTX_free(m_RSAVerifyCtx); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
void Base64Encode( const unsigned char* buffer, |
|||
size_t length, |
|||
char** base64Text) { |
|||
BIO *bio, *b64; |
|||
BUF_MEM *bufferPtr; |
|||
|
|||
b64 = BIO_new(BIO_f_base64()); |
|||
bio = BIO_new(BIO_s_mem()); |
|||
bio = BIO_push(b64, bio); |
|||
|
|||
BIO_write(bio, buffer, length); |
|||
BIO_flush(bio); |
|||
BIO_get_mem_ptr(bio, &bufferPtr); |
|||
BIO_set_close(bio, BIO_NOCLOSE); |
|||
BIO_free_all(bio); |
|||
|
|||
*base64Text=(*bufferPtr).data; |
|||
} |
|||
|
|||
size_t calcDecodeLength(const char* b64input) { |
|||
size_t len = strlen(b64input), padding = 0; |
|||
|
|||
if (b64input[len-1] == '=' && b64input[len-2] == '=') //last two chars are =
|
|||
padding = 2; |
|||
else if (b64input[len-1] == '=') //last char is =
|
|||
padding = 1; |
|||
return (len*3)/4 - padding; |
|||
} |
|||
|
|||
void Base64Decode(const char* b64message, unsigned char** buffer, size_t* length) { |
|||
BIO *bio, *b64; |
|||
|
|||
int decodeLen = calcDecodeLength(b64message); |
|||
*buffer = (unsigned char*)malloc(decodeLen + 1); |
|||
(*buffer)[decodeLen] = '\0'; |
|||
|
|||
bio = BIO_new_mem_buf(b64message, -1); |
|||
b64 = BIO_new(BIO_f_base64()); |
|||
bio = BIO_push(b64, bio); |
|||
|
|||
*length = BIO_read(bio, *buffer, strlen(b64message)); |
|||
BIO_free_all(bio); |
|||
} |
|||
|
|||
char* sign(std::string privateKey, std::string plainText) { |
|||
RSA* privateRSA = createPrivateRSA(privateKey); |
|||
unsigned char* encMessage; |
|||
char* base64Text; |
|||
size_t encMessageLength; |
|||
RSASign(privateRSA, (unsigned char*) plainText.c_str(), plainText.length(), &encMessage, &encMessageLength); |
|||
Base64Encode(encMessage, encMessageLength, &base64Text); |
|||
free(encMessage); |
|||
return base64Text; |
|||
} |
|||
|
|||
bool verify(std::string publicKey, std::string plainText, char* signatureBase64) { |
|||
RSA* publicRSA = createPublicRSA(publicKey); |
|||
unsigned char* encMessage; |
|||
size_t encMessageLength; |
|||
bool authentic; |
|||
Base64Decode(signatureBase64, &encMessage, &encMessageLength); |
|||
bool result = RSAVerifySignature(publicRSA, encMessage, encMessageLength, plainText.c_str(), plainText.length(), &authentic); |
|||
return result & authentic; |
|||
} |
@ -0,0 +1,27 @@ |
|||
#ifndef _SONO_KEY_RSA_H |
|||
#define _SONO_KEY_RSA_H |
|||
|
|||
#include <string> |
|||
|
|||
/**
|
|||
* @brief Signs msg with RSA |
|||
* |
|||
* @param private_key private key to encrypt the massage |
|||
* @param msg massage |
|||
* @return char* generated signature |
|||
*/ |
|||
char* sign(std::string private_key, std::string msg); |
|||
|
|||
|
|||
/**
|
|||
* @brief Verifies weather public key is working correctly or not |
|||
* |
|||
* @param public_key public key to decrypt the massages |
|||
* @param expected_msg expected decrypted massage |
|||
* @param signatureBase64 signature read from device |
|||
* @return true if signature and massage matched |
|||
* @return false if they don't |
|||
*/ |
|||
bool verify(std::string public_key, std::string expected_msg, char* signatureBase64); |
|||
|
|||
#endif |
Loading…
Reference in new issue