Various cross-platform encryption results using OpenSSL

I am working on a piece of cross-platform (Windows and Mac OS X) C code that is supposed to encrypt / decrypt drops using AES-256 with CBC and a block size of 128 bits. Among the various libraries and APIs, I chose OpenSSL.

This piece of code will then download blob using a multi-page PUT to the server, which then decrypts it using the same settings in the .NET crypto framework (Aes, CryptoStream, etc.).

The problem I am facing is that server decryption works fine when local encryption is performed on Windows, but it does not work when encryption is performed on Mac OS X - the server throws "Invalid padding and exception throwing."

I considered this from many points of view:

  • I confirmed the correctness of transportation - the byte array obtained by the server decryption method is exactly the same as from Mac OS X and Windows
  • The actual contents of the encrypted blob for the same key is different from Windows and Mac OS X. I tested it with a hard key and ran this patch on Windows and Mac OS X for the same blob
  • I am sure that the fix is ​​correct, as it will take care of OpenSSL and since the same code works for Windows. Nevertheless, I tried to implement an add-on scheme , as it is in the original Microsoft source for .NET , but still, you don’t want to
  • I confirmed that IV is the same for Windows and Mac OS X (I thought maybe there was a problem with some of the special characters, such as ETBs, which appear in IV but weren’t)
  • I tried LibreSSL and mbedtls without positive results. In mbedtls, I also had to implement an add-on because, as far as I know, the debugger is responsible for the user of the API.
  • I have been dealing with this problem for almost two weeks, and I begin to pull out my (once scanty) hair.

As a help system, I will send the client code C for encryption and the C # server code for decryption. Some small details on the server side will be omitted (they do not interfere with the crypto code).

Client:

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ void __setup_aes(EVP_CIPHER_CTX *ctx, const char *key, qvr_bool encrypt) { static const char *iv = ""; /* for security reasons, the actual IV is omitted... */ if (encrypt) EVP_EncryptInit(ctx, EVP_aes_256_cbc(), key, iv); else EVP_DecryptInit(ctx, EVP_aes_256_cbc(), key, iv); } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ void __encrypt(void *buf, size_t buflen, const char *key, unsigned char **outbuf, size_t *outlen) { EVP_CIPHER_CTX ctx; int blocklen = 0; int finallen = 0; int remainder = 0; __setup_aes(&ctx, key, QVR_TRUE); EVP_CIPHER *c = ctx.cipher; blocklen = EVP_CIPHER_CTX_block_size(&ctx); //*outbuf = (unsigned char *) malloc((buflen + blocklen - 1) / blocklen * blocklen); remainder = buflen % blocklen; *outlen = remainder == 0 ? buflen : buflen + blocklen - remainder; *outbuf = (unsigned char *) calloc(*outlen, sizeof(unsigned char)); EVP_EncryptUpdate(&ctx, *outbuf, outlen, buf, buflen); EVP_EncryptFinal_ex(&ctx, *outbuf + *outlen, &finallen); EVP_CIPHER_CTX_cleanup(&ctx); //*outlen += finallen; } 

Server:

 static Byte[] Decrypt(byte[] input, byte[] key, byte[] iv) { try { // Check arguments. if (input == null || input.Length <= 0) throw new ArgumentNullException("input"); if (key == null || key.Length <= 0) throw new ArgumentNullException("key"); if (iv == null || iv.Length <= 0) throw new ArgumentNullException("iv"); byte[] unprotected; using (var encryptor = Aes.Create()) { encryptor.Key = key; encryptor.IV = iv; using (var msInput = new MemoryStream(input)) { msInput.Position = 0; using ( var cs = new CryptoStream(msInput, encryptor.CreateDecryptor(), CryptoStreamMode.Read)) using (var data = new BinaryReader(cs)) using (var outStream = new MemoryStream()) { byte[] buf = new byte[2048]; int bytes = 0; while ((bytes = data.Read(buf, 0, buf.Length)) != 0) outStream.Write(buf, 0, bytes); return outStream.ToArray(); } } } } catch (Exception ex) { throw ex; } } 

Does anyone know why this might happen? For reference, this is a .NET method from the source of Microsoft.sln, which (I think) does the decryption: https://gist.github.com/Metaluim/fcf9a4f1012fdeb2a44f#file-rijndaelmanagedtransform-cs

+13
c openssl encryption aes macos
source share
1 answer

I think the AES add-on scheme has been changed between OpenSSL versions 0.9.8 * and 1.0.1 * (at least between 0.9.8r and 1.0.1j). If two of your modules use these different versions of OpenSSL, this may be the cause of your problem. To check out this first version of OpenSSL. If you click on the described case, you might think that the alignment of the fill pattern is the same.

0
source share

All Articles