openssl AES加密以及padding
好习惯,先上代码再说事
加密
void AesEncrypt(unsigned char* pchIn, int nInLen, unsigned char *ciphertext, int &ciphertext_len, unsigned char * pchKey)
{
EVP_CIPHER_CTX en;
EVP_CIPHER_CTX_init(&en);
const EVP_CIPHER *cipher_type;
unsigned char *passkey, *passiv, *plaintxt;
unsigned char *plaintext = NULL; unsigned char iv[] = { 0x00}; cipher_type = EVP_aes_128_ecb();
EVP_EncryptInit_ex(&en, cipher_type, NULL, pchKey, iv); //当长度正好为16字节的倍数时,同样需要padding
static const int MAX_PADDING_LEN = 16; if(!EVP_EncryptInit_ex(&en, NULL, NULL, NULL, NULL))
{
printf("ERROR in EVP_EncryptInit_ex \n");
return;
} int bytes_written = 0;
ciphertext_len = 0;
if(!EVP_EncryptUpdate(&en, ciphertext, &bytes_written, (unsigned char *) pchIn, nInLen) )
{
printf("ERROR in EVP_EncryptUpdate \n");
return;
}
ciphertext_len += bytes_written; if(!EVP_EncryptFinal_ex(&en, ciphertext + bytes_written, &bytes_written))
{
printf("ERROR in EVP_EncryptFinal_ex \n");
return;
}
ciphertext_len += bytes_written;
ciphertext[ciphertext_len] = 0; EVP_CIPHER_CTX_cleanup(&en); return;
}
解密
void AesDecrypt(unsigned char* pchInPut, int nInl, unsigned char *pchOutPut, unsigned char *pchKey)
{
unsigned char achIv[8];
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx); EVP_DecryptInit_ex(&ctx, EVP_aes_128_ecb(), NULL, pchKey, achIv);
int nLen = 0;
int nOutl = 0; EVP_DecryptUpdate(&ctx, pchOutPut+nLen, &nOutl, pchInPut+nLen, nInl);
nLen += nOutl; EVP_DecryptFinal_ex(&ctx, pchOutPut+nLen, &nOutl);
nLen+=nOutl;
pchOutPut[nLen]=0;
EVP_CIPHER_CTX_cleanup(&ctx); return;
}
下面开始说事,纯A代码的下面不用看了。
首先明确以下概念,AES是加密的算法,使用128、192 和 256 位密钥,将被加密数据划分为128位(16字节)一块,然后使用某种加密模式进行加密。
1、主要的加密模式有以下几种:
ECB模式
按照块密码的块大小被分为数个块,并对每个块进行独立加密。
优点:
1.简单;
2.有利于并行计算;
3.误差不会被传送;
缺点:
1.不能隐藏明文的模式;
2.可能对明文进行主动攻击;
CBC模式:
每个平文块先与前一个密文块进行异或后,再进行加密。在这种方法中,每个密文块都依赖于它前面的所有平文块。
同时,为了保证每条消息的唯一性,在第一个块中需要使用初始化向量。
优点:
1.不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。
缺点:
1.不利于并行计算;
2.误差传递;
3.需要初始化向量IV
CFB模式:
模式类似于CBC,可以将块密码变为自同步的流密码。
优点:
1.隐藏了明文模式;
2.分组密码转化为流模式;
3.可以及时加密传送小于分组的数据;
缺点:
1.不利于并行计算;
2.误差传送:一个明文单元损坏影响多个单元;
3.唯一的IV;
OFB模式:
可以将块密码变成同步的流密码。它产生密钥流的块,然后将其与平文块进行异或,得到密文。
优点:
1.隐藏了明文模式;
2.分组密码转化为流模式;
3.可以及时加密传送小于分组的数据;
缺点:
1.不利于并行计算;
2.对明文的主动攻击是可能的;
3.误差传送:一个明文单元损坏影响多个单元;
PCBC模式
略
CTR模式
略
在我的代码中使用的是最简单的ecb模式。
2、由于被加密数据分组时,有可能不会正好为128bit的整数倍,所以需要padding(填充补齐),而padding模式有以下几种:
None //不填充。
PKCS7 //填充字符串由一个字节序列组成,每个字节填充该字节序列的长度。
Zeros //填充字符串由设置为零的字节组成。
ANSIX923 //ANSIX923 填充字符串由一个字节序列组成,此字节序列的最后一个字节填充字节序列的长度,其余字节均填充数字零。
ISO10126 //ISO10126 填充字符串由一个字节序列组成,此字节序列的最后一个字节填充字节序列的长度,其余字节填充随机数据。
根据官方文档地址(https://www.openssl.org/docs/crypto/EVP_CIPHER_CTX_set_padding.html)中描述:
If padding is enabled (the default) then EVP_EncryptFinal_ex() encrypts the "final" data, that is any data that remains in a partial block. It uses standard block padding (aka PKCS padding) as described in the NOTES section, below. The encrypted final data is written to out which should have sufficient space for one cipher block. The number of bytes written is placed in outl. After this function is called the encryption operation is finished and no further calls to EVP_EncryptUpdate() should be made.
可以知道在调用EVP_EncryptFinal_ex函数时,padding是默认启用的。
是否使用padding可以通过EVP_CIPHER_CTX_set_padding函数设置,第二个参数为0则禁用padding,为1则启用padding。
文档中说padding的模式为PKCS padding,具体指的是PKCS#7。
这里用例子表述一下PKCS#7:
假设块长度为128bit,也就是16个字节。
那么当需要padding的字符串长度为11时(假设字符源串16进制为 : DD DD DD DD DD DD DD DD | DD DD DD DD ),则padding结果为:
| DD DD DD DD DD DD DD DD | DD DD DD DD 04 04 04 04 |
也就是缺4个字节,就是用04来padding,缺5个,就用05来Padding。
然后再将padding后的字符串进行加密。
我如何知道Padding模式是PKCS#7的?如果你不质疑我的分析,此部分可以跳过。
1.先使用一个key对长度为16的源串(随意)进行加密
EVP_EncryptFinal_ex函数调用后,得到结果如图1中红色部分,
红色部分就是padding内容的加密结果。
因为在PKCS#7模式下,padding的内容为 | 16 16 16 16 16 16 16 16 | 16 16 16 16 16 16 16 16 |
那么我构造一个字符串,如下图
经过加密后,如下图
可以看到此处16进制字符串与上面的红色字符串一致,所以能说明此处使用的Padding模式为PKCS#7。
为什么要研究这个padding?
1.当在使用openssl库与其他不同的库进行通信时,padding与加密模式不同(这都能搞错?)会导致让你蛋疼的问题。
2.理论是指导实践的标准,实践是检验理论的方法。
关于padding更详细的信息可以参考:
http://en.wikipedia.org/wiki/Padding_(cryptography)
最后hex与char互转的代码
char SupperToLower(char in)
{
if(in >= 65 && in <= 90)
return in + 32;
else
return in;
} char LowerToSupper(char in)
{
if(in >= 97 && in <= 122)
return in - 32;
else
return in;
} static const char *tohex = "0123456789ABCDEF"; void CharToHex(unsigned char *pchOut, const unsigned char *pchIn, int nLen)
{
int i = 0;
while(i < nLen)
{
*pchOut++ = tohex[pchIn[i] >> 4];
*pchOut++ = tohex[pchIn[i] & 0x0F];
++i;
} return;
} void HexToChar(unsigned char *pchOut, const unsigned char *pchIn, int nInLen)
{
int an=1,num=0,st,q,tmp,kk = 0;
for(q = nInLen - 1,st = nInLen / 2 - 1; q >= 0,st >= 0; q --)
{
if(kk==2)
{
pchOut[st] = (unsigned char)num;
st --;
num = 0;
an = 1;
kk = 0;
}
if(LowerToSupper(pchIn[q]) >= 'A' && LowerToSupper(pchIn[q]) <= 'F')
tmp = pchIn[q] - 'A' + 10;
else
tmp = pchIn[q] - '0';
num += an * tmp;
an *= 16;
kk ++;
} return;
}
openssl AES加密以及padding的更多相关文章
- openssl AES加密
此代码不涉及ECB和CBC等关联加密 #include <stdio.h> #include <string.h> #include <stdlib.h> #inc ...
- JS和利用openssl的object C加密得到相同的aes加密密文
这是之前接到的一个工作内容,项目原本的登录操作是获得账号和密码以后,对密码进行一遍MD5加密,然后传递账号和密文到cgi文件.在c中获取到账户以后,从数据库中获取到密码,对密码进行一次MD5的加密,然 ...
- openssl与cryptoAPI交互AES加密解密
继上次只有CryptoAPI的加密后,这次要实现openssl的了 动机:利用CryptoAPI制作windows的IE,火狐和chrome加密控件后,这次得加上与android的加密信息交互 先前有 ...
- OPENSSL安装 以及使用openssl中的AES加密和解密
OPENSSL安装:(VS) 1:第一步和所有的软件安装一样. 2:将OPENSSL中INLUCDE 和 LIB 分别拷贝到VS中VC的INLUCDE 和LIB目录下(我的机器上的目录是:C:\Pro ...
- [转贴]C++调用openssl 的AES加密例子
#include <stdio.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h ...
- openssl之aes加密(源码分析 AES_encrypt 与 AES_cbc_encrypt ,加密模式)
首先要了解AES加密是什么,以及几种加密模式的区别.之后才是编程.具体的编程案例,在下面的链接. openssl之aes加密(AES_cbc_encrypt 与 AES_encrypt 的编程案例) ...
- openSSL实现AES加密
Openssl是很常见的C接口的库,个人觉得易用.以下是AES加密的使用备忘.如果你有一定的密码学基础,那么就很好理解.代码是从网上弄下来的(原始地址已经忘记了),然后在尝试的过程中改了一点东西.其它 ...
- c#和js互通的AES加密解密
一.使用场景 在使用前后端分离的框架中常常会进行传输数据相互加密解密以确保数据的安全性,如web Api返回加密数据客户端或web端进行解密,或者客户端或web端进行加密提交数据服务端解密数据等等. ...
- javascript AES加密 C#AES解密实现
首先需要引入js类库 crypto-js(开源),地址:http://code.google.com/p/crypto-js 现在很多人无法打开这个地址不要紧,下面我们会将全部代码贴出来 需要引入 a ...
随机推荐
- 两个正在运行的activity之间的通信
在android应用程序开发的时候,从一个activity启动另一个activity并传递一些数据到新的activity非常的简单,但是当您需要让后台运行的activity回到前台并传递一些数据可能就 ...
- html5相关
1.语义化标签: header\section\aside\footer 2.音视频播放: video\audio 其中video支持ogg\mpeg4\webm格式的视频: 3.canvas 一.画 ...
- openstack4j
Identity // V2 authentication OSClientV2 os = OSFactory.builderV2() .endpoint("http://127.0.0.1 ...
- qemu-img convert -c -O qcow2 source.raw aim.qcow2
qemu-img convert -c -O qcow2 source.raw aim.qcow2 qemu-img create -f qcow2 -o preallocation=metadata ...
- 【MySQL】frm文件解析
官网说明:http://dev.mysql.com/doc/internals/en/frm-file-format.html frm是MySQL表结构定义文件,通常frm文件是不会损坏的,但是如果出 ...
- Heavily reliance on forensic tools is risky
We could take advantage of forensic tools to examine and analyze the evidence, but heavily reliance ...
- 1028 C语言文法
<程序> -> <外部声明> | <程序> <外部声明> <外部声明> -> <函数定义> | &l ...
- Android IOS WebRTC 音视频开发总结(三九)-- win10升级为何要p2p
本文主要介绍webrtc p2p的应用场景,文章来自博客园RTC.Blacker,支持原创,转载请说明出处. P2P最简单的解释就是两个客户端之间直接进行数据交互,不经过服务端转发. 最早接触P2P是 ...
- C/C++下Netbeans的配置
目录 目录1 1 netbeans开发环境搭建2 2 netbeans工程管理2 2.1 采用IDE自动生成Makefile2 3 netbeans工程配置2 3.1 编译工具链3 3.1.1 添加配 ...
- 破解source insignt方法
source insignt版本:官网3.5版本 方法:在桌面建立一个文本文档,将下面内容拷贝进去,保存为.reg文件(注意拓展名问题,自己设置),然后双击即可. win7 64bit Window ...