OpenAES/OpenSSL compatibility - c

I'm trying to use both OpenAES and OpenSSL in C, this way:
Application 1 encodes a password using OpenAES
Application 2 decodes the password using OpenSSL
The problem is that I can't decode it, actually I'm quite surprised as OpenAES generates a
different block each time when OpenSSL or any other AES implementation I've seen always generate
the same block.
Another difference I noticed is that the OpenAES generated block is 48 bytes, when OpenSSL generates 16.
This is how I encrypt the string (OpenAES):
pCtx = oaes_alloc();
if (pCtx == NULL)
return FALSE;
oRet = oaes_key_import(pCtx, sKey, szKey);
if (oRet != OAES_RET_SUCCESS)
{
return FALSE;
}
// Get the required buffer size
oRet = oaes_encrypt(pCtx, (const uint8_t*)csSource, szLen, NULL, pOutLen);
if (oRet != OAES_RET_SUCCESS)
{
oaes_free(&pCtx);
return FALSE;
}
*ppOut = (char*)calloc(*pOutLen, sizeof(char));
oRet = oaes_encrypt(pCtx, (const uint8_t*)csSource, szLen, (uint8_t*)*ppOut, pOutLen);
if (oRet != OAES_RET_SUCCESS)
{
oaes_free(&pCtx);
free(*ppOut);
return FALSE;
}
oaes_free(&pCtx);
And this is how I decrypt it (OpenSSL):
AES_KEY kDecrypt;
AES_set_decrypt_key(sKey, 128, &kDecrypt);
AES_decrypt(pEncoded, pDecoded, &kDecrypt);
sKey being the key generated with OpenAES
pEncoded the crypted block from OpenAES
pDecoded the output data.
I can't put my finger on the problem yet...
Is there a particular way to use OpenAES so the result can be decrypted by OpenSSL, or is it just not compatible?

OpenAES prefixes the encrypted data with a OpenAES specific header, followed by the iv and then the encrypted data (+ padding).
As the IV seems to be generated randomly by OpenAES that explains why the data differs with each encrypt.

Related

MBED TLS Symetric Key Wrap

I'm trying to use MBED TLS cryptography functions to unwrap a key which has been encrypted using AES-128 key wrapping using a symmetric key, which I have.
I'm new to encryption and my understanding is that key wrapping/unwrapping is different to encrypting/decrypting. Is this correct?
There are examples listed on this page but the aes examples are doing decryption rather than key unwrapping, and the wrap examples are using public keys rather than symmetrical keys.
Is there some reference or example for using MBED TLS to do key-unwrapping using AES-128 encryption?
I have tried simply using the decryption function and I do not get the correct data as a result. See below.
//Initialise AES context
mbedtls_aes_init( &aes_ctx );
//Set-up the context
mbedtls_aes_setkey_dec( &aes_ctx, AES_key, 128 );
//Process the encrypted data in blocks of 16 bytes
for(i = 0; i< encryptedDataLength; i+= 16)
{
mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_DECRYPT, pEncryptedData + i, pPlainValue + i);
}
//Free the context
mbedtls_aes_free( &aes_ctx );
Thanks!
I found a solution, using the nist_kw interface
//Initialise key-wrap context
mbedtls_nist_kw_init(&kw_ctx);
//Set up the context
mbedtls_nist_kw_setkey(&kw_ctx, MBEDTLS_CIPHER_ID_AES, AES_key, 128, 0);
//Process the encrypted data
mbedtls_nist_kw_unwrap(&kw_ctx, MBEDTLS_KW_MODE_KW,
pEncryptedData, encrypted_length,
pPlainValue, &decrypted_length,
encryptedDataLength);
//Free the context
mbedtls_nist_kw_free(&kw_ctx);
This decrypts the data correctly for me. Thanks for being my rubber ducky!

How to verify ECC Signature from wolfSSL with OpenSSL

