openssl实现分组加密模式(例如AES128-CBC的CBC部分)的模块名字叫做modes,源代码位于
https://gitee.com/gh_mirrors/openssl/tree/master/crypto/modes
博主又打不开github了TT,只能找个gitee镜像
头文件是modes.h。
该模块目前支持12种加密模式,如图,每一个文件就是一个模式。
加密模式与加密算法并不绑定,你可以使用自定义的加密函数,只要分组长度是128bit即可。理论上可以使用非对称的加密函数,但必须是128bit等长分组,这种情况并不常见。
以CRYPTO_cbc128_encrypt为例,该函数的最后一个参数是一个函数指针,用于对一个分组进行加密,需要调用者提供。
void CRYPTO_cbc128_encrypt(const unsigned char *in, unsigned char *out,size_t len, const void *key,unsigned char ivec[16], block128_f block)
{size_t n;const unsigned char *iv = ivec;if (len == 0)return;#if !defined(OPENSSL_SMALL_FOOTPRINT)if (STRICT_ALIGNMENT &&((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {while (len >= 16) {for (n = 0; n < 16; ++n)out[n] = in[n] ^ iv[n];(*block) (out, out, key);iv = out;len -= 16;in += 16;out += 16;}} else {while (len >= 16) {for (n = 0; n < 16; n += sizeof(size_t))*(size_t_aX *)(out + n) =*(size_t_aX *)(in + n) ^ *(size_t_aX *)(iv + n);(*block) (out, out, key);iv = out;len -= 16;in += 16;out += 16;}}
#endifwhile (len) {for (n = 0; n < 16 && n < len; ++n)out[n] = in[n] ^ iv[n];for (; n < 16; ++n)out[n] = iv[n];(*block) (out, out, key);iv = out;if (len <= 16)break;len -= 16;in += 16;out += 16;}if (ivec != iv)memcpy(ivec, iv, 16);
}
注意事项:
1、block参数必须支持前2个参数使用相同的指针,即输入输出使用同一块缓存。
2、key参数没有长度限制,实际长度取决于block。因此受限制的是分组长度而非密钥长度,密钥长度可以不等于分组长度,AES256就是这种情况。
对于GCM这种较为复杂的模式,需要输入上下文对象指针。