好习惯,先上代码再说事

加密

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的更多相关文章

  1. openssl AES加密

    此代码不涉及ECB和CBC等关联加密 #include <stdio.h> #include <string.h> #include <stdlib.h> #inc ...

  2. JS和利用openssl的object C加密得到相同的aes加密密文

    这是之前接到的一个工作内容,项目原本的登录操作是获得账号和密码以后,对密码进行一遍MD5加密,然后传递账号和密文到cgi文件.在c中获取到账户以后,从数据库中获取到密码,对密码进行一次MD5的加密,然 ...

  3. openssl与cryptoAPI交互AES加密解密

    继上次只有CryptoAPI的加密后,这次要实现openssl的了 动机:利用CryptoAPI制作windows的IE,火狐和chrome加密控件后,这次得加上与android的加密信息交互 先前有 ...

  4. OPENSSL安装 以及使用openssl中的AES加密和解密

    OPENSSL安装:(VS) 1:第一步和所有的软件安装一样. 2:将OPENSSL中INLUCDE 和 LIB 分别拷贝到VS中VC的INLUCDE 和LIB目录下(我的机器上的目录是:C:\Pro ...

  5. [转贴]C++调用openssl 的AES加密例子

    #include <stdio.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h ...

  6. openssl之aes加密(源码分析 AES_encrypt 与 AES_cbc_encrypt ,加密模式)

    首先要了解AES加密是什么,以及几种加密模式的区别.之后才是编程.具体的编程案例,在下面的链接. openssl之aes加密(AES_cbc_encrypt 与 AES_encrypt 的编程案例) ...

  7. openSSL实现AES加密

    Openssl是很常见的C接口的库,个人觉得易用.以下是AES加密的使用备忘.如果你有一定的密码学基础,那么就很好理解.代码是从网上弄下来的(原始地址已经忘记了),然后在尝试的过程中改了一点东西.其它 ...

  8. c#和js互通的AES加密解密

    一.使用场景 在使用前后端分离的框架中常常会进行传输数据相互加密解密以确保数据的安全性,如web Api返回加密数据客户端或web端进行解密,或者客户端或web端进行加密提交数据服务端解密数据等等. ...

  9. javascript AES加密 C#AES解密实现

    首先需要引入js类库 crypto-js(开源),地址:http://code.google.com/p/crypto-js 现在很多人无法打开这个地址不要紧,下面我们会将全部代码贴出来 需要引入 a ...

随机推荐

  1. php 5.6.14手动安装 php -v 显示没有安装

    奇怪了,今天利用源码手动php,安装成功后,利用php -v提示没有安装,which php也是有问题,php文件也没有办法执行 搞了半天,发现是没有添加环境变量,╮(╯▽╰)╭ 方法: 修改/etc ...

  2. Windows Server 2012下安装Hyper-V虚拟机

    Windows Server 2012下安装Hyper-V虚拟机 Win server 2012系统中Hyper-V 性能进一步提高,广大爱好者都尝试体验它,可是有不少朋友无法正确安装虚拟机,尽管在网 ...

  3. Freebsd下压缩解压文件详解

    压缩篇: 把/usr/webgames目录下的文件打包.命名为bak.tar.gz 放到/usr/db-bak目录里 下面命令可以在任意目录执行.无视当前目录和将要存放文件的目录.tar -zcvf ...

  4. ssh注解basedao简单的实现

    @Repository public class BaseDao extends HibernateDaoSupport{ protected Class objectClass; protected ...

  5. CodeSmith 7.01破解下载

    运行CodesmithKeyGenerator.exe,1.修改Prefix输入框的值为:CS70P-2.在主页面点Generate,生成注册码,填入激活码到code smith的Serial框中,( ...

  6. WP8_UTF8 to GB2312转码 (url网址中带中文字符的处理)

    直接使用例如:http://www.abc.php?name=中文符 ,客户端调用,在服务端修改后,会出现乱码, 而windows phone 又不能直接支持gb2312, 经过大量分析和验证,发现 ...

  7. OpenLDAP 安装及配置 笔记

    首先下载 OpenLdap(Ldap服务器) 和 LdapAdmin(客户端) 两个软件 OpenLDAPforWindows_2.4.39.part1.rar OpenLDAPforWindows_ ...

  8. leetcode 27

    27. Remove Element Given an array and a value, remove all instances of that value in place and retur ...

  9. XCode 7.1 安装 Alcatraz包管理器失败的处理

    按照官方的文档(https://github.com/supermarin/Alcatraz),先卸载再重新安装即可.步骤如下: 1. 退出Xcode 2. rm -rf ~/Library/Appl ...

  10. PHP版实现友好的时间显示方式(例如:2小时前)

    完整php类,通常我会配合smary使用,快捷使用 (plugins/function.rdate.php),更多php技术开发就去php教程网,http://php.662p.com <?PH ...