• OpenSSL中AES加密的用法


    《OpenSSL中AES加密的用法》
    作者: 游蓝海
    原文链接: http://blog.csdn.net/you_lan_hai/article/details/50992719
    转载请注明出处

    使用API的时候,需要特别小心数据长度,我在初次使用的时候简直被弄的晕头转向,遂作此文留个备忘。一般没有指定长度的参数,默认都是16(AES_BLOCK_SIZE)个字节。输出数据的长度一般都是16字节的倍数,否则会出现数组越界访问。
    以下API中,encrypt表示加密,decrypt表示解密。

    1.生成加密/解密的Key

    int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
                            AES_KEY *key);
    int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
                            AES_KEY *key);

    参数说明:

    参数名称 描述
    userKey 用户指定的密码。注意:只能是16、24、32字节。如果密码字符串长度不够,可以在字符串末尾追加一些特定的字符,或者重复密码字符串,直到满足最少的长度。
    bits 密码位数。即userKey的长度 * 8,只能是128、192、256位。
    key 向外输出参数。

    如果函数调用成功,返回0,否则是负数。

    2.使用AES加密/解密

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

    参数说明:

    参数名称 描述
    in 输入数据。必须是16字节。
    out 输出数据。必须是16字节。
    key 使用AES_set_encrypt/decrypt_key生成的Key。

    AES_encrypt/AES_decrypt一次只处理16个字节。如果输入数据较长,你需要使用循环语句,每16个字节处理一次,直到所有数据处理完毕。如果数据不足16字节,可以用0填充至16字节。

    3.使用AES CBC加密/解密

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

    参数说明:

    参数名称 描述
    in 输入数据。长度任意。
    out 输出数据。能够容纳下输入数据,且长度必须是16字节的倍数。
    length 输入数据的实际长度。
    key 使用AES_set_encrypt/decrypt_key生成的Key。
    ivec 可读写的一块内存。长度必须是16字节。
    enc 是否是加密操作。AES_ENCRYPT表示加密,AES_DECRYPT表示解密。

    这个函数比AES_encrypt多了一个ivec参数,ivec的内容可以任意指定,但是加密和解密操作必须使用同样的数据。在AES_cbc_encrypt底层,实际上是每16个字节做一次处理,先和ivec做异或运算,然后调用AES_encrypt函数进行加密。
    AES_cbc_encrypt在加密的过程中会修改ivec的内容,因此ivec参数不能是一个常量,而且不能在传递给加密函数后再立马传递给解密函数,必须重新赋值之后再传递给解密函数。

    关于输出数据的长度
    输出数据缓冲区的长度必须是16字节的倍数,加密完成后,比输入长度多出来的输出数据是不可以丢弃的。因此,存档的时候,需要记录原始数据的长度

    关于输入数据的长度不必是16字节的倍数(做个备忘):
    下面是AES_cbc_encrypt函数的底层实现代码

        ... 
        //处理16字节倍数的数据
        while (len >= 16) {
                for (n = 0; n < 16; ++n)
                    out[n] = in[n] ^ iv[n];
                (*block) (out, out, key); //调用AES_encrypt处理数据
                iv = out;
                len -= 16;
                in += 16;
                out += 16;
            }
        //当数据小于16字节的时候,进入下面的循环
        while (len) { 
            for (n = 0; n < 16 && n < len; ++n)
                out[n] = in[n] ^ iv[n];
            for (; n < 16; ++n)
                out[n] = iv[n]; //使用ivec补齐不足16字节的部分
            (*block) (out, out, key); //调用AES_encrypt处理数据
            iv = out;
            if (len <= 16)
                break;
            len -= 16;
            in += 16;
            out += 16;
        }

    4.结尾

    其他加密函数我还没有用过,在此就不继续列举了,但是参数跟上面几个相似,弄明白上面的就不成问题。

  • 相关阅读:
    [CF603C] Lieges of Legendre
    [CF1070A] Find a Number
    [CF431D] Random Task
    2020牛客暑期多校训练营(第二场)C
    2020牛客暑期多校训练营(第二场)F
    2020牛客暑期多校训练营(第二场)D
    2020牛客暑期多校训练营(第一场)H
    [CF1000E] We Need More Bosses
    Java学习2 (ThreadLocal)
    Java复习1
  • 原文地址:https://www.cnblogs.com/ygxsk/p/7693978.html
Copyright © 2020-2023  润新知