I'm using openssl c lib to encrypt decrypt a file using 3DES, If the file contains a few words, the file will be encrypted and decrypted ok, But if the source plain file contains more words, it decrypted incorrectly. Any suggestions would be kind!
#include <stdio.h>
#include <stdlib.h>
#include <openssl/pem.h>
#include <openssl/conf.h>
#include <openssl/x509v3.h>
#include <openssl/pkcs12.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/md5.h>
#include <openssl/rc4.h>
#include <iostream>
using namespace std;
#define MAX_PATH 512
#define BUFLEN 2048
void DoEncrypt(const char* srcfile, const char* enc_file)
{
char mykey[EVP_MAX_KEY_LENGTH] = "this's my key";
char iv[EVP_MAX_IV_LENGTH] = "my iv";
char ciphertext[BUFLEN*2] = {0};
char plaintext[BUFLEN] = {0};
FILE* fpread = fopen(srcfile, "rb");
int iReadLen = 0;
if (NULL == fpread)
{
cout<<"do encrypt read src file fail" <<endl;
return;
}
FILE* fpwrite = fopen(enc_file, "w+");
if (NULL == fpwrite)
{
cout<<"enc_file to create fail" <<endl;
fclose(fpread);
return;
}
const EVP_CIPHER* cipherType = EVP_des_ede3_ecb();
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
int out_len;
EVP_EncryptInit(&ctx, cipherType, (const unsigned char*)mykey, (const unsigned char*)iv);
while ( (iReadLen = fread(plaintext, 1, BUFLEN, fpread)) > 0 )
{
memset(ciphertext, 0x00, sizeof(ciphertext));
EVP_EncryptUpdate(&ctx, (unsigned char*)ciphertext, &out_len, (const unsigned char*)plaintext, iReadLen);
fwrite(ciphertext, 1, out_len, fpwrite);
memset(plaintext, 0x00, sizeof(plaintext));
}
EVP_EncryptFinal(&ctx, (unsigned char*)ciphertext, &out_len);
fwrite(ciphertext, 1, out_len, fpwrite);
EVP_CIPHER_CTX_cleanup(&ctx);
fclose(fpread);
fclose(fpwrite);
cout<< "DoEncrypt finish" <<endl;
}
void DoDecrypt(const char* enc_file, const char* dec_file)
{
char mykey[EVP_MAX_KEY_LENGTH] = "this's my key";
char iv[EVP_MAX_IV_LENGTH] = "my iv";
char ciphertext[BUFLEN*2] = {0};
char plaintext[BUFLEN] = {0};
FILE* fpread = fopen(enc_file, "rb");
if (NULL == fpread)
{
cout<<"DoDecrypt enc file open fail" <<endl;
return;
}
FILE* fpwrite = fopen(dec_file, "w+");
if (NULL == fpwrite)
{
cout<< "DoDecrypt open dec file create fail" <<endl;
fclose(fpread);
return;
}
const EVP_CIPHER* cipherType = EVP_des_ede3_ecb();
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_DecryptInit(&ctx, (const EVP_CIPHER*)cipherType, (const unsigned char*)mykey, (const unsigned char*)iv);
int iReadLen, out_len;
while ( (iReadLen = fread(plaintext, 1, BUFLEN, fpread)) > 0 )
{
memset(ciphertext, 0x00, sizeof(ciphertext));
EVP_DecryptUpdate(&ctx, (unsigned char*)ciphertext, &out_len, (const unsigned char*)plaintext, iReadLen);
fwrite(ciphertext, 1, out_len, fpwrite);
memset(plaintext, 0x00, sizeof(plaintext));
}
EVP_DecryptFinal(&ctx, (unsigned char*)ciphertext, &out_len);
fwrite(ciphertext, 1, out_len, fpwrite);
EVP_CIPHER_CTX_cleanup(&ctx);
fclose(fpread);
fclose(fpwrite);
cout<< "DoDecrypt finished" <<endl;
}
int main(void)
{
const char* srcfile = "abc.txt";
const char* enc_file = "abc.txt.enc";
const char* dec_file = "abc.txt.dec";
DoEncrypt(srcfile, enc_file);
DoDecrypt(enc_file, dec_file);
return 0;
}
You need "w+b" instead of "w+" in your fopen calls.
Related
I´ve created a rsa class with Openssl EVP (OpenSSL Ref) Methods.
rsa.h
#ifndef RSA_RSA_H
#define RSA_RSA_H
#include <string>
#include <stdexcept>
#include <sstream>
#include <iostream>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include "utils.h"
#define PADDING RSA_PKCS1_OAEP_PADDING
#define LOGGING
namespace tools
{
class CryptoRSA
{
private:
int _keysize;
char *_rsaPrivateKeyStr, *_privateKeyStr, *_publicKeyStr;
unsigned char* _encryptedKey, *_iv;
EVP_PKEY *_pkey;
EVP_CIPHER_CTX *rsaEncryptContext, *rsaDecryptContext;
static std::string getOpenSSLError();
bool generateRSAKey();
bool loadKeyFromFile(const std::string &filepath);
bool loadKeyFromStr(const std::string &str);
public:
explicit CryptoRSA(int keysize);
explicit CryptoRSA(const std::string &key);
virtual ~CryptoRSA();
inline unsigned char* getRSAIV() const { return _iv; }
inline unsigned char* getRSAEncryptedKey() const { return _encryptedKey; }
inline EVP_PKEY *getEvpPkey() { return _pkey; }
inline int getEvpPkeySize(EVP_PKEY *key) { return EVP_PKEY_size(key); }
char *getRSAPrivateKeyStr();
char *getPrivateKeyStr();
char *getPublicKeyStr();
int encryptEVP(EVP_PKEY *key, const unsigned char *message, size_t messageLength, unsigned char **encryptedMessage, unsigned char **encryptedKey, size_t *encryptedKeyLength, unsigned char **iv);
int decryptEVP(EVP_PKEY *key, unsigned char *encryptedMessage, size_t encryptedMessageLength, unsigned char *encryptedKey, size_t encryptedKeyLength, unsigned char *iv, unsigned char **decryptedMessage);
};
} // namespace tools
#endif //RSA_RSA_H
and rsa.cpp
#include "rsa.h"
namespace tools
{
CryptoRSA::CryptoRSA(int keysize) : _keysize(keysize), _pkey(nullptr)
{
// Initalize contexts
rsaEncryptContext = EVP_CIPHER_CTX_new();
rsaDecryptContext = EVP_CIPHER_CTX_new();
// Generate the RSA Key
if ( !generateRSAKey() )
{
#ifdef LOGGING
std::cerr << "Error at generating the RSA key!" << std::endl;
#endif
throw std::runtime_error("Error at generating the RSA key!");
}
}
CryptoRSA::CryptoRSA(const std::string &key) : _keysize(-1), _pkey(nullptr)
{
// Initalize contexts
rsaEncryptContext = EVP_CIPHER_CTX_new();
rsaDecryptContext = EVP_CIPHER_CTX_new();
// Load pkey from file or string
if ( !loadKeyFromFile(key) )
{
#ifdef LOGGING
std::cerr << "Could not load key from file/string!" << std::endl;
#endif
}
}
CryptoRSA::~CryptoRSA()
{
EVP_PKEY_free(_pkey);
EVP_CIPHER_CTX_free(rsaEncryptContext);
EVP_CIPHER_CTX_free(rsaDecryptContext);
}
std::string CryptoRSA::getOpenSSLError()
{
char *buf;
BIO *bio = BIO_new(BIO_s_mem());
ERR_print_errors(bio);
size_t len = static_cast<size_t >(BIO_get_mem_data(bio, &buf));
std::string err(buf, len);
BIO_free(bio);
return err;
}
bool CryptoRSA::generateRSAKey()
{
EVP_PKEY_CTX *context = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
if(EVP_PKEY_keygen_init(context) <= 0)
{
return false;
}
if(EVP_PKEY_CTX_set_rsa_keygen_bits(context, _keysize) <= 0)
{
return false;
}
if(EVP_PKEY_keygen(context, &_pkey) <= 0)
{
return false;
}
EVP_PKEY_CTX_free(context);
return true;
}
bool CryptoRSA::loadKeyFromFile(const std::string &filepath)
{
if ( existsFile(filepath) )
{
if ( loadKeyFromStr(readBinFile(filepath)) )
{
#ifdef LOGGING
std::cerr << "Loaded successfully rsa key from file " << filepath << std::endl;
#endif
return true;
}
} else
{
if ( loadKeyFromStr(filepath) )
{
#ifdef LOGGING
std::cerr << "Loaded successfully rsa key from string!" << std::endl;
#endif
return true;
}
}
return false;
}
bool CryptoRSA::loadKeyFromStr(const std::string &str)
{
std::string fLine;
std::istringstream f(str);
std::getline(f, fLine);
BIO *bioPrivate = BIO_new(BIO_s_mem());
BIO_write(bioPrivate, str.c_str(), static_cast<int>(str.length()));
if (fLine == "-----BEGIN RSA PRIVATE KEY-----")
{
_pkey = PEM_read_bio_PrivateKey(bioPrivate, nullptr, nullptr, nullptr);
} else if (fLine == "-----BEGIN PUBLIC KEY-----")
{
_pkey = PEM_read_bio_PUBKEY(bioPrivate, nullptr, nullptr, nullptr);
} else
{
#ifdef LOGGING
std::cerr << "Unsupported file provided with file header: " << fLine << std::endl;
#endif
BIO_free(bioPrivate);
return false;
}
BIO_free(bioPrivate);
return true;
}
char* CryptoRSA::getRSAPrivateKeyStr()
{
RSA *rsaPrivateKey = EVP_PKEY_get0_RSA(_pkey);
BIO *bioPrivate = BIO_new(BIO_s_mem());
PEM_write_bio_RSAPrivateKey(bioPrivate, rsaPrivateKey, nullptr, nullptr, 0, nullptr, nullptr);
BIO_flush(bioPrivate);
BIO_get_mem_data(bioPrivate, &_rsaPrivateKeyStr);
return _rsaPrivateKeyStr;
}
char* CryptoRSA::getPrivateKeyStr()
{
BIO *bioPrivate = BIO_new(BIO_s_mem());
PEM_write_bio_PrivateKey(bioPrivate, _pkey, NULL, NULL, 0, 0, NULL);
BIO_flush(bioPrivate);
BIO_get_mem_data(bioPrivate, &_privateKeyStr);
return _privateKeyStr;
}
char* CryptoRSA::getPublicKeyStr()
{
BIO *bioPublic = BIO_new(BIO_s_mem());
PEM_write_bio_PUBKEY(bioPublic, _pkey);
BIO_flush(bioPublic);
BIO_get_mem_data(bioPublic, &_publicKeyStr);
return _publicKeyStr;
}
int CryptoRSA::encryptEVP(EVP_PKEY *key, const unsigned char *message, size_t messageLength, unsigned char **encryptedMessage,
unsigned char **encryptedKey, size_t *encryptedKeyLength, unsigned char **iv)
{
// Allocate memory for everything
size_t encryptedMessageLength = 0;
size_t blockLength = 0;
*encryptedKey = (unsigned char*)malloc(EVP_PKEY_size(key));
*iv = (unsigned char*)malloc(EVP_MAX_IV_LENGTH);
*encryptedMessage = (unsigned char*)malloc(messageLength + EVP_MAX_IV_LENGTH);
if(!EVP_SealInit(rsaEncryptContext, EVP_aes_256_cbc(), encryptedKey, (int*)encryptedKeyLength, *iv, &key, 1))
{
#ifdef LOGGING
std::cerr << "Error during EVP_SealInit in RSA encrypt: " << getOpenSSLError() << std::endl;
#endif
return -1;
}
if(!EVP_SealUpdate(rsaEncryptContext, *encryptedMessage + encryptedMessageLength, (int*)&blockLength, (const unsigned char*)message, (int)messageLength))
{
#ifdef LOGGING
std::cerr << "Error during EVP_SealUpdate in RSA encrypt: " << getOpenSSLError() << std::endl;
#endif
return -1;
}
encryptedMessageLength += blockLength;
if(!EVP_SealFinal(rsaEncryptContext, *encryptedMessage + encryptedMessageLength, (int*)&blockLength))
{
#ifdef LOGGING
std::cerr << "Error during EVP_SealFinal in RSA encrypt: " << getOpenSSLError() <<std::endl;
#endif
return -1;
}
encryptedMessageLength += blockLength;
return (int)encryptedMessageLength;
}
int CryptoRSA::decryptEVP(EVP_PKEY *key, unsigned char *encryptedMessage, size_t encryptedMessageLength, unsigned char *encryptedKey,
size_t encryptedKeyLength, unsigned char *iv, unsigned char **decryptedMessage)
{
// Allocate memory for everything
size_t decryptedMessageLength = 0;
size_t blockLength = 0;
*decryptedMessage = (unsigned char*)malloc(encryptedMessageLength + EVP_MAX_IV_LENGTH);
// Decrypt it!
if(!EVP_OpenInit(rsaDecryptContext, EVP_aes_256_cbc(), encryptedKey, getEvpPkeySize(key), iv, key))
{
#ifdef LOGGING
std::cerr << "Error during EVP_OpenInit in RSA decrypt: " << getOpenSSLError() << std::endl;
#endif
return -1;
}
if(!EVP_OpenUpdate(rsaDecryptContext, (unsigned char*)*decryptedMessage + decryptedMessageLength, (int*)&blockLength, encryptedMessage, (int)encryptedMessageLength))
{
#ifdef LOGGING
std::cerr << "Error during EVP_OpenUpdate in RSA decrypt: " << getOpenSSLError() << std::endl;
#endif
return -1;
}
decryptedMessageLength += blockLength;
if(!EVP_OpenFinal(rsaDecryptContext, (unsigned char*)*decryptedMessage + decryptedMessageLength, (int*)&blockLength))
{
#ifdef LOGGING
std::cerr << "Error during EVP_OpenFinal in RSA decrypt: " << getOpenSSLError() << std::endl;
#endif
return -1;
}
decryptedMessageLength += blockLength;
return (int)decryptedMessageLength;
}
} // namespace tools
main.cpp
#include <iostream>
#include <memory>
#include <cstring>
#include "rsa.h"
bool writeBinFile(const std::string &filepath, const char* content, long contentLength, bool append=false)
{
std::fstream out;
if (append)
{
out.open(filepath, std::ios::out | std::ios::app | std::ios::binary);
} else
{
out.open(filepath, std::ios::out | std::ios::binary);
}
if (out.is_open())
{
out.write(content, contentLength);
return true;
} else
{
return false;
}
}
void encrypt_decrypt_with_evp(std::string msg_to_encrypt)
{
std::unique_ptr<tools::CryptoRSA> cryptoRSA = std::unique_ptr<tools::CryptoRSA>(new tools::CryptoRSA(2048));
unsigned char *encryptedMessage = nullptr;
char *decryptedMessage = nullptr;
unsigned char *encryptedKey;
unsigned char *iv;
size_t encryptedKeyLength;
std::string priv = cryptoRSA->getRSAPrivateKeyStr();
std::string pub = cryptoRSA->getPublicKeyStr();
// Save RSA KeyPair
writeBinFile("RSAPrivateKey.pem", priv.c_str(), priv.length());
writeBinFile("PublicKey.pem", pub.c_str(), pub.length());
// Start RSA Encryption
int encryptedMessageLength = cryptoRSA->encryptEVP(cryptoRSA->getEvpPkey(), (const unsigned char*)msg_to_encrypt.c_str(), msg_to_encrypt.size()+1,
&encryptedMessage, &encryptedKey, &encryptedKeyLength, &iv);
if(encryptedMessageLength == -1)
{
std::cerr << "Encryption failed" << std::endl;
exit(1);
}
std::cout << "Encrypted message: " << encryptedMessage << std::endl;
writeBinFile("enc_msg.bin", reinterpret_cast<const char *>(encryptedMessage), encryptedMessageLength);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Start RSA Decryption
int decryptedMessageLength = cryptoRSA->decryptEVP(cryptoRSA->getEvpPkey(), encryptedMessage, (size_t)encryptedMessageLength,
encryptedKey, encryptedKeyLength, iv, (unsigned char**)&decryptedMessage);
if(decryptedMessageLength == -1)
{
std::cerr << "Decryption failed" << std::endl;
exit(1);
}
std::cout << "Decrypted message: " << decryptedMessage << std::endl;
}
int main(int argc, char* argv[])
{
encrypt_decrypt_with_evp("abcdef");
return 0;
}
The RSA Encryption and Decryption with the implemented class works completely fine.
What i would like to achieve is the following:
Encrypt a message like abcdef with my implemented solution and save the content in a file enc_msg.bin
Using the openssl command line interface (for instance: openssl rsautl) to decrypt the message
Or:
Encrypt the message abcdef with the openssl command line interface
Decrypt the created file with my implemented solution
As you can see the EVP_SealInit uses the EVP_aes_256_cbc with an encryptedKey and an IV. But i didn´t find a possibility to provide those parameters to the openssl rsautl cli.
Does anyone know how to decrypt messages (with Openssl cli) which were created with the EVP methods (EVP_SealInit, EVP_SealUpdate, EVP_SealFinal)?
Every help is highly appreciated!
With the help of #Topaco i found the solution. It is a Hybrid Encryption
I saved also the EncryptedKey and the IV to rsa_ek.bin and rsa_iv.txt file.
Decrypt the rsa_ek.bin with the openssl rsautl cli
openssl rsautl -decrypt -inkey RSAPrivateKey.pem -in rsa_ek.bin -out rsa_ek.txt
Decrypt the enc_msg.bin file with the AES-256-CBC Cipher
openssl enc -aes-256-cbc -d -in enc_msg.bin -K $(xxd -p -c 256 rsa_ek.txt) -iv $(xxd -p -c 256 rsa_iv.txt) -out enc_msg.dec.txt
I'm learning C++ at the moment and wanted to learn more about this exploit...
I'm using Linux and tried to compile it with the "g++ examplefile.ccp -o outputfile" command.
#include <jni.h>
#include <string>
#include <dlfcn.h>
#include <link.h>
typedef uint8_t byte;
char *gadget_p;
void* libc,* lib;
//dls iteration for rop
int dl_callback(struct dl_phdr_info *info, size_t size, void *data)
{
int j;
const char *base = (const char *)info->dlpi_addr;
for (j = 0; j < info->dlpi_phnum; j++) {
const ElfW(Phdr) *phdr = &info->dlpi_phdr[j];
if (phdr->p_type == PT_LOAD && (strcmp("/system/lib64/libhwui.so",info->dlpi_name) == 0)) {
gadget_p = (char *) base + phdr->p_vaddr;
return 1;
}
}
return 0;
}
//system address
void* get_system_address(){
libc = dlopen("libc.so",RTLD_GLOBAL);
void* address = dlsym( libc, "system");
return address;
}
//rop gadget address
void get_gadget_lib_base_address() {
lib = dlopen("libhwui.so",RTLD_GLOBAL);
dl_iterate_phdr(dl_callback, NULL);
}
//search gadget
long search_for_gadget_offset() {
char *buffer;
long filelen;
char curChar;
long pos = 0; int curSearch = 0;
//reading file
FILE* fd = fopen("/system/lib64/libhwui.so","rb");
fseek(fd, 0, SEEK_END);
filelen = ftell(fd);
rewind(fd);
buffer = (char *)malloc((filelen+1)*sizeof(char));
fread(buffer, filelen, 1, fd);
fclose(fd);
//searching for bytes
byte g1[12] = {0x68, 0x0E, 0x40, 0xF9, 0x60, 0x82, 0x00, 0x91, 0x00, 0x01, 0x3F, 0xD6};
while(pos <= filelen){
curChar = buffer[pos];pos++;
if(curChar == g1[curSearch]){
curSearch++;
if(curSearch > 11){
curSearch = 0;
pos-=12;
break;
}
}
else{
curSearch = 0;
}
}
return pos;
}
extern "C" JNIEXPORT jstring JNICALL Java_com_valbrux_myapplication_MainActivity_getSystem(JNIEnv* env,jobject) {
char buff[30];
//system address
snprintf(buff, sizeof(buff), "%p", get_system_address());
dlclose(libc);
std::string system_string = buff;
return env->NewStringUTF(system_string.c_str());
}
extern "C" JNIEXPORT jstring JNICALL Java_com_valbrux_myapplication_MainActivity_getROPGadget(JNIEnv* env,jobject) {
char buff[30];
get_gadget_lib_base_address();
//gadget address
snprintf(buff, sizeof(buff), "%p",gadget_p+search_for_gadget_offset());
dlclose(lib);
std::string system_string = buff;
return env->NewStringUTF(system_string.c_str());
}
After trying to compile this it gives me this error:
47515.cpp:11:10: fatal error: jni.h: No such file or directory
11 | #include <jni.h>
| ^~~~~~~
compilation terminated.
Is there a way I can include the library by installing it like in other programming languages or do I have to include a line of code that declares where the file is that can't be found ?
I have the following string:ET8d1voUkzNcqud7M8W0WQcd3l2Ih1ZtiMxStPeubKg=
I want to apply SHA256 to it and obtain its hash.
Then I want to sign that hash with RSA and a private key.
This is the signature I'm suppose to be obtaining (without line breaks):
Zg8ftxJqRyoreMQtMKAZNrjHHcD/rOSkU29Ty8zV9aItwHBDO0WpzaaPrqnX6/vdayUAndDVvSBoOc9g0WBkFHQHtB/auLlq+ABeBP4jxy
d7ypPxBbJFecfZiBDaGCq4jAxUnhQ2HjT5R23DHOOcf/i50TrWXr2G5k8enqa754TUn1JiDOJJT2JkfnKmgM7EPpCjHV/eCJsOQFXNaxht
h7zHz5hZ4aOfy6EGGveOggzIjKSLeo0pIE8jBc1wy9V8vZkhPTpkeLguCxnwvpMIV1X7zF3m5OoM0PbC5yXgPUYPrz0JNSlvCKR9q5CsFm
rnit5vBfi5el1ZmevP2MgyEA==
This is the signature I get:
AR1X19H5wyb9IEi9WHrhatkR1jtTc7TovX23tdx8yID5CEWz+DF5kBNCXZxttJ8v
ctsbOL0rrQ0b4Gqa2ld00+nfzZJNg1osWwKb+sj6yNLy1XLqxFvfn1wrZ9Y8yOwS
oqJ0tTCpYbbbMo1mSVO4YuD18GbZJEDBUhBYY5D8H0MoHCSWLXsAjThAImyxw4ch
Hr2d1Sli4n6OA+CckGOQ15uLk6JiO6rNzNWfbbSb8a9trJ7bAdVPiKoln1X9tnWF
s3HK6fnfro9jlRQQ/Z0bCpF+FQrWrLouvLk+mjuTeiC+86HeeqzqlReAtpqtcO5/
9lWmrxXV2qZIqfuPYMovcA==
The code I'm using:
#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>
#include <assert.h>
#include <string.h>
#include <cstring>
std::string privateKey = "-----BEGIN RSA PRIVATE KEY-----\n"\
"MIIEogIBAAKCAQEAjdKXiqYHzi++YmEb9X6qvqFWLCz1VEfxom2JhinPSJxxcuZW\n"\
"Bejk2I5yCL5pDnUaG2xpQlMTkV/7S7JfGGvYJumKO4R5zg0QSA7qdxiEhcwf/ekf\n"\
"SvzM2EDnLHDCKAQwEWsnJy78uxZTLzu/65VZ7EgEcWUTvCs/GZJLI9s6XmKY2SMm\n"\
"v9+vfqBqkJNXE0ZB6OfSbyeE325P94iMn+B/yJ4vZwXvXGFqNDJyqG+ww7f77HYu\n"\
"bQPJjLQPedy2qTcgmSAwkUEJVBjYA6mPf/BeZlL1YJHHM7CIBnb3/bzED0n944wo\n"\
"io+4+rnMZdfhcCVpm74DZomlEf9KuJtq5u/JRQIDAQABAoIBAG2AzvWE4L346z02\n"\
"0cmptdhe5hRR2lLrAc1yWh83JQ9hi881vfHuMtRql+3cZ218SV4nRNarIo6612NJ\n"\
"JFfM3SaeZ9cwoIPSXmHk8nBmg9xzEbiRSVIzA09uPZB4t9EB+sNYQvDkPMuPn0b3\n"\
"EWaq+LWRnayYaLZ/hccOx+m1mcnJnIs27+EPnufrUKVniCguburQoU3VEXSFCzBk\n"\
"23rhSu20vUOikLuuU4gcvWfnfUoOwdhb2iBhjgMbsjTTmg3+GQuPtblCSTKjk11F\n"\
"YX2MJHEDFfwVzSurmbqAZC9rjr7PbflC8GMmPfa1LCb7IG5s9AIM4v9Fea0SyZP+\n"\
"/pM9mzkCgYEAyjLPU7ieqly9+mgeb2fmWh7pYgO49KuFIqqHnP+LaXXYK/TvCJ8X\n"\
"zJ3PxBgwVMOT94nXSDNjzNLzp0hl8OWWBH0tN0fiq1OEyySM3Mlji6o8KpGcU1k4\n"\
"jFkXMK1rVQcW8ckLmzMrQF3SphQi4UiEpLX1Zba4YQ4fNHK8NHHHaEMCgYEAs48m\n"\
"Oe4iEZcVDnag+Mp0Zjgu4mYJeeeGtVUZFCJOeyLDsQVmnt5mJIgGwrxg4o3qljut\n"\
"aAUXzf8aYZ0fURAsLcwnQg03THFKeIt94Rw/72n2UWT+AZTU3GQtuwf+osZHUfS3\n"\
"XTLaQE+A1JBC4XLJ99j/95sxt6xZy5YyfhfY09cCgYAbqyhDxJexqE823NiNViJn\n"\
"YqN9DhVZJb9qJvu3uCBTphSWr0WmYF7ZWR79LnIupzSwQuR6tM2LUbKVyYpplIEa\n"\
"zCZL0kJqP1uEkNPVwpkkm37wNEy3+xWJ3wcVWiW91OKG44P7EN1ySWRx5X+AZHQC\n"\
"NgQGjyJb5ZrPioPGiWtIEQKBgE/0B/N3o9ftTET6cccWbootDkNlaAbOH1+TGu2q\n"\
"MQQHgNfMLdvD7/uITmpb81AuHSz0Ocy9p9HkK90XV6CC8QkbhMeWlu8E60It6slY\n"\
"COgUaMfpjmkp2nagbPSBJNNaMtu9egCX6jMEs7ry2bUFpgUkrSWWB1df+UP8B1O6\n"\
"TqRVAoGAVQoCUPVm6C6h6V5dgPvsJMxJ8EjOCgwkXNucAHWcpBV3/LlxLiCGRuEL\n"\
"B+epYxqwKLpSQBhldasKmmKB0M6MFTwxXwxCmCi80+DBdP5A7GIK52ZGth63i22t\n"\
"FI8MeDIzA5HqAI24P7ltozoEYAB7GIdJQXq9oT/DRagTwQUzQ8E=\n"\
"-----END RSA PRIVATE KEY-----\n";
/*std::string privateKey ="-----BEGIN PRIVATE KEY-----\n"\
"MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCN0peKpgfOL75i\n"\
"YRv1fqq+oVYsLPVUR/GibYmGKc9InHFy5lYF6OTYjnIIvmkOdRobbGlCUxORX/tL\n"\
"sl8Ya9gm6Yo7hHnODRBIDup3GISFzB/96R9K/MzYQOcscMIoBDARaycnLvy7FlMv\n"\
"O7/rlVnsSARxZRO8Kz8Zkksj2zpeYpjZIya/369+oGqQk1cTRkHo59JvJ4Tfbk/3\n"\
"iIyf4H/Ini9nBe9cYWo0MnKob7DDt/vsdi5tA8mMtA953LapNyCZIDCRQQlUGNgD\n"\
"qY9/8F5mUvVgkcczsIgGdvf9vMQPSf3jjCiKj7j6ucxl1+FwJWmbvgNmiaUR/0q4\n"\
"m2rm78lFAgMBAAECggEAbYDO9YTgvfjrPTbRyam12F7mFFHaUusBzXJaHzclD2GL\n"\
"zzW98e4y1GqX7dxnbXxJXidE1qsijrrXY0kkV8zdJp5n1zCgg9JeYeTycGaD3HMR\n"\
"uJFJUjMDT249kHi30QH6w1hC8OQ8y4+fRvcRZqr4tZGdrJhotn+Fxw7H6bWZycmc\n"\
"izbv4Q+e5+tQpWeIKC5u6tChTdURdIULMGTbeuFK7bS9Q6KQu65TiBy9Z+d9Sg7B\n"\
"2FvaIGGOAxuyNNOaDf4ZC4+1uUJJMqOTXUVhfYwkcQMV/BXNK6uZuoBkL2uOvs9t\n"\
"+ULwYyY99rUsJvsgbmz0Agzi/0V5rRLJk/7+kz2bOQKBgQDKMs9TuJ6qXL36aB5v\n"\
"Z+ZaHuliA7j0q4Uiqoec/4tpddgr9O8InxfMnc/EGDBUw5P3iddIM2PM0vOnSGXw\n"\
"5ZYEfS03R+KrU4TLJIzcyWOLqjwqkZxTWTiMWRcwrWtVBxbxyQubMytAXdKmFCLh\n"\
"SISktfVltrhhDh80crw0ccdoQwKBgQCzjyY57iIRlxUOdqD4ynRmOC7iZgl554a1\n"\
"VRkUIk57IsOxBWae3mYkiAbCvGDijeqWO61oBRfN/xphnR9RECwtzCdCDTdMcUp4\n"\
"i33hHD/vafZRZP4BlNTcZC27B/6ixkdR9LddMtpAT4DUkELhcsn32P/3mzG3rFnL\n"\
"ljJ+F9jT1wKBgBurKEPEl7GoTzbc2I1WImdio30OFVklv2om+7e4IFOmFJavRaZg\n"\
"XtlZHv0uci6nNLBC5Hq0zYtRspXJimmUgRrMJkvSQmo/W4SQ09XCmSSbfvA0TLf7\n"\
"FYnfBxVaJb3U4objg/sQ3XJJZHHlf4BkdAI2BAaPIlvlms+Kg8aJa0gRAoGAT/QH\n"\
"83ej1+1MRPpxxxZvKi0OQ2VoBs4fX5Ma7aoxBAeA18wt28Pv+4hOalvzUC4dLPQ5\n"\
"zL2n0eQr3RdXoILxCRuEx5aW7wTrQi3qyVgI6BRox+mOaSnadqBs9IEk01oy2716\n"\
"AJfqMwSzuvLZtQWmBSStJZYHV1/5Q/wHU7pOpFUCgYBVCgJQ9WboLqHpXl2A++wk\n"\
"zEnwSM4KDCRc25wAdZykFXf8uXEuIIZG4QsH56ljGrAoulJAGGV1qwqaYoHQzowV\n"\
"PDFfDEKYKLzT4MF0/kDsYgrnZka2HreLba0Ujwx4MjMDkeoAjbg/uW2jOgRgAHsY\n"\
"h0lBer2hP8NFqBPBBTNDwQ==\n"\
"-----END PRIVATE KEY-----\n";
*/
std::string publicKey ="-----BEGIN PUBLIC KEY-----\n"\
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjdKXiqYHzi++YmEb9X6q\n"\
"vqFWLCz1VEfxom2JhinPSJxxcuZWBejk2I5yCL5pDnUaG2xpQlMTkV/7S7JfGGvY\n"\
"JumKO4R5zg0QSA7qdxiEhcwf/ekfSvzM2EDnLHDCKAQwEWsnJy78uxZTLzu/65VZ\n"\
"7EgEcWUTvCs/GZJLI9s6XmKY2SMmv9+vfqBqkJNXE0ZB6OfSbyeE325P94iMn+B/\n"\
"yJ4vZwXvXGFqNDJyqG+ww7f77HYubQPJjLQPedy2qTcgmSAwkUEJVBjYA6mPf/Be\n"\
"ZlL1YJHHM7CIBnb3/bzED0n944woio+4+rnMZdfhcCVpm74DZomlEf9KuJtq5u/J\n"\
"RQIDAQAB\n"\
"-----END PUBLIC KEY-----\n";
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);
}
unsigned char * strToHex(std::string plainText){
unsigned char * hexArray;
hexArray = (unsigned char*)malloc(plainText.length());
for(int i = 0; i < plainText.size();i++){
hexArray[i] = std::strtol(&plainText[i],NULL,64);
}
return hexArray;
}
char* signMessage(std::string privateKey, std::string plainText) {
RSA* privateRSA = createPrivateRSA(privateKey);
unsigned char* encMessage;
char* base64Text;
size_t encMessageLength;
RSASign(privateRSA, (unsigned char*) plainText.data(), plainText.length(), &encMessage, &encMessageLength);
Base64Encode(encMessage, encMessageLength, &base64Text);
free(encMessage);
return base64Text;
}
bool verifySignature(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;
}
int main() {
std::string plainText = "ET8d1voUkzNcqud7M8W0WQcd3l2Ih1ZtiMxStPeubKg=";
char* signature = signMessage(privateKey, plainText);
bool authentic = verifySignature(publicKey, "ET8d1voUkzNcqud7M8W0WQcd3l2Ih1ZtiMxStPeubKg=", signature);
if ( authentic ) {
std::cout << "Authentic" << std::endl;
std::cout << signature << std::endl;
} else {
std::cout << "Not Authentic" << std::endl;
}
}
What I'm actually trying to do is to 'translate' a C# code used by a third-party, I REQUIRE to do the same operations, I tried looking for the docs of the libreries used here but I couldn't find much, the code I'm trying to replicate is the following:
using System;
using System.Security.Cryptography;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
namespace KeyPairLoad
{
class Program
{
static void Main(string[] args)
{
string cadena = ComputeSha256Hash("ET8d1voUkzNcqud7M8W0WQcd3l2Ih1ZtiMxStPeubKg=");
string pathPrivateKey = #"C:\Users\xxx\Downloads\Fieles de pruebas\FOO1\some.key";
string password = "12345678a";
byte[] privBytes = System.IO.File.ReadAllBytes(pathPrivateKey);
AsymmetricKeyParameter llavePrivada = PrivateKeyFactory.DecryptKey(password.ToCharArray(), privBytes);
var rsaPriv = DotNetUtilities.ToRSA(llavePrivada as RsaPrivateCrtKeyParameters);
var csp = new CspParameters();
csp.KeyContainerName = "KeyContainer";
var rsaPrivate = new RSACryptoServiceProvider(csp);
string fin = Convert.ToBase64String(rsaPrivate.SignHash(Convert.FromBase64String(cadena), "SHA256"));
}
static string ComputeSha256Hash(string rawData)
{
using (SHA256 sha256Hash = SHA256.Create())
{
byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData));
return Convert.ToBase64String(bytes);
}
}
}
}
This third-party gave me the signature I'm supposed to be obtaining. I've tried many things but nothing works, I get different signatures but not the one I'm looking for.
Am I missing something in my translation? Am I doing something wrong?
Thanks for your patience and time. Let me know if u require more info.
Regards!
This code gets the desired signature:
Zg8ftxJqRyoreMQtMKAZNrjHHcD/rOSkU29Ty8zV9aItwHBDO0WpzaaPrqnX6/vdayUAndDVvSBoOc9g0WBkFHQHtB/auLlq+ABeBP4jxy
d7ypPxBbJFecfZiBDaGCq4jAxUnhQ2HjT5R23DHOOcf/i50TrWXr2G5k8enqa754TUn1JiDOJJT2JkfnKmgM7EPpCjHV/eCJsOQFXNaxht
h7zHz5hZ4aOfy6EGGveOggzIjKSLeo0pIE8jBc1wy9V8vZkhPTpkeLguCxnwvpMIV1X7zF3m5OoM0PbC5yXgPUYPrz0JNSlvCKR9q5CsFm
rnit5vBfi5el1ZmevP2MgyEA==
that I originally stated. It writes it in a file called result.dat which I have to encode in base 64 resulting int he above signature.
#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>
#include <assert.h>
#include <string>
#include <cstring>
#include <memory>
#include <vector>
#include <fstream>
#include "base64.h"
std::string privateKey = "-----BEGIN RSA PRIVATE KEY-----\n"
"MIIEogIBAAKCAQEAjdKXiqYHzi++YmEb9X6qvqFWLCz1VEfxom2JhinPSJxxcuZW\n"
"Bejk2I5yCL5pDnUaG2xpQlMTkV/7S7JfGGvYJumKO4R5zg0QSA7qdxiEhcwf/ekf\n"
"SvzM2EDnLHDCKAQwEWsnJy78uxZTLzu/65VZ7EgEcWUTvCs/GZJLI9s6XmKY2SMm\n"
"v9+vfqBqkJNXE0ZB6OfSbyeE325P94iMn+B/yJ4vZwXvXGFqNDJyqG+ww7f77HYu\n"
"bQPJjLQPedy2qTcgmSAwkUEJVBjYA6mPf/BeZlL1YJHHM7CIBnb3/bzED0n944wo\n"
"io+4+rnMZdfhcCVpm74DZomlEf9KuJtq5u/JRQIDAQABAoIBAG2AzvWE4L346z02\n"
"0cmptdhe5hRR2lLrAc1yWh83JQ9hi881vfHuMtRql+3cZ218SV4nRNarIo6612NJ\n"
"JFfM3SaeZ9cwoIPSXmHk8nBmg9xzEbiRSVIzA09uPZB4t9EB+sNYQvDkPMuPn0b3\n"
"EWaq+LWRnayYaLZ/hccOx+m1mcnJnIs27+EPnufrUKVniCguburQoU3VEXSFCzBk\n"
"23rhSu20vUOikLuuU4gcvWfnfUoOwdhb2iBhjgMbsjTTmg3+GQuPtblCSTKjk11F\n"
"YX2MJHEDFfwVzSurmbqAZC9rjr7PbflC8GMmPfa1LCb7IG5s9AIM4v9Fea0SyZP+\n"
"/pM9mzkCgYEAyjLPU7ieqly9+mgeb2fmWh7pYgO49KuFIqqHnP+LaXXYK/TvCJ8X\n"
"zJ3PxBgwVMOT94nXSDNjzNLzp0hl8OWWBH0tN0fiq1OEyySM3Mlji6o8KpGcU1k4\n"
"jFkXMK1rVQcW8ckLmzMrQF3SphQi4UiEpLX1Zba4YQ4fNHK8NHHHaEMCgYEAs48m\n"
"Oe4iEZcVDnag+Mp0Zjgu4mYJeeeGtVUZFCJOeyLDsQVmnt5mJIgGwrxg4o3qljut\n"
"aAUXzf8aYZ0fURAsLcwnQg03THFKeIt94Rw/72n2UWT+AZTU3GQtuwf+osZHUfS3\n"
"XTLaQE+A1JBC4XLJ99j/95sxt6xZy5YyfhfY09cCgYAbqyhDxJexqE823NiNViJn\n"
"YqN9DhVZJb9qJvu3uCBTphSWr0WmYF7ZWR79LnIupzSwQuR6tM2LUbKVyYpplIEa\n"
"zCZL0kJqP1uEkNPVwpkkm37wNEy3+xWJ3wcVWiW91OKG44P7EN1ySWRx5X+AZHQC\n"
"NgQGjyJb5ZrPioPGiWtIEQKBgE/0B/N3o9ftTET6cccWbootDkNlaAbOH1+TGu2q\n"
"MQQHgNfMLdvD7/uITmpb81AuHSz0Ocy9p9HkK90XV6CC8QkbhMeWlu8E60It6slY\n"
"COgUaMfpjmkp2nagbPSBJNNaMtu9egCX6jMEs7ry2bUFpgUkrSWWB1df+UP8B1O6\n"
"TqRVAoGAVQoCUPVm6C6h6V5dgPvsJMxJ8EjOCgwkXNucAHWcpBV3/LlxLiCGRuEL\n"
"B+epYxqwKLpSQBhldasKmmKB0M6MFTwxXwxCmCi80+DBdP5A7GIK52ZGth63i22t\n"
"FI8MeDIzA5HqAI24P7ltozoEYAB7GIdJQXq9oT/DRagTwQUzQ8E=\n"
"-----END RSA PRIVATE KEY-----\n";
// std::string privateKey ="-----BEGIN PRIVATE KEY-----\n"\
// "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCN0peKpgfOL75i\n"\
// "YRv1fqq+oVYsLPVUR/GibYmGKc9InHFy5lYF6OTYjnIIvmkOdRobbGlCUxORX/tL\n"\
// "sl8Ya9gm6Yo7hHnODRBIDup3GISFzB/96R9K/MzYQOcscMIoBDARaycnLvy7FlMv\n"\
// "O7/rlVnsSARxZRO8Kz8Zkksj2zpeYpjZIya/369+oGqQk1cTRkHo59JvJ4Tfbk/3\n"\
// "iIyf4H/Ini9nBe9cYWo0MnKob7DDt/vsdi5tA8mMtA953LapNyCZIDCRQQlUGNgD\n"\
// "qY9/8F5mUvVgkcczsIgGdvf9vMQPSf3jjCiKj7j6ucxl1+FwJWmbvgNmiaUR/0q4\n"\
// "m2rm78lFAgMBAAECggEAbYDO9YTgvfjrPTbRyam12F7mFFHaUusBzXJaHzclD2GL\n"\
// "zzW98e4y1GqX7dxnbXxJXidE1qsijrrXY0kkV8zdJp5n1zCgg9JeYeTycGaD3HMR\n"\
// "uJFJUjMDT249kHi30QH6w1hC8OQ8y4+fRvcRZqr4tZGdrJhotn+Fxw7H6bWZycmc\n"\
// "izbv4Q+e5+tQpWeIKC5u6tChTdURdIULMGTbeuFK7bS9Q6KQu65TiBy9Z+d9Sg7B\n"\
// "2FvaIGGOAxuyNNOaDf4ZC4+1uUJJMqOTXUVhfYwkcQMV/BXNK6uZuoBkL2uOvs9t\n"\
// "+ULwYyY99rUsJvsgbmz0Agzi/0V5rRLJk/7+kz2bOQKBgQDKMs9TuJ6qXL36aB5v\n"\
// "Z+ZaHuliA7j0q4Uiqoec/4tpddgr9O8InxfMnc/EGDBUw5P3iddIM2PM0vOnSGXw\n"\
// "5ZYEfS03R+KrU4TLJIzcyWOLqjwqkZxTWTiMWRcwrWtVBxbxyQubMytAXdKmFCLh\n"\
// "SISktfVltrhhDh80crw0ccdoQwKBgQCzjyY57iIRlxUOdqD4ynRmOC7iZgl554a1\n"\
// "VRkUIk57IsOxBWae3mYkiAbCvGDijeqWO61oBRfN/xphnR9RECwtzCdCDTdMcUp4\n"\
// "i33hHD/vafZRZP4BlNTcZC27B/6ixkdR9LddMtpAT4DUkELhcsn32P/3mzG3rFnL\n"\
// "ljJ+F9jT1wKBgBurKEPEl7GoTzbc2I1WImdio30OFVklv2om+7e4IFOmFJavRaZg\n"\
// "XtlZHv0uci6nNLBC5Hq0zYtRspXJimmUgRrMJkvSQmo/W4SQ09XCmSSbfvA0TLf7\n"\
// "FYnfBxVaJb3U4objg/sQ3XJJZHHlf4BkdAI2BAaPIlvlms+Kg8aJa0gRAoGAT/QH\n"\
// "83ej1+1MRPpxxxZvKi0OQ2VoBs4fX5Ma7aoxBAeA18wt28Pv+4hOalvzUC4dLPQ5\n"\
// "zL2n0eQr3RdXoILxCRuEx5aW7wTrQi3qyVgI6BRox+mOaSnadqBs9IEk01oy2716\n"\
// "AJfqMwSzuvLZtQWmBSStJZYHV1/5Q/wHU7pOpFUCgYBVCgJQ9WboLqHpXl2A++wk\n"\
// "zEnwSM4KDCRc25wAdZykFXf8uXEuIIZG4QsH56ljGrAoulJAGGV1qwqaYoHQzowV\n"\
// "PDFfDEKYKLzT4MF0/kDsYgrnZka2HreLba0Ujwx4MjMDkeoAjbg/uW2jOgRgAHsY\n"\
// "h0lBer2hP8NFqBPBBTNDwQ==\n"\
// "-----END PRIVATE KEY-----\n";
std::string publicKey ="-----BEGIN PUBLIC KEY-----\n"\
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjdKXiqYHzi++YmEb9X6q\n"\
"vqFWLCz1VEfxom2JhinPSJxxcuZWBejk2I5yCL5pDnUaG2xpQlMTkV/7S7JfGGvY\n"\
"JumKO4R5zg0QSA7qdxiEhcwf/ekfSvzM2EDnLHDCKAQwEWsnJy78uxZTLzu/65VZ\n"\
"7EgEcWUTvCs/GZJLI9s6XmKY2SMmv9+vfqBqkJNXE0ZB6OfSbyeE325P94iMn+B/\n"\
"yJ4vZwXvXGFqNDJyqG+ww7f77HYubQPJjLQPedy2qTcgmSAwkUEJVBjYA6mPf/Be\n"\
"ZlL1YJHHM7CIBnb3/bzED0n944woio+4+rnMZdfhcCVpm74DZomlEf9KuJtq5u/J\n"\
"RQIDAQAB\n"\
"-----END PUBLIC KEY-----\n";
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;
}
void sellar(std::string hashclear, std::string privateKey_string){
EVP_PKEY_CTX *ctx;
/* md is a SHA-256 digest in this example. */
unsigned char *sig;
size_t siglen;
unsigned char clear_message[hashclear.length()];
strcpy((char*) clear_message,hashclear.c_str());
size_t mdlen;
// //1. Decodificar hashclear. || base64 -d data.dat > b64.dat -> Me debe dar una cadena de 32 bytes.
unsigned char * md = base64_decode(clear_message, strlen((char*) clear_message), &mdlen);
std::cout << "MD is " << mdlen << " bytes long.\n";
// //2. Cargar llave privada.
RSA* privateRSA = createPrivateRSA(privateKey);
EVP_PKEY* signing_key = EVP_PKEY_new();
EVP_PKEY_assign_RSA(signing_key, privateRSA);
ctx = EVP_PKEY_CTX_new(signing_key, NULL /* no engine */);
if(!ctx) {
std::cout << "Error CTX_new" << std::endl;
return;
}
if (EVP_PKEY_sign_init(ctx) <= 0){
std::cout << "Error sign_init\n";
return;
}
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0){
std::cout << "Error set_rsa_padding\n";
return;
}
if (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0){
std::cout << "Error set_signature_md\n";
return;
}
/* Determine buffer length */
if (EVP_PKEY_sign(ctx, NULL, &siglen, md, mdlen) <= 0){
std::cout << "Error PKEY_sign\n";
return;
}
sig = (unsigned char*)OPENSSL_malloc(siglen);
if (!sig){
std::cout << "Error malloc";
return;
}
if (EVP_PKEY_sign(ctx, sig, &siglen, md, mdlen) <= 0){
std::cout << "Error sign";
return;
}
std::cout << siglen << " bytes written in buffer sig\n";
/* Signature is siglen bytes written to buffer sig */
size_t cadena_sellada_len;
unsigned char * cadena_sellada = base64_encode(sig, siglen, &cadena_sellada_len);
std::ofstream myfile ("result_final.dat");
if (myfile.is_open())
{
for(int count = 0; count < cadena_sellada_len; count ++){
myfile << cadena_sellada[count] ;
}
myfile.close();
}
else std::cout << "Unable to open file";
}
int main() {
std::string plainText = "ET8d1voUkzNcqud7M8W0WQcd3l2Ih1ZtiMxStPeubKg=\n";
// unsigned char src[plainText.length()];
// strcpy((char*) src,plainText.c_str());
// std::cout << "Src has " << strlen((char*)src) << " entries.\n";
// size_t out_len;
// unsigned char * bytes = base64_decode(src, strlen((char*)src), &out_len);
// std::cout << "bytes has " << out_len << " entries.\n";
// std::cout << bytes << std::endl;
// size_t re_out_len;
// unsigned char * re_encode = base64_encode(bytes, out_len,&re_out_len);
// std::cout << re_encode << "\n";
// std::ofstream myfile ("b64.dat");
// if (myfile.is_open())
// {
// for(int count = 0; count < out_len; count ++){
// myfile << bytes[count] ;
// }
// myfile.close();
// }
// else std::cout << "Unable to open file";
sellar(plainText, privateKey);
return 0;
//strcpy()
//std::cout << "Length : " << b64dat.length() << std::endl;
//char* signature = signMessage(privateKey, plainText);
//std::cout << signature << std::endl;
// bool authentic = verifySignature(publicKey, "ET8d1voUkzNcqud7M8W0WQcd3l2Ih1ZtiMxStPeubKg=", signature);
// if ( authentic ) {
// std::cout << "Authentic" << std::endl;
// } else {
// std::cout << "Not Authentic" << std::endl;
// }
}
Thank you all for your time and patience.
I'm not going to read all the code to try and figure out what it is you're trying to do and thus where your mistake(s) are. Instead, I'll just examine what you've provided and you can go from there.
Clearly, both the signatures you've provided are valid signatures. This can be seen by manually going through the verification steps, stopping just after modular exponentiation using the encrypt exponent. The result is as expected for pkcs1 EMSA-PKCS1-v1_5 encoding. And just as clearly, we can see that different SHA-256 hashes are involved. In other words, the signatures are different because the data they are signing is different.
For the signature that starts with AR1X19... the data being signed is the UTF-8 encoding of the string ET8d1voUkzNcqud7M8W0WQcd3l2Ih1ZtiMxStPeubKg=. Note that this string a pretty obviously the base64-encoding of random looking 32 bytes. In this context one might guess that those 32-bytes are actually the sha256 hash of some other unknown quantity. And sure, enough the signature that starts with Zg8ftxJqR... is over data whose sha256 hash is the base64-decoding of ET8d....
So it looks like the first signature is correct, and the second one is the result of base64-encoding the sha256 hash during in the middle of the signing operation.
there is code
#include <stdio.h>
#include <string.h>
#include <openssl/hmac.h>
int main() {
const char key[] = "012345678";
char data[] = "hello world";
unsigned char* result;
unsigned int len = 20;
result = (unsigned char*)malloc(sizeof(char) * len);
HMAC_CTX ctx;
HMAC_CTX_init(&ctx);
HMAC_Init_ex(&ctx, key, strlen(key), EVP_sha1(), NULL);
HMAC_Update(&ctx, (unsigned char*)&data, strlen(data));
HMAC_Final(&ctx, result, &len);
HMAC_CTX_cleanup(&ctx);
printf("HMAC digest: ");
for (int i = 0; i != len; i++)
printf("%02x", (unsigned int)result[i]);
printf("\n");
free(result);
}
output HMAC digest: e19e220122b37b708bfb95aca2577905acabf0c0
I can not update this code for openssl 1.1.0.
The new version changed the syntax hmac.
#include <iostream>
#include <string.h>
#include <openssl/hmac.h>
using namespace std;
int main() {
const char key[] = "012345678";
char data[] = "hello world";
int datalen = strlen(data);
int keylen = strlen(key);
unsigned char* result;
unsigned int len = 20;
result = (unsigned char*)malloc(sizeof(char) * len);
cout << datalen << endl;
cout << keylen << endl;
cout << len << endl;
HMAC_CTX *HMAC_CTX_new();
int HMAC_CTX_reset(HMAC_CTX *ctx);
int HMAC_Init_ex(HMAC_CTX *ctx, const char key, int keylen, const EVP_MD EVP_sha1());
int HMAC_Update(HMAC_CTX * ctx, char &data, int datalen);
int HMAC_Final(HMAC_CTX * ctx, char result, int &len);
int HMAC_CTX_cleanup(HMAC_CTX * ctx);
printf("HMAC digest: ");
for (int i = 0; i != len; i++)
printf("%02x", (unsigned int)result[i]);
printf("\n");
free(result);
return 0;
}
output HMAC digest: 0000000000000000000000000000000000000000
I will be glad of any help
I'm trying generate a rsa public key from a modulus type char[], and I now the exponent is RSA_F4(65537);
But when I'm trying generate my public key using this values for "n" and "e", the RSA_public_encrypt, return -1;
Thanks!
My code:
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <crypt.h>
#include <iostream>
#include <stdlib.h>
#include <openssl/rsa.h>
#include <openssl/aes.h>
#include <openssl/opensslconf.h>
#include <openssl/engine.h>
#include <openssl/pem.h>
#include <openssl/rc4.h>
using namespace std;
int main(void)
{
//modulus in format char hex;
char key[] = "C0E7FC730EB5CF85B040EC25DAEF288912641889AD651B3707CFED9FC5A1D3F6C40062AD46E3B3C3E21D4E71CC4800C80226D453242AEB2F86D748B41DDF35FD";
char palavra[] = "teste";
char crip[512];
int ret;
RSA * pubkey = RSA_new();
BIGNUM * modul = BN_new();
BIGNUM * expon = BN_new();
BN_hex2bn(&modul, (const char *) key);
BN_hex2bn(&expon, "010001");
cout << "N KEY: " << BN_bn2hex(modul) << endl;
cout << "E KEY: " << BN_bn2hex(expon) << endl;
pubkey->n = modul;
pubkey->e = expon;
cout << "N PUB KEY: " << BN_bn2hex(pubkey->n) << endl;
cout << "E PUB KEY: " << BN_bn2hex(pubkey->e) << endl;
if (RSA_public_encrypt(strlen((const char *) palavra), (const unsigned char *) palavra, (unsigned char *) crip, pubkey, RSA_PKCS1_PADDING ))
{
printf("ERRO encrypt\n");
}
else
{
printf("SUC encrypt\n");
}
return 0;
}
You probably want something that looks more like:
RSA *pubkey = RSA_new();
int len = BN_hex2bn(&pubkey->n, (const char *)p);
if (len == 0 || p[len])
fprintf(stderr, "'%s' does not appear to be a valid modulus\n", p);
BN_hex2bn(&pubkey->e, "010001");
edit
Your code works fine, except for the error check. RSA_public_encrypt returns the size of the ciphertext on success, not 0, so to make the code above work, add a <= 0 test to if line:
if (RSA_public_encrypt(....) <= 0)
Here is some C code, that does the trick:
#include <string.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/pem.h>
// cheating, .. ignoring deprecation warnings
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
unsigned char *base64_decode(const char* base64data, int* len) {
BIO *b64, *bmem;
size_t length = strlen(base64data);
unsigned char *buffer = (unsigned char *)malloc(length);
b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
bmem = BIO_new_mem_buf((void*)base64data, length);
bmem = BIO_push(b64, bmem);
*len = BIO_read(bmem, buffer, length);
BIO_free_all(bmem);
return buffer;
}
BIGNUM* bignum_base64_decode(const char* base64bignum) {
BIGNUM* bn = NULL;
int len;
unsigned char* data = base64_decode(base64bignum, &len);
if (len) {
bn = BN_bin2bn(data, len, NULL);
}
free(data);
return bn;
}
EVP_PKEY* RSA_fromBase64(const char* modulus_b64, const char* exp_b64) {
BIGNUM *n = bignum_base64_decode(modulus_b64);
BIGNUM *e = bignum_base64_decode(exp_b64);
if (!n) printf("Invalid encoding for modulus\n");
if (!e) printf("Invalid encoding for public exponent\n");
if (e && n) {
EVP_PKEY* pRsaKey = EVP_PKEY_new();
RSA* rsa = RSA_new();
rsa->e = e;
rsa->n = n;
EVP_PKEY_assign_RSA(pRsaKey, rsa);
return pRsaKey;
} else {
if (n) BN_free(n);
if (e) BN_free(e);
return NULL;
}
}
void assert_syntax(int argc, char** argv) {
if (argc != 4) {
fprintf(stderr, "Description: %s takes a RSA public key modulus and exponent in base64 encoding and produces a public key file in PEM format.\n", argv[0]);
fprintf(stderr, "syntax: %s <modulus_base64> <exp_base64> <output_file>\n", argv[0]);
exit(1);
}
}
int main(int argc, char** argv) {
assert_syntax(argc, argv);
const char* modulus = argv[1];
const char* exp = argv[2];
const char* filename = argv[3];
EVP_PKEY* pkey = RSA_fromBase64(modulus, exp);
if (pkey == NULL) {
fprintf(stderr, "an error occurred :(\n");
return 2;
} else {
printf("success decoded into RSA public key\n");
FILE* file = fopen(filename, "w");
PEM_write_PUBKEY(file, pkey);
fflush(file);
fclose(file);
printf("written to file: %s\n", filename);
}
return 0;
}
See this link for further info: http://www.techper.net/2012/06/01/converting-rsa-public-key-modulus-and-exponent-into-pem-file/