I am new to Elliptic Curve Cryptography, openSSL and wolfSSL. My context is that I generate KeyPair from command line with openssl and import the private key to my code. Then I use wolfSSL to generate signature and output it.
I save the output in DER format and try to verify with openSSL, the verification fails.
If I Sign and Verify inside my code with wolfSSL, it verifies successfully and also it's successful if I sign and verify in command line with openSSL.
Is there an encoding issue, which I am not sure about?
Update Code
// ECC public key
const uint8_t pubKey[] ={Hex Format key};
// ECC Signature from wolfSSL
char* sigString = {Signature from wolfSSL returned as char};
/* TYPE CONVERTIONS*/
const uint8_t *der_bytes_copy;
const uint8_t *pub_bytes_copy;
der_bytes_copy = (const unsigned char*)sigString;
pub_bytes_copy = pubKey;
EC_KEY *ECpubkey;
size_t keySize = sizeof(pubKey);
int eccgrp;
eccgrp = OBJ_txt2nid("secp256r1");
ECpubkey = EC_KEY_new_by_curve_name(eccgrp);
o2i_ECPublicKey(&ECpubkey, &pub_bytes_copy, keySize);
ECDSA_SIG *signature;
signature = d2i_ECDSA_SIG(NULL, &der_bytes_copy, signedSize);
uint8_t digest[36];
int verified;
const char message[] = "Test for Authenticate Kernel with ECC";
SHA256_CTX ctx;
SHA256_Init(&ctx);
SHA256_Update(&ctx, (const uint8_t*)message,sizeof(message));
SHA256_Final(digest, &ctx);
verified = ECDSA_do_verify(digest, sizeof(digest), signature, ECpubkey);
The private key is used with wolfSSL to sign the message and then the public key with openssl to verify, but this stops abruptly.
In the past when working with openSSL and comparing sign values to wolfSSL I have found that OpenSSL does the following steps when signing:
Read in and decode the key
compute a hash
Signature Encode the hash
sign the encoded hash
Base64 Encode the signature
OpenSSL does not make this apparent or user-friendly so unfortunately it's something you have to discover as you have.
Please use the following steps in wolfSSL to achieve your desired output:
1 Create or import your ECC key
2 Compute the sha hash on the input as you did previously
3 Encode the hash with this API call: encodedSz = wc_EncodeSignature(encodedOutput, hashInput, SHA256_DIGEST_SIZE, SHA256h);
4 Sign the encoded hash
5 Now do the verify
Let us know if that works for you.

How to encrypt data using RSA, with SHA-256 as hash function and MGF1 as mask generating function?

