1

I tried GCM encryption using OpenSSL library in VC++. I am getting the encrypted data, but the data is not matching with the output data as in JAVA and C#. I used same parameter credentials.

Here is the code I am using:

int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *aad,int aad_len, unsigned char *key, unsigned char *iv,unsigned char *ciphertext, unsigned char *tag)
{
    EVP_CIPHER_CTX *ctx;

    int len;

    int ciphertext_len;


    /* Create and initialise the context */
    if (!(ctx = EVP_CIPHER_CTX_new())) handleErrors();

    /* Initialise the encryption operation. */
    if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
        handleErrors();

    /* Set IV length if default 12 bytes (96 bits) is not appropriate */
    if (1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL))
        handleErrors();

    /* Initialise key and IV */
    if (1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors();

    /* Provide any AAD data. This can be called zero or more times as
    * required
    */
    if (1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len))
        handleErrors();

    /* Provide the message to be encrypted, and obtain the encrypted output.
    * EVP_EncryptUpdate can be called multiple times if necessary
    */
    if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
        handleErrors();
    ciphertext_len = len;

    /* Finalise the encryption. Normally ciphertext bytes may be written at
    * this stage, but this does not occur in GCM mode
    */
    if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors();
    ciphertext_len += len;

    /* Get the tag */
    if (1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))
        handleErrors();

    /* Clean up */
    EVP_CIPHER_CTX_free(ctx);

    return ciphertext_len;
}

The C# Code we are using

public byte[] GCM_Encryption(byte[] plainText)
        {
            byte[] authenticationTag;
            byte[] Nonce;
            byte[] AAD;
            byte[] ciphertext;

            string _nonce = Cur_DnT.Substring(Cur_DnT.Length - 12);
            string _AAD = Cur_DnT.Substring(Cur_DnT.Length - 16);

            Nonce = new byte[] { 0x2d, 0x32, 0x35, 0x54, 0x31, 0x35, 0x3a, 0x31, 0x35, 0x3a, 0x32, 0x39 };//Encoding.UTF8.GetBytes(_nonce);
            AAD = new byte[] { 0x37, 0x2d, 0x30, 0x35, 0x2d, 0x32, 0x35, 0x54, 0x31, 0x35, 0x3a, 0x31, 0x35, 0x3a, 0x32, 0x39 };//Encoding.UTF8.GetBytes(_AAD);

            using (AuthenticatedAesCng aes = new AuthenticatedAesCng())
            {
                aes.Key = new byte[] { 0xF9, 0x28, 0x01, 0x98, 0xBB, 0xC9, 0x43, 0xF8, 0x85, 0x6D, 0xA8, 0x36, 0x0F, 0x07, 0x37, 0x92, 0x7C, 0x49, 0x45, 0x29, 0x6C, 0xAF, 0xD5, 0x30, 0x1B, 0x92, 0x0E, 0x32, 0xAA, 0x20, 0xA2, 0x33 };//SKey;
                aes.IV = Nonce;
                aes.CngMode = CngChainingMode.Gcm;

                // This data is required to verify the authentication tag, but will not go into the
                // ciphertext
                aes.AuthenticatedData = AAD;

                // Do the encryption
                using (MemoryStream ms = new MemoryStream())
                using (IAuthenticatedCryptoTransform encryptor = aes.CreateAuthenticatedEncryptor())
                using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                {
                    // Encrypt the plaintext
                    byte[] plaintext = plainText;
                    cs.Write(plaintext, 0, plaintext.Length);

                    // Complete the encryption operation, and generate the authentication tag
                    cs.FlushFinalBlock();

                    // Get the generated ciphertext and authentication tag
                    ciphertext = ms.ToArray();
                    authenticationTag = encryptor.GetTag();
                }
            }
            string ddf = BitConverter.ToString(ciphertext);
            return ciphertext.Concat(authenticationTag).ToArray();
        }
  • [AES encrypt with openssl decrypt using java](https://stackoverflow.com/q/14486814/608639), [Encrypt using OpenSSL in the same way Java does](https://stackoverflow.com/q/32018672/608639), [AES encrypt with OpenSSL, decrypt with C# .Net](https://stackoverflow.com/q/15006717/608639), [OpenSSL encryption using .NET classes](https://stackoverflow.com/q/5452422/608639), [AES 256 CBC Openssl Encryption and decryption in C#](https://stackoverflow.com/q/15470190/608639), [Encrypting & Decrypting files using OpenSSL in .NET](https://stackoverflow.com/q/5146755/608639), etc. – jww Jun 02 '17 at 07:38
  • My requirement is AES GCM in C++ @jww – vinod swamy Jun 02 '17 at 07:47
  • Use AES/GCM instead of one of the other modes. You have plenty of examples to choose from. You should also show some of your Java or C# code so folks can see how you are arriving at your AES key. – jww Jun 02 '17 at 07:51
  • Nothing obvious jumps out at me for the OpenSSL code. It looks like you are using the example at [EVP Authenticated Encryption and Decryption](https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption), which is a good starting point. Use test vectors to see which implementation(s) are producing correct results. NIST provides some at [Cryptographic Algorithm Validation Program (CAVP)](http://csrc.nist.gov/groups/STM/cavp/). – jww Jun 02 '17 at 08:20
  • 1
    The IV (Nonce) you are using the C# code is 12 bytes long. In the C code you are explicitly setting it to be 16 bytes long, so this will definitely cause a difference. You also don't show the key/IV/AAD in the C code. It would be helpful if you did to confirm that they are the same. – Matt Caswell Jun 02 '17 at 09:00
  • Thank you it's working for IV length 12 @MattCaswell – vinod swamy Jun 02 '17 at 10:00

0 Answers0