openssl aes 解密流程

初始化

int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx,
                                 const EVP_CIPHER *cipher, ENGINE *impl,
                                 const unsigned char *key,
                                 const unsigned char *iv, int enc)
                                

此初始化方法的实现在evp_enc.c中,此方法中分配了秘钥的内存。 ctx->cipher_data = OPENSSL_zalloc(ctx->cipher->ctx_size);

在初始化方法中进行了加密模式的判断,判断是ECB,CBC,GCM等模式,方法为EVP_CIPHER_CTX_mode(ctx)

最后调用到cipher.init方法
实现是e_aes.c中的aes_init_key方法,在这个方法中将刚才分配的cipher_data强转成 EVP_AES_KEY.
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
现在这个key还是空的,解下来要给他赋值.

            ret = AES_set_decrypt_key(key,
                                      EVP_CIPHER_CTX_key_length(ctx) * 8,
                                      &dat->ks.ks);
            dat->block = (block128_f) AES_decrypt;
            dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
                (cbc128_f) AES_cbc_encrypt : NULL;

AES_set_decrypt_key 此方法中生成了轮密钥。
此方法是在aes_core.c中定义的,想了解轮密钥的生成,可以研究下这个方法

接着刚才的代码,发现设置了两个函数指针。应该就是就是具体的解密算法了。

            dat->block = (block128_f) AES_decrypt;
            dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
                (cbc128_f) AES_cbc_encrypt : NULL;

这样初始化就完成了。

update

加解密数据

int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
                     const unsigned char *in, int inl)

此方法定义在evp_enc.c中,定义如下

int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
                     const unsigned char *in, int inl)
{
    if (ctx->encrypt)
        return EVP_EncryptUpdate(ctx, out, outl, in, inl);
    else
        return EVP_DecryptUpdate(ctx, out, outl, in, inl);
}

由于这里是解密,进入解密方法,解密方法有调用到下面这个方法

static int evp_EncryptDecryptUpdate(EVP_CIPHER_CTX *ctx,
                                    unsigned char *out, int *outl,
                                    const unsigned char *in, int inl)

此方法中调用cipher.do_cipher,进入到e_aes.c的下面这个方法

static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
                        const unsigned char *in, size_t len)
{
  EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);

  if (dat->stream.cbc)
      (*dat->stream.cbc) (in, out, len, &dat->ks,
                          EVP_CIPHER_CTX_iv_noconst(ctx),
                          EVP_CIPHER_CTX_encrypting(ctx));
  else if (EVP_CIPHER_CTX_encrypting(ctx))
      CRYPTO_cbc128_encrypt(in, out, len, &dat->ks,
                            EVP_CIPHER_CTX_iv_noconst(ctx), dat->block);
  else
      CRYPTO_cbc128_decrypt(in, out, len, &dat->ks,
                            EVP_CIPHER_CTX_iv_noconst(ctx), dat->block);

  return 1;
}

上面方法走到了dat->stream.cbc方法中,这个方法最终的定义是在aes_cbc.c,这个也是初始化的时候函数指针的指向。

void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
                     size_t len, const AES_KEY *key,
                     unsigned char *ivec, const int enc)
{

    if (enc)
        CRYPTO_cbc128_encrypt(in, out, len, key, ivec,
                              (block128_f) AES_encrypt);
    else
        CRYPTO_cbc128_decrypt(in, out, len, key, ivec,
                              (block128_f) AES_decrypt);
}

由于是解密进入下面方法CRYPTO_cbc128_decrypt,此方法定义在cbc_128.c中

void CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out,
                           size_t len, const void *key,
                           unsigned char ivec[16], block128_f block)

这里应该是对cbc_128的通用处理,最终的处理还是在最后一个参数的函数指针AES_decrypt。

AES_decrypt定义在aes_core.c中


void AES_decrypt(const unsigned char *in, unsigned char *out,
                 const AES_KEY *key)

final

int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
{
    if (ctx->encrypt)
        return EVP_EncryptFinal(ctx, out, outl);
    else
        return EVP_DecryptFinal(ctx, out, outl);
}

调用到
int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
在EVP_DecryptFinal_ex这个方法里面没有看到解密的过程,只是一个赋值,把cipherUpdate处理的时缓存到ctx中的final数据拷贝到输出缓存区中就完事了。


        n = ctx->cipher->block_size - n;
        for (i = 0; i < n; i++)
            out[i] = ctx->final[i];
        *outl = n;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值