I was doing some experiments with cryptography. Now I have the public key of receiver and i want to encrypt some data and pass to the receiver.
I want to use RSAES-OAEP algorithm. with SHA-256 as hash function and MGF1 as mask generation function.
I want do this using openssl. I found a function RSA_public_encrypt() with this function we can specify the padding. One of the padding option available was
RSA_PKCS1_OAEP_PADDING
EME-OAEP as defined in PKCS #1 v2.0 with SHA-1 , MGF1 .
they are using sha-1.
I want to reconfigure the function to use SHA256 as hash function ans MGF1 as hash function. How can I do it ?
The following excerpt allows using OAEP with SHA256 for both the MGF and hash function. Tested with OpenSSL 1.0.2L
int flags = CMS_BINARY | CMS_PARTIAL | CMS_KEY_PARAM;
cms = CMS_encrypt(NULL, in, cipher, flags)
ri = CMS_add1_recipient_cert(cms, cert, flags);
pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_OAEP_PADDING);
EVP_PKEY_CTX_set_rsa_oaep_md(pctx, EVP_sha256());
EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, EVP_sha256());
With a newer OpenSSL 1.0.2+ you can do it using the command:
openssl pkeyutl -in PlaintextKeyMaterial.bin -out EncryptedKeyMaterial.bin -inkey PublicKey.bin -keyform DER -pubin -encrypt -pkeyopt rsa_padding_mode:oaep
-pkeyopt rsa_oaep_md:sha256
This is taken from AWS KMS doc here: https://aws.amazon.com/es/premiumsupport/knowledge-center/invalidciphertext-kms/
OpenSSL uses definitions from PKCS #1 v2.0 and so the default for EME-OAEP is SHA-1 and MGF1. If you need to use SHA-256, you'll need to do the encoding yourself. This isn't terribly difficult however, see PKCS #1 v2.2 PDF Page 18 for details.
In the latest version of Openssl(1.0.2k) the signature of the API is changed which gives us more flexibility. Please find the details below,
int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
const unsigned char *from, int flen,
int num, const unsigned char *param,
int plen, const EVP_MD *md,
const EVP_MD *mgf1md)
You can pass the EVP_MD structure to invoke the SHA-256 hashing using this.
The PKCS#1 doc referred to above is more mathematical and doesn't give coding examples, and the CMS answer is for ASN.1/SMIME data and not really relevant for the question asked, which was how to replace RSA_public_encrypt() which deals with simple binary/text data. I spent a whole day with trial and error and online searching to find the answer to this, and eventually got the answer (which was to use OpenSSL's EVP API) from looking at the source code of "openssl pkeyutl" - once I discovered that it was not difficult.
In my case I was looking to replace RSA_private_decrypt() for decryption using the private key and this is how to do that - it should be pretty easy to put to together an RSA_public_encrypt() replacement based on this:
EVP_PKEY *privKey = NULL;
BIO *bioPrivKey;
int outLen = 0, ret;
if ((bioPrivKey = BIO_new(BIO_s_mem())))
{
// Read the private key from the RSA context into the memory BIO,
// then convert it to an EVP_PKEY:
if ((ret = PEM_write_bio_RSAPrivateKey(bioPrivKey, rsaCtxt, NULL, NULL, 0, NULL, NULL)) &&
(privKey = PEM_read_bio_PrivateKey(bioPrivKey, NULL, NULL, NULL)))
{
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(privKey, NULL);
EVP_PKEY_free(privKey);
if (ctx)
{
if (EVP_PKEY_decrypt_init(ctx) > 0)
{
EVP_PKEY_CTX_ctrl_str(ctx, "rsa_padding_mode", "oaep");
EVP_PKEY_CTX_ctrl_str(ctx, "rsa_oaep_md", "sha256");
EVP_PKEY_CTX_ctrl_str(ctx, "rsa_mgf1_md", "sha256");
outLen = dataOutMax;
ret = EVP_PKEY_decrypt(ctx, dataOut, &outLen, dataIn, inDataLen);
if (ret > 0 && outLen > 0 && outLen <= dataOutMax)
{
// Success :-)
}
}
EVP_PKEY_CTX_free(ctx);
}
}
BIO_free_all(bioPrivKey);
}
You can add error handling for the failure cases using ERR_get_error().

Erratic openssl/rsa behaviour: RSA_EAY_PRIVATE_DECRYPT:padding check failed

I have written a program that runs permanently using <openssl/rsa> C library.
It basically decrypts a password given in argument. The problem is that sometimes it works flawlessly, and some other times it fails (with the same pubkey/privkey/password, returning this error:
message: error:04065072:rsa routines:RSA_EAY_PRIVATE_DECRYPT:padding check failed
Has anyone ever experienced that?
Why this kind of error is returned, generally?
Some more details
It retrieves the private key at the initialisation of the program with the following:
#define PRIVFILE "<correct-path>/privkey.pem"
EVP_PKEY *privKey;
int size_key;
FILE *fp = fopen(PRIVFILE, "r");
if (!fp)
{
<logs>
return -1;
}
PEM_read_PrivateKey(fp, &privKey, 0, NULL);
fclose (fp);
if (privKey == NULL)
{
ERR_print_errors_fp (stderr);
return -1;
}
size_key = EVP_PKEY_size(privKey);
Later, during a listening loop, a method call the private decryption algorithm
int len_enc = size_key;
unsigned char* enc_pw;
unsigned char* dec_pw;
int len_dec = 8;
char* err = malloc(130);
enc_pw = malloc(len_enc);
dec_pw = malloc(len_dec);
memset(enc_pw, 0, len_enc);
memset(dec_pw, 0, len_dec);
memcpy(enc_pw, value, len_enc); //value being the raw ciphered data to decrypt
ERR_load_crypto_strings();
if (RSA_private_decrypt(len_enc, enc_pw, dec_pw, privKey->pkey.rsa,RSA_PKCS1_OAEP_PADDING) == -1)
{
ERR_error_string(ERR_get_error(), err);
radlog(L_ERR, "message: %s", err);
}
free(enc_pw);
free(dec_pw);
free(err);
I have done encryption on the data with perl using Crypt::OpenSSL::RSA:
my $rsa_pub = Crypt::OpenSSL::RSA->new_public_key( $key_string);
my $ciphertext = $rsa_pub->encrypt( $plaintext);
There is some base64 encoding/decoding that i didn't mention to make it a little bit shorter. The problem does not come from that.
private key and public key are generated with openssl genrsa:
openssl genrsa -out privkey.pem 1024 and openssl rsa -in privkey.pem -pubout > pubkey.pub
It seems to work for some time, but occasionally (during a peak of request, if that matters) i get these errors for ciphered data that seemed valid before:
message: error:04065072:rsa routines:RSA_EAY_PRIVATE_DECRYPT:padding check failed
Is it a multi threaded application?
I was getting the same problem yesterday and, in my case, it was related to more than one thread using the key (one for decript and many others for encript). The problem was solved protecting the key with a mutex semaphore.
The service is up and stable since yesterday.

Openssl/libcrypto AES 128 encoding using the KEY

I am encrypting a certain string using AES-128-ECB and then save the result in a file e.g test.enc
Here is my method that does the encryption:
int do_crypt(char *outfile) {
unsigned char outbuf[1024];
int outlen, tmplen;
unsigned char key[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
char intext[] = "Some Text";
EVP_CIPHER_CTX ctx;
FILE *out;
EVP_CIPHER_CTX_init(&ctx);
EVP_EncryptInit_ex(&ctx, EVP_aes_128_ecb(), NULL, key, NULL);
if(!EVP_EncryptUpdate(&ctx, outbuf, &outlen, intext, strlen(intext))) {
/* Error */
return 0;
}
/* Buffer passed to EVP_EncryptFinal() must be after data just
* encrypted to avoid overwriting it.
*/
if(!EVP_EncryptFinal_ex(&ctx, outbuf + outlen, &tmplen))
{
/* Error */
return 0;
}
outlen += tmplen;
EVP_CIPHER_CTX_cleanup(&ctx);
/* Need binary mode for fopen because encrypted data is
* binary data. Also cannot use strlen() on it because
* it wont be null terminated and may contain embedded
* nulls.
*/
out = fopen(outfile, "wb");
fwrite(outbuf, 1, outlen, out);
fclose(out);
return 1;
}
As you can see the key is the actual password and in order to decode the encrypted file following command line should be executed:
openssl aes-128-ecb -in test.enc -K 000102030405060708090A0B0C0D0E0F -d
"000102030405060708090A0B0C0D0E0F" is a password hex representation I use in the code above 0123456789191112131415. As I understand the password can be encrypted as well using MD5 algorithm.
The question is how to encrypt data using actual KEY derived from password and not the password itself using libcrypto?
Take a look at EVP_BytesToKey.
My comments in an old app tell me that BytesToKey is out of date and you should perhaps consider looking at PKCS5_v2_PBE_keyivgen or similar. But essentially, a highly simplified way of doing it is you derive your Key as a hash from your password and a suitable salt value:
EVP_DigestInit_ex(...)
EVP_DigestUpdate(...Password...)
EVP_DigestUpdate(...Salt...)
EVP_DigestFinal_ex(...)
then you use the newly generated Key to derive your IV by:
EVP_DigestInit_ex(...)
EVP_DigestUpdate(...Key...)
EVP_DigestUpdate(...Password...)
EVP_DigestUpdate(...Salt...)
EVP_DigestFinal_ex(...)
A browse of the OpenSSL source code is most useful for looking up stuff like this.
Disclaimer: I'm not a C programmer (the app in question was Delphi using OpenSSL DLLs) nor a security expert so take these suggestions as a starting point, read the proper docs and use proper functions where possible!!...

Resources