1.OpenSSL提供了AES加解密算法的API
const char *AES_options(void);
AES算法状态,是所有支持或者是部分支持。
返回值:“aes(full)” 或者"aes(partial)"
int AES_set_encrypt_key(const unsigned char *userKey, const int bits,AES_KEY *key);
设定加密用的Key;
userKey: 密钥数值。
bits:密钥长度,以bit为单位。假设密钥数字是16个字节,则此參数值应为128。
key: AES_KEY对象指针;
返回值: 0 成功, -1 userkey,key为空, -2: 密钥长度不是128。192。256;
int AES_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);
设定解密用的Key;
userKey: 密钥数值;
bits:密钥长度,以bit为单位,假设密钥数字是16个字节。则此參数值应为128;
key: AES_KEY对象指针;
返回值: 0 成功, -1 userkey。key为空。 -2: 密钥长度不是128。192,256。
void AES_encrypt(const unsigned char *in, unsigned char *out,const AES_KEY *key);
AES 加密。加密单个数据块。in,out能够是同一内存区;
in: 须要加密的数据;
out: 加密后的数据。
key:AES 密钥。
void AES_decrypt(const unsigned char *in, unsigned char *out,const AES_KEY *key);
AES 解密。解密单个数据块,in。out能够是同一内存区;
in: 须要解密的数据。
out: 解密后的数据;
key:AES 密钥。
void AES_ecb_encrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key, const int enc);
AES加密/解密单个数据块,ECB模式
in: 须要加密/解密的数据;
out: 计算后输出的数据。
key:密钥
enc: AES_ENCRYPT 代表加密, AES_DECRYPT代表解密。
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t length, const AES_KEY *key, unsigned char *ivec, const int enc);
AES加密/解密单个数据块,CBC模式
in: 须要加密/解密的数据;
out: 计算后输出的数据。
length: 数据长度
key:密钥
ivec: 初始向量
enc: AES_ENCRYPT 代表加密, AES_DECRYPT代表解密;
void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
AES CFB128位模式加密/解密。输入输出数据区能够重叠。
in: 须要加密/解密的数据。
out: 计算后输出的数据;
length: 数据长度;
key: 密钥;
ivec: 初始化向量
num: 输出參数。计算状态。多少个CFB数据块
enc: 计算模式。 加密: AES_ENCRYPT 。 解密: AES_DECRYPT
void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
AES CFB1位模式加密/解密。输入输出数据区能够重叠;
in: 须要加密/解密的数据;
out: 计算后输出的数据;
length: 数据长度;
key: 密钥;
ivec: 初始化向量
num: 输出參数,计算状态,多少个CFB数据块
enc: 计算模式, 加密: AES_ENCRYPT , 解密: AES_DECRYPT
void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
AES CFB8位模式加密/解密。输入输出数据区能够重叠;
in: 须要加密/解密的数据;
out: 计算后输出的数据;
length: 数据长度;
key: 密钥;
ivec: 初始化向量
num: 输出參数,计算状态,多少个CFB数据块
enc: 计算模式, 加密: AES_ENCRYPT , 解密: AES_DECRYPT
void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num);
AES OFB128位模式加密/解密,输入输出数据区能够重叠;
in: 须要加密/解密的数据;
out: 计算后输出的数据。
length: 数据长度;
key: 密钥。
ivec: 初始化向量
num: 输出參数,计算状态,多少个CFB数据块
enc: 计算模式, 加密: AES_ENCRYPT , 解密: AES_DECRYPT
void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char ivec[AES_BLOCK_SIZE],
unsigned char ecount_buf[AES_BLOCK_SIZE],
unsigned int *num);
AES CTR128位模式加密/解密,输入输出数据区能够重叠;
in: 须要加密/解密的数据。
out: 计算后输出的数据;
length: 数据长度;
key: 密钥。
ivec: 初始化向量
ecount_buf: 输出參加,加密的次数,在第一次调用此函数时,须要初始化为0
num: 输出參数,计算状态,多少个CFB数据块,在第一次调用此函数时,须要初始化为0
enc: 计算模式。 加密: AES_ENCRYPT , 解密: AES_DECRYPT
void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, const int enc);
AES 加密/解密,输入输出数据区能够重叠,初始化向量是加密数据块的2倍,加密前用前半部分做一次异或。加密后用后半部分做一次异或;
in: 须要加密/解密的数据;
out: 计算后输出的数据。
length: 数据长度;
key: 密钥;
ivec: 初始化向量
enc: 计算模式。 加密: AES_ENCRYPT , 解密: AES_DECRYPT
void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
const AES_KEY *key2, const unsigned char *ivec,
const int enc);
AES 加密/解密。输入输出数据区能够重叠。初始化向量是加密数据块的4倍,加密前用第一部分做一次异或。加密后用第二部分做一次异或;
最后一个加密数据块,加密前用第三部分异或,加密后用第四部分异或;
in: 须要加密/解密的数据;
out: 计算后输出的数据;
length: 数据长度。
key: 密钥。
ivec: 初始化向量
enc: 计算模式, 加密: AES_ENCRYPT , 解密: AES_DECRYPT
int AES_wrap_key(AES_KEY *key, const unsigned char *iv,
unsigned char *out,
const unsigned char *in, unsigned int inlen)
用AES算法对明文key数据加密
key: AES Key,用于加密密钥数据
iv: 初始化向量
out: 加密后的密钥数据
in: 密钥数据
inlen: 密钥数据长度
返回值: 1: 成功。 0: 失败
int AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
unsigned char *out,
const unsigned char *in, unsigned int inlen)
用AES算法对明文key数据加密
key: AES Key,用于加密密钥数据
iv: 初始化向量
out: 加密后的密钥数据
in: 密钥数据
inlen: 密钥数据长度
返回值: 1: 成功, 0: 失败
2.C实例分析
首先要了解AES加密是什么。以及几种加密模式的差别。之后才是编程。
ECB模式
长处:
1.简单;
2.有利于并行计算。
3.误差不会被传送。
缺点:
1.不能隐藏明文的模式;
2.可能对明文进行主动攻击;
CBC模式:
长处:
1.不easy主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。
缺点:
1.不利于并行计算。
2.误差传递。
3.须要初始化向量IV
CFB模式:
长处:
1.隐藏了明文模式;
2.分组password转化为流模式;
3.能够及时加密传送小于分组的数据;
缺点:
1.不利于并行计算;
2.误差传送:一个明文单元损坏影响多个单元;
3.唯一的IV;
ofb模式:
长处:
1.隐藏了明文模式;
2.分组password转化为流模式;
3.能够及时加密传送小于分组的数据;
缺点:
1.不利于并行计算;
2.对明文的主动攻击是可能的;
3.误差传送:一个明文单元损坏影响多个单元;
了解这些加密模式之后,再看openssl提供的接口就好理解了。
aes.c 源代如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <openssl/aes.h>
// out的内存大小需要注意 后边有 out += AES_BLOCK_SIZE
// 所以out 内存最小不能小于 AES_BLOCK_SIZE
int aes_encrypt(char* in, char* key, char* out)
{
if (!in || !key || !out)
{
return 0;
}
AES_KEY aes;
if (AES_set_encrypt_key((unsigned char*)key, 128, &aes) < 0)
{
return 0;
}
int len = strlen(in), en_len = 0;
//输入输出字符串够长。而且是AES_BLOCK_SIZE的整数倍,须要严格限制
while (en_len < len)
{
AES_encrypt((unsigned char*)in, (unsigned char*)out, &aes);
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
en_len += AES_BLOCK_SIZE;
}
return 1;
}
int aes_decrypt(char* in, char* key, char* out)
{
if (!in || !key || !out)
{
return 0;
}
AES_KEY aes;
if (AES_set_decrypt_key((unsigned char*)key, 128, &aes) < 0)
{
return 0;
}
int len = strlen(in), en_len = 0;
while (en_len < len)
{
AES_decrypt((unsigned char*)in, (unsigned char*)out, &aes);
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
en_len += AES_BLOCK_SIZE;
}
return 1;
}
int main(int argc, char**argv)
{
char *data, *key = "1111222", encrypt_buffer[100] = {0}, decrypt_buffer[100] = {0};
size_t len;
if (argc != 2)
{
printf("请输入待加密的明文。\n");
return -1;
}
data = argv[1];
printf("原始数据:%s\n", data);
len = strlen(data);
printf("明文长度:%d\n", len);
aes_encrypt(data, key, encrypt_buffer);
printf("加密结果:%s\n", encrypt_buffer);
aes_decrypt(encrypt_buffer, key, decrypt_buffer);
printf("解密结果:%s\n", decrypt_buffer);
}
编译:
gcc aes.c -lssl -lcrypto
运行效果: