OpenSSL C example of AES-GCM using EVP interfaces

后端 未结 4 1456
名媛妹妹
名媛妹妹 2021-02-01 23:09

For AES-GCM encryption/decryption, I tried this, but it has a problem.

ctx     = EVP_CIPHER_CTX_new();

//Get the cipher.
cipher  = EVP_aes_128_gcm ();


#define         


        
4条回答
  •  星月不相逢
    2021-02-01 23:43

    OpenSSL has a nice wiki page on using AES-GCM ciphers. Code examples are also provided. The link to the page is Authenticated_Decryption_using_GCM_mode

    I followed this wiki and worked out decryption for AES-GCM. Code segment is copied below

    int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *aad,
        int aad_len, unsigned char *tag, unsigned char *key, unsigned char *iv,
        unsigned char *plaintext)
    {
        EVP_CIPHER_CTX *ctx;
        int len;
        int plaintext_len;
        int ret;
    
        /* Create and initialise the context */
        if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
    
        /* Initialise the decryption operation. */
        if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
            handleErrors();
    
        /* Set IV length. Not necessary if this is 12 bytes (96 bits) */
        if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL))
            handleErrors();
    
        /* Initialise key and IV */
        if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors();
    
        /* Provide any AAD data. This can be called zero or more times as
         * required
         */
        if(!EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len))
            handleErrors();
    
        /* Provide the message to be decrypted, and obtain the plaintext output.
         * EVP_DecryptUpdate can be called multiple times if necessary
         */
        if(!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
            handleErrors();
        plaintext_len = len;
    
        /* Set expected tag value. Works in OpenSSL 1.0.1d and later */
        if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag))
            handleErrors();
    
        /* Finalise the decryption. A positive return value indicates success,
         * anything else is a failure - the plaintext is not trustworthy.
         */
        ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
    
        /* Clean up */
        EVP_CIPHER_CTX_free(ctx);
    
        if(ret > 0)
        {
            /* Success */
            plaintext_len += len;
            return plaintext_len;
        }
        else
        {
            /* Verify failed */
            return -1;
        }
    }
    

    Also, as people pointed out, you should check the value returned from EVP_DecryptFinal_ex(). If your cipher text is modified a bit, it still can be decrypted, but the final returning value will not be true, because the authentication tag (or the mac) can not be verified.

提交回复
热议问题