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