When I see you again(加密原理介绍,代码实现DES、AES、RSA、Base64、MD5)
关于网络安全的数据加密部分,本来打算总结一篇博客搞定,没想到东西太多,这已是第三篇了,而且这篇写了多次,熬了多次夜,真是again and again。起个名字:数据加密三部曲,前两部链接如下:
- 整体介绍:网络安全——数据的加密与签名,RSA介绍
- 编码与哈希实现:网络安全——Base64编码、MD5、SHA1-SHA512、HMAC(SHA1-SHA512)哈希
- 本篇DES、AES、RSA加密的介绍与实现
github下载地址
https://github.com/mddios/EncryptionTools
代码提供两种加解密方法:
- 一个是我自己封装的NSString的分类,用起来也比较方便,也足够我们日常使用。
- 另一个是https://github.com/kelp404/CocoaSecurity,也将其集成到了工程。
一、DES对称加密
关于DES 3DES加密解密原理不再介绍,现在已经用的不多,如果你的项目还在使用DES加密,还是赶快换吧,换做AES或者更强的非对称RSA加密。
另外它与AES有很多的相似性,也可以参照AES介绍。下面是具体的用法。
对"123"加密,密钥为16进制的3031323334353637(01234567)
使用电脑终端:
echo -n "123" | openssl enc -des-ecb -a -K 3031323334353637
结果:
MV5dUGKtzbM=
代码加密解密使用:
首先引入头文件NSString+Encryption.h
/*
DES加密 key为NSString形式 结果返回base64编码
*/
- (NSString *)desEncryptWithKey:(NSString *)key;
/*
DES加密 key为NSData形式 结果返回NSData
*/
- (NSData *)desEncryptWithDataKey:(NSData *)key;
#pragma mark - DES解密
/*
DES解密,字符串必须为base64格式,key为字符串形式
*/
- (NSString *)desDecryptWithKey:(NSString *)key;
/*
DES解密
*/
+ (NSData *)desDecryptWithData:(NSData *)data dataKey:(NSData *)key;
二、AES对称加密
AES是高级加密标准Advanced Encryption Standard
的缩写,有多种模式,下面介绍使用最多的两种
ECB(Electronic Code Book,电子密码本)模式
是一种基础的加密方式,要加密的数据被分割成分组长度相等的块(不足补齐,补齐方式下文介绍),然后单独的一个个组加密,合在一起输出组成密文。
电脑终端:
echo -n "123" | openssl enc -aes-128-ecb -a -K 30313233343536373839414243444546
加密结果:
0b6ikfq9CQs11aSCnNXIog==
代码加密解密使用:
首先引入头文件NSString+Encryption.h
/**
AES-ECB模式加密
@param key Hex形式,密钥支持128 192 256bit,16、24、32字节,转换为16进制字符串长度为32、48、64,长度错误将抛出异常
@return 加密结果为base64编码
*/
- (NSString *)aesECBEncryptWithHexKey:(NSString *)key;
/**
AES-ECB模式加密
@param key 字符串形式,密钥支持128 192 256bit,16、24、32字节,长度错误将抛出异常
@return 加密结果为base64编码
*/
- (NSString *)aesECBEncryptWithKey:(NSString *)key;
/**
AES-ECB模式加密
@param key 密钥支持128 192 256bit,16、24、32字节,长度错误将抛出异常
*/
- (NSData *)aesECBEncryptWithDataKey:(NSData *)key;
/*
ECB模式解密,返回base64编码
*/
- (NSString *)aesECBDecryptWithHexKey:(NSString *)key;
/*
ECB模式解密,返回NSData
*/
- (NSData *)aesECBDecryptWithDataKey:(NSData *)key;
CBC(Cipher Block Chaining,加密块链)模式
是一种循环模式,也将要加密的数据分割为长度相等的组(不足补齐,补齐方式下文介绍),前一个分组的密文和当前分组的明文异或操作后再加密,这样做的目的是增强破解难度,会比ECB安全一点。但是也因为他们的关联性,造成以下三个缺点:
- 不利于并行计算:很明显第一组完成才能计算第二组然后第三组。。。
- 误差传递:也是依次传递
- 需要初始化向量IV:第二组根据第一组的结果来加密,那第一组根据谁呢?那就是需要额外提供初始化向量
可以在电脑终端(openssl):
echo -n "123" | openssl enc -aes-128-cbc -a -K 30313233343536373839414243444546 -iv 30313233343536373839414243444546
结果:
5IQJlqxa2e5NGzGqqPpoSw==
代码加密解密使用:
首先引入头文件NSString+Encryption.h
/**
AES-CBC模式加密,默认模式
@param key Hex形式,密钥支持128 192 256bit,16、24、32字节,转换为16进制字符串长度为32、48、64,长度错误将抛出异常
@param iv 进制字符串形式;初始化向量iv为16字节。如果为nil,则初始化向量为0
@return 加密结果为base64编码
*/
- (NSString *)aesEncryptWithHexKey:(NSString *)key hexIv:(NSString *)iv;
/**
AES-CBC模式加密,默认模式
@param key 密钥支持128 192 256bit,16、24、32字节,长度错误将抛出异常
@param iv 进制字符串形式;初始化向量iv为16字节。如果为nil,则初始化向量为0
@return 加密结果为base64编码
*/
- (NSString *)aesEncryptWithKey:(NSString *)key iv:(NSString *)iv;
/**
AES-CBC模式加密,默认模式
@param data 要加密的数据
@param key 密钥支持128 192 256bit,16、24、32字节,长度错误将抛出异常
@param iv 初始化向量iv为16字节。如果为nil,则初始化向量为0
@return 加密结果为NSData形式
*/
- (NSData *)aesEncryptWithDataKey:(NSData *)key dataIv:(NSData *)iv;
/**
AES-CBC模式解密,要求NSString为base64的结果
@param key 密钥支持128 192 256bit,16、24、32字节,长度错误将抛出异常
@param iv 进制字符串形式;初始化向量iv为16字节。如果为nil,则初始化向量为0
*/
- (NSString *)aesBase64StringDecryptWithHexKey:(NSString *)key hexIv:(NSString *)iv;
/**
AES-CBC模式解密
@param key 密钥支持128 192 256bit,16、24、32字节,长度错误将抛出异常
@param iv 初始化向量iv为16字节。如果为nil,则初始化向量为0
*/
+ (NSData *)aesDecryptWithData:(NSData *)data dataKey:(NSData *)key dataIv:(NSData *)iv;
三、RSA非对称加密
关于介绍,之前的博客已经给出,具体可以参考:网络安全——数据的加密与签名,RSA介绍
openssl 生成的密钥PEM文件为Base64编码(这里的Base64格式,长度超过64字符插有换行,生成的私钥为PKCS#1格式),下面是具体的openssl生成公私钥步骤:
- 1 生成私钥,1024bit,PKCS1Padding格式,Base64编码
命令行:openssl genrsa -out rsa_private_key.pem 1024
结果如下:
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQDOxoZIsFbFMeR0OWnc/sF5A3Gj0BWsoClQW3BKgvMQ85ZXVCM6
7g6XItl5sSW2EyMaIeQ8tRsM0HI4oCvlOMjSVgdyZmqbUfaZDoDYPW2pDbLqMDr/
o1eKxYpssbAyH6ZDyJeTOEu9yF7XUsIilokzc0D9i+uPc8yp/vLYTPDJEQIDAQAB
AoGAFUMevcy8L2zQ9A6PTzU3Cc2L2u9juyuA9A1i/5Z1jhGuLO6u7Llb8LiZqkTH
/u/61Q4VHRT2YhvxEteNi/WJ2L+1wTZYWbE/NIHBls4dTDt4aiMGUG2y6uBcFPmB
97sjT3ofcOHVZuFc80ktyhVuvx5osB8obZHbjn+3hn/pIF0CQQDx1bollu3XXL08
YJrS1mpB3F/87HXcxDa0dWUoqBRUCPjqC+8SuxaddPK6RFvkb1UyWJNzQ5Mb3OZt
65/sipdDAkEA2uMWf0ukTRhxiEYhZIJDSaERYeaWFU+mc6mC2//Tcvy7hldBe15n
7UQNKWl7DbI3Z7NmuKPa+rWqwASqtBAHGwJAOav7iW1V6Q8fvd9X7MHfczdn2LxX
Wz+bwCti5XA38NZ27fHMoM3nFcPHAu68b1yxl6ESAOHzmihy93HCoLloWwJARodX
j2rTJRhUNMHMLrOedNIWZMJE59cDXk9nX/X9rxZqYi4pZlQUDqqXxxk60j3zhlGT
Lrl1bMUuoLKgQmbLswJAIfv1Vw18YcEexWPBkn5iKufu0Fo7+Z776lDLYP1kNyQZ
eohofAAWYNQvHZ4WTpiIxi2FZ9xIRu+M7smsIs0h2g==
-----END RSA PRIVATE KEY-----
- 2 根据上面的私钥生成公钥
命令行:openssl rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout
结果如下:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOxoZIsFbFMeR0OWnc/sF5A3Gj
0BWsoClQW3BKgvMQ85ZXVCM67g6XItl5sSW2EyMaIeQ8tRsM0HI4oCvlOMjSVgdy
ZmqbUfaZDoDYPW2pDbLqMDr/o1eKxYpssbAyH6ZDyJeTOEu9yF7XUsIilokzc0D9
i+uPc8yp/vLYTPDJEQIDAQAB
-----END PUBLIC KEY-----
- 3 将私钥生成pkcs8格式,可在iOS工程中直接使用
openssl pkcs8 -topk8 -in rsa_private_key.pem -out pkcs8_rsa_private_key.pem -nocrypt
结果:
-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAM7GhkiwVsUx5HQ5
adz+wXkDcaPQFaygKVBbcEqC8xDzlldUIzruDpci2XmxJbYTIxoh5Dy1GwzQcjig
K+U4yNJWB3JmaptR9pkOgNg9bakNsuowOv+jV4rFimyxsDIfpkPIl5M4S73IXtdS
wiKWiTNzQP2L649zzKn+8thM8MkRAgMBAAECgYAVQx69zLwvbND0Do9PNTcJzYva
72O7K4D0DWL/lnWOEa4s7q7suVvwuJmqRMf+7/rVDhUdFPZiG/ES142L9YnYv7XB
NlhZsT80gcGWzh1MO3hqIwZQbbLq4FwU+YH3uyNPeh9w4dVm4VzzSS3KFW6/Hmiw
HyhtkduOf7eGf+kgXQJBAPHVuiWW7ddcvTxgmtLWakHcX/zsddzENrR1ZSioFFQI
+OoL7xK7Fp108rpEW+RvVTJYk3NDkxvc5m3rn+yKl0MCQQDa4xZ/S6RNGHGIRiFk
gkNJoRFh5pYVT6ZzqYLb/9Ny/LuGV0F7XmftRA0paXsNsjdns2a4o9r6tarABKq0
EAcbAkA5q/uJbVXpDx+931fswd9zN2fYvFdbP5vAK2LlcDfw1nbt8cygzecVw8cC
7rxvXLGXoRIA4fOaKHL3ccKguWhbAkBGh1ePatMlGFQ0wcwus5500hZkwkTn1wNe
T2df9f2vFmpiLilmVBQOqpfHGTrSPfOGUZMuuXVsxS6gsqBCZsuzAkAh+/VXDXxh
wR7FY8GSfmIq5+7QWjv5nvvqUMtg/WQ3JBl6iGh8ABZg1C8dnhZOmIjGLYVn3EhG
74zuyawizSHa
-----END PRIVATE KEY-----
可以在终端对"123"RSA加密,由于使用PKCS#1生成随机码,所以每次加密结果会不一样
echo "123" | openssl rsautl -encrypt -inkey rsa_public_key.pem -pubin | Base64
加密结果(Base64):
ZDBtICMxy2JHg6QDqolyAeqBRMseqJQ33tYQRE26c69/dGlS3TJ2xzMRZlsww+NnQH48KVthyCJ6nIhgAvhmAOaG+MvMqhZT/G180euH3OfLX8/VcIWqelxm8IYzA3NRD8n2jWbWoxZHh8Sp3n+YM7vor+8Q3SsFXMuurwT+xPI=
例程RSA加密使用了第三方框架,链接如下:https://github.com/ideawu/Objective-C-RSA,在使用时公钥可以直接使用,私钥需要使用pkcs8格式。公私钥可以加-----BEGIN PRIVATE KEY-----
与-----END PRIVATE KEY-----
,也可以不加,程序会自动处理。
四、实际使用
选择哪种算法当然是根据自己的需求来定
- 如果不是关键的数据可以使用DES加密,或者Base64编码不直接看到数据即可,这样速度快
- 稍微重要的数据,可以用AES加密,一定要保护好密钥
- 关于钱、用户登陆之类的比较重要,数据量也少,可以使用RSA加密
另外,我们也可以对称加密和非对称加密结合使用,对数据进行AES或DES加密,AES或DES的密钥随机生成,并使用RSA将其加密。对方收到信息后,先RSA解密得到密钥,然后在解密得到加密的数据。这样的话,随机算法就比较重要。
五、关于Padding
- 数据长度
AES和DES在ECB或者CBC模式下,要加密的数据必须是分组长度的整数倍,比如AES是128位16字节,而DES是64位8字节,那么加密数据必须是16(AES)或者8(DES)的整数倍,如果不是那么就需要填充(pad)。
- 密钥长度
不像数据长度必须是block的整数倍,密钥长度是固定的。
AES有三种:128、192、256bit
pad的方式有很多种,而且你也可以自定义,用的比较多的有PKCS7Padding、PKCS1Padding和PKCS5Padding。
- PKCS7Padding:用十六进制0x07来填充,下面为一个简单的实现方法(其实很多加密工具已经实现,这里只是举个例子)
// plainData为要加密的数据,“16”是block大小
while (plainData.length % 16 != 0) {
// PKCS7Padding模式
Byte PKCS7Pad = 0x07;
[plainData appendData:[[NSData alloc] initWithBytes:&PKCS7Pad length:1]];
}
- PKCS5Padding:稍麻烦一点,比如需要填充7个字节就填充0x07,需要填充6个字节就是0x06。。。需要填充1个字节就是0x01
加解密双方必须使用相同的方式,不然解密就会失败。
关于电脑终端Openssl加密解密命令
对"123"加密,密钥为"30313233343536373839414243444546"(16进制,对应ASCII码为0~F)
,初始化向量为"30313233343536373839414243444546"(16进制,对应ASCII码为0~F)
echo -n "123" | openssl enc -aes-128-cbc -a -A -K 30313233343536373839414243444546 -iv 30313233343536373839414243444546
下面对参数做说明:
echo -n "123" |
:输出123且不换行,“|”是管道符号,将前面的输出作为后面的输入,即"123"作为后面要加密的数据。openssl命令是对文件加密,这样做好处是直接可以对字符串加密。enc
:对称加密-aes-128-cbc
:算法名字模式-a
:加密结果进行base64编码-A
:输出不换行,默认情况下,base64编码结果换行-K
:后面跟密钥,16进制形式-iv
:初始化向量(CBC模式有)
如果想对openssl有更详细的了解,可以参考 赵春平写的《Openssl编程》里面有很多实用东西,另外也将书的pdf格式上传到了github工程里面,链接见文章最后
When I see you again(加密原理介绍,代码实现DES、AES、RSA、Base64、MD5)的更多相关文章
- 加密原理介绍,代码实现DES、AES、RSA、Base64、MD5
阅读目录 github下载地址 一.DES对称加密 二.AES对称加密 三.RSA非对称加密 四.实际使用 五.关于Padding 关于电脑终端Openssl加密解密命令 关于网络安全的数据加密部分, ...
- Java实现SSH模式加密原理及代码
一.SSH加密原理 SSH是先通过非对称加密告诉服务端一个对称加密口令,然后进行验证用户名和密码的时候,使用双方已经知道的加密口令进行加密和解密,见下图: 解释:SSH中为什么要使用非对称加密,又使用 ...
- (转)DES、RSA、MD5、SHA、随机生成加密与解密
一.数据加密/编码算法列表 常见用于保证安全的加密或编码算法如下: 1.常用密钥算法 密钥算法用来对敏感数据.摘要.签名等信息进行加密,常用的密钥算法包括: DES(Data Encr ...
- DES、RSA、MD5、SHA、随机生成加密与解密
一.数据加密/编码算法列表 常见用于保证安全的加密或编码算法如下: 1.常用密钥算法 密钥算法用来对敏感数据.摘要.签名等信息进行加密,常用的密钥算法包括: DES(Data Encr ...
- asp.netcore mvc 防CSRF攻击,原理介绍+代码演示+详细讲解
一.CSRF介绍 1.CSRF是什么? CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session ridin ...
- Base64加密解密原理以及代码实现(VC++)
Base64加密解密原理以及代码实现 转自:http://blog.csdn.net/jacky_dai/article/details/4698461 1. Base64使用A--Z,a--z,0- ...
- 密码学——网间数据加密传输全流程(SSL加密原理)
0.导言 昨天写了一篇关于<秘钥与公钥>的文章,写的比较简单好理解,有点儿像过家家,如果详细探究起来会有不少出入,今天就来详细的说明一下数据加密的原理和过程.这个原理就是大名鼎鼎SSL的加 ...
- 一篇读懂HTTPS:加密原理、安全逻辑、数字证书等
1.引言 HTTPS(全称: Hypertext Transfer Protocol Secure,超文本传输安全协议),是以安全为目标的HTTP通道,简单讲是HTTP的安全版.本文,就来深入介绍下其 ...
- android黑科技系列——分析某直播App的协议加密原理以及调用加密方法进行协议参数构造
一.前言 随着直播技术火爆之后,各家都出了直播app,早期直播app的各种请求协议的参数信息都没有做任何加密措施,但是慢慢的有人开始利用这个后门开始弄刷粉关注工具,可以让一个新生的小花旦分分钟变成网红 ...
随机推荐
- 使用EntityFramework6连接MySql数据库(code first方式)
demo托管地址:http://git.oschina.net/uustudy/ASP.NET-CodeFirst-MySQL-Demo.git 之前的是db first(地址:http://www. ...
- ENode框架单台机器在处理Command时的设计思路
设计目标 尽量快的处理命令和事件,保证吞吐量: 处理完一个命令后不需要等待命令产生的事件持久化完成就能处理下一个命令,从而保证领域内的业务逻辑处理不依赖于持久化IO,实现真正的in-memory: 保 ...
- H5嵌入原生开发小结----兼容安卓与ios的填坑之路
一开始听说开发H5,以为就是做适配现代浏览器的移动网页,心想不用管IE了,欧也.到今天,发现当初too young too simple,兼容IE和兼容安卓与IOS,后者让你更抓狂.接下来数一下踩过的 ...
- [WinAPI] 获取窗口句柄的几种方法
1.使用FindWindow函数获取窗口句柄 示例:使用FindWindow函数获取窗口句柄,然后获得窗口大小,并且移动窗口到指定位置. 我们想获得酷我音乐盒的窗口句柄并移动它,该怎么办呢? 首先打开 ...
- Jvm --- 常用工具
jps:虚拟机进程状况工具 JVM Process Status Tool. 可以列出所有目前正在运行虚拟机的进程. jps -l 详细参数: -q 输出LVMID,省略主类名称 -m 输出虚拟机进程 ...
- 「标准」的 JS风格
首先,这份 JS风格指南已经在我司的前端团队实行半年多了: 其次,在程序员的世界里,从入行到资深都需要面对几个世界级的难题,如: 世界上最好的编辑器是什么? 是用空格还是 TAB?用空格还特么衍生出 ...
- 创建DbContext
返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 上一篇介绍了<创建实体>,这一篇我们顺其自然地介绍<创建DbContext>. 温故: 提到DbConte ...
- jQuery选择器中,通配符[id^='code']input[id$='code'][id*='code']
1.选择器 (1)通配符: $("input[id^='code']");//id属性以code开始的所有input标签 $("input[id$='code']&qu ...
- Android开发学习之路-插件安装、检查应用是否安装解决方案
使用Bmob的时候,如果需要用到支付功能,就需要让应用去安装一个支付插件.而一般的做法是将插件放置在assets目录中,当用户需要支付,先检查是否能支付,不能的话,提示安装插件.代码: public ...
- iOS集成sharesdk遇到的坑
分享新浪微博 ★★★分享新浪微博★★★ 前言: 写这个目地是为了记录那些过坑,直接先上效果图.大家看看如果你遇到了应该如果处理更好,因为刚一看到这个效果的时候就明白其实很简单不就是分享微博吧.但是要求 ...