数据安全及各类加密算法对比

平时开发中不只会遇到各类须要保护用户隐私的状况,并且还有可能须要对公司核心数据进行保护,这时候加密隐私数据就成为了必要。然而市场上存在着各类各样的抓包工具及解密算法,甚至一些公司有专门的逆向部门,这就加大了数据安全的风险,本文将经过如下几个方面对各类加密算法进行分析对比:php

  • Base64编码(基础)
  • 单项散列函数 MD五、SHA一、SHA25六、SHA512等
  • 消息认证码 HMAC-MD五、HMAC-SHA1
  • 对称加密 DES|3DES|AES(高级加密标准)
  • 非对称加密 RSA
  • 数字签名
  • 证书

一般咱们对消息进行加解密有两种处理方式:css

  1. 只须要保存一个值,保证该值得机密性,不须要知道原文(用户登陆)
  2. 除了保证机密性外还须要对加密后的值进行解密获得原文

Base64编码

因为咱们可能对各类各样的数据进行加密,好比:视频、音频、文本文件等,因此加密以前咱们须要统一文件类型,而后再进行加密处理。git

  • Base64编码
// 要编码的字符串
NSString *str = @"haha";

// 转换成二进制文件
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];

// 进行base64编码
NSString *dataStr = [data base64EncodedStringWithOptions:kNilOptions];

NSLog(@"%@", dataStr);复制代码
  • Base64解码
// 先对数据进行解码
NSData *encData = [[NSData alloc]initWithBase64EncodedString:dataStr options:kNilOptions];
    
// 将二进制数据转换成字符串
NSString *encStr = [[NSString alloc]initWithData:encData encoding:NSUTF8StringEncoding];
    
NSLog(@"%@", encStr);复制代码

接下来分析一下Base64的编码过程,参考维基百科:github

image

若是要编码的字节数不能被3整除,最后会多出1个或2个字节,那么可使用下面的方法进行处理:先使用0字节值在末尾补足,使其可以被3整除,而后再进行Base64的编码。在编码后的Base64文本后加上一个或两个=号,表明补足的字节数。也就是说,当最后剩余两个八位字节(2个byte)时,最后一个6位的Base64字节块有四位是0值,最后附加上两个等号;若是最后剩余一个八位字节(1个byte)时,最后一个6位的base字节块有两位是0值,最后附加一个等号。 参考下表:算法

image
  • Base64编码原理
  1. 将全部字符串转换成ASCII码
  2. 将ASCII码转换成8位二进制
  3. 将二进制三位归成一组(不足三位在后边补0),再按每组6位,拆成若干组
  4. 统一在6位二进制后不足8位的补0
  5. 将补0后的二进制转换成十进制
  6. 从Base64编码表取出十进制对应的Base64编码

若原数据长度不是3的倍数时且剩下1个输入数据,则在编码结果后加2个=;若剩下2个输入数据,则在编码结果后加1个=数据库

如上面的例子:浏览器

原数据为A,数据长度为1,1 % 3 = 1 后面加两个==安全

原数据为bc,数据长度为2,2 % 3 = 2 后面加一个=服务器

  • Base64编码的特色
  1. 能够将任意的二进制数据进行Base64编码。
  2. 全部的数据都能被编码为并只用65个字符就能表示的文本文件。
  3. 编码后的65个字符包括AZ,az,0~9,+,/,=
  4. 对文件或字符串进行Base64编码后将比原始大小增长33%。
  5. 可以逆运算
  6. 不够安全,但却被不少加密算法做为编码方式

单项散列函数

单向散列函数也称为消息摘要函数、哈希函数或者杂凑函数。
单向散列函数输出的散列值又称为消息摘要或者指纹微信

特色:

  1. 对任意长度的消息散列获得散列值是定长的
  2. 散列计算速度快,很是高效
  3. 消息不一样,则散列值必定不一样
  4. 消息相同,则散列值必定相同
  5. 具有单向性,没法逆推计算

经典算法:

  • MD四、MD五、SHA一、SHA25六、SHA512等

安全性:

  • md5解密网站:www.cmd5.com
  • MD5的强抗碰撞性已经被证明攻破,即对于重要数据不该该再继续使用MD5加密。

疑问一:单项散列函数为何不可逆??

原来好多同窗知识知道md5加密是不可逆的,殊不知道是为何,其实散列函数能够将任意长度的输入通过变化获得不一样的输出,若是存在两个不一样的输入获得了相同的散列值,咱们称之为这是一个碰撞,由于使用的hash算法,在计算过程当中原文的部分信息是丢失了的,一个MD5理论上能够对应多个原文,由于MD5是有限多个,而原文是无限多个的。

网上看到一个形象的例子:2 + 5 = 7,可是根据 7 的结果,却并不能推算出是由 2 + 5计算得来的

疑问二:为何有些网站能够解密MD5后的数据??

MD5解密网站,并非对加密后的数据进行解密,而是数据库中存在大量的加密后的数据,对用户输入的数据进行匹配(也叫暴力碰撞),匹配到与之对应的数据就会输出,并无对应的解密算法。

MD5改进

由以上信息能够知道,MD5加密后的数据也并非特别安全的,其实并无绝对的安全策略,咱们能够对MD5进行改进,加大破解的难度,典型的加大解密难度的方式有一下几种:

  1. 加盐(Salt):在明文的固定位置插入随机串,而后再进行MD5
  2. 先加密,后乱序:先对明文进行MD5,而后对加密获得的MD5串的字符进行乱序
  3. 先乱序,后加密:先对明文字符串进行乱序处理,而后对获得的串进行加密
  4. 先乱序,再加盐,再MD5等
  5. HMac消息认证码

也能够进行屡次的md5运算,总之就是要加大破解的难度。

Hmac消息认证码(对MD5的改进)

原理:

  1. 消息的发送者和接收者有一个共享密钥
  2. 发送者使用共享密钥对消息加密计算获得MAC值(消息认证码)
  3. 消息接收者使用共享密钥对消息加密计算获得MAC值
  4. 比较两个MAC值是否一致

使用:

  1. 客户端须要在发送的时候把(消息)+(消息·HMAC)一块儿发送给服务器
  2. 服务器接收到数据后,对拿到的消息用共享的KEY进行HMAC,比较是否一致,若是一致则信任
image

对称加密算法

对称加密的特色:

  • 加密/解密使用相同的密钥
  • 是可逆的

经典算法:

  • DES 数据加密标准
  • 3DES 使用3个密钥,对消息进行(密钥1·加密)+(密钥2·解密)+(密钥3·加密)
  • AES 高级加密标准

密码算法能够分为分组密码和流密码两种:

  • 分组密码:每次只能处理特定长度的一zu数据的一类密码算法。一个分组的比特数量就称之为分组长度。
  • 流密码:对数据流进行连续处理的一类算法。流密码中通常以1比特、8比特或者是32比特等做为单位俩进行加密和解密。

分组模式:主要有两种

  • ECB模式(又称电子密码本模式)
    • 使用ECB模式加密的时候,相同的明文分组会被转换为相同的密文分组。
    • 相似于一个巨大的明文分组 -> 密文分组的对照表。
image

某一块分组被修改,不影响后面的加密结果

  • CBC模式(又称电子密码链条)

    • 在CBC模式中,首先将明文分组与前一个密文分组进行XOR(异或)运算,而后再进行加密。
    • 每个分组的加密结果依赖须要与前一个进行异或运算,因为第一个分组没有前一个分组,因此须要提供一个初始向量iv
    image

某一块分组被修改,影响后面的加密结果

代码演示两种分组模式

  • AES - ECB模式

加密:

/** * 加密字符串并返回base64编码字符串 * * @param string 要加密的字符串 * @param keyString 加密密钥 * @param iv 初始化向量(8个字节) * * @return 返回加密后的base64编码字符串 */
    NSLog(@"%@", [[EncryptionTools sharedEncryptionTools] encryptString:@"haha" keyString:@"abc" iv:nil]);
    
    // 输出 MIoAu+xUEpQZSUmkZUW6JQ==复制代码

解密:

NSLog(@"%@", [[EncryptionTools sharedEncryptionTools] decryptString:@"MIoAu+xUEpQZSUmkZUW6JQ==" keyString:@"abc" iv:nil]);
    
// 输出 haha复制代码
  • AES - CBC模式

加密:

uint8_t iv[8] = {1,2,3,4,5,6,7,8};

NSData *data = [[NSData alloc] initWithBytes:iv length:sizeof(iv)];

NSLog(@"%@", [[EncryptionTools sharedEncryptionTools] encryptString:@"haha" keyString:@"abc" iv:data]);
    
// 输出 E/wWqUTiw/E+1DThAzV39A==复制代码

解密:

NSLog(@"%@", [[EncryptionTools sharedEncryptionTools] decryptString:@"E/wWqUTiw/E+1DThAzV39A==" keyString:@"abc" iv:data]);
    
// 输出 haha复制代码

对称加密存在的问题??

很明显,对称加密主要取决于秘钥的安全性,数据传输的过程当中,若是秘钥被别人破解的话,之后的加解密就将失去意义

image

其实有点儿相似于咱们日常看的谍战类的电视剧,地下党将情报发送给后方,一般须要一个中间人将密码本传输给后方,若是中间人被抓交出密码本,那么未来全部的情报都将失去意义,因而可知情报工做多么的重要!!!

对称密码体制中只有一种密钥,而且是非公开的,若是要解密就得让对方知道密钥。因此保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就能够不须要像对称密码那样传输对方的密钥了

非对称加密

鉴于对称加密存在的风险,非对称加密应运而生

特色:

  • 使用公钥加密,使用私钥解密
  • 公钥是公开的,私钥保密
  • 加密处理安全,可是性能极差

非对称密码体制的特色:算法强度复杂、安全性依赖于算法与密钥,可是因为其算法复杂,而使得加密解密速度没有对称加密解密的速度快

经典算法:

  • RSA
RSA算法原理
* 求N,准备两个质数p和q,N = p x q
* 求L,L是p-1和q-1的最小公倍数。L = lcm(p-1,q-1)
* 求E,E和L的最大公约数为1(E和L互质)
* 求D,E x D mode L = 1复制代码
RSA加密实践
* p = 17,q = 19 =>N = 323
* lcm(p-1,q-1)=>lcm(1618)=>L= 144
* gcd(E,L)=1 =>E=5
* E乘以几能够mode L =1? D=29能够知足
* 获得公钥为:E=5,N=323
* 获得私钥为:D=29,N=323
* 加密 明文的E次方 mod N = 1235次方 mod 323 = 225(密文)
* 解密 密文的D次方 mod N = 22529次方 mod 323 = 123(明文)复制代码
openssl生成密钥命令
  • 生成强度是 512 的 RSA 私钥:$ openssl genrsa -out private.pem 512
  • 以明文输出私钥内容:$ openssl rsa -in private.pem -text -out private.txt
  • 校验私钥文件:$ openssl rsa -in private.pem -check
  • 从私钥中提取公钥:$ openssl rsa -in private.pem -out public.pem -outform PEM -pubout
  • 以明文输出公钥内容:$ openssl rsa -in public.pem -out public.txt -pubin -pubout -text
  • 使用公钥加密小文件:$ openssl rsautl -encrypt -pubin -inkey public.pem -in msg.txt -out msg.bin
  • 使用私钥解密小文件:$ openssl rsautl -decrypt -inkey private.pem -in msg.bin -out a.txt
  • 将私钥转换成 DER 格式:$ openssl rsa -in private.pem -out private.der -outform der
  • 将公钥转换成 DER 格式:$ openssl rsa -in public.pem -out public.der -pubin -outform der
非对称加密存在的安全问题

原理上看非对称加密很是安全,客户端用公钥进行加密,服务端用私钥进行解密,数据传输的只是公钥,原则上看,就算公钥被人截获,也没有什么用,由于公钥只是用来加密的,那还存在什么问题呢??那就是经典的中间人攻击

image

废了半天劲画的图,太low了,我仍是本身总结一遍吧!!!

中间人攻击详细步骤:

  1. 客户端向服务器请求公钥信息
  2. 服务端返回给客户端公钥被中间人截获
  3. 中间人将截获的公钥存起来
  4. 中间人本身伪造一套本身的公钥和私钥
  5. 中间人将本身伪造的公钥发送给客户端
  6. 客户端将重要信息利用伪造的公钥进行加密
  7. 中间人获取到本身公钥加密的重要信息
  8. 中间人利用本身的私钥对重要信息进行解密
  9. 中间人篡改重要信息(将给客户端转帐改成向本身转帐)
  10. 中间人将篡改后的重要信息利用原来截获的公钥进行加密,发送给服务器
  11. 服务器收到错误的重要信息(给中间人转帐)

疑问一:为何会形成中间人攻击??

形成中间人攻击的直接缘由就是客户端没办法判断公钥信息的正确性。

疑问二:怎么解决中间人攻击??

须要对公钥进行数字签名。就像古代书信传递,家人之因此知道这封信是你写的,是由于信上有你的签名、印章等证实你身份的信息。

数字签名须要严格验证发送发的身份信息!!!

数字证书

数字证书包含:

  • 公钥
  • 认证机构的数字签名(权威机构CA)

数字证书能够本身生成,也能够从权威机构购买,可是注意,本身生成的证书,只能本身承认,别人都不承认.

权威机构签名的证书:
GitHub官网为例,Chrome浏览器打开网址,地址栏有一个小绿锁,点击,内容以下:

权威机构认证的证书:

image

能够看到链接是安全的,点击证书能够看到详细信息


image

这是由权威机构认证的证书,可是是须要花钱的,一年至少得一两千,因此也有些公司用本身签名的证书,本身签名的证书不被信任,可能会提示用户有风险,好比原来的12306网站,如今大多数网站也都采用了CA签名数字证书进行签名,本身作签名的也很差找了!!!12306都改为CA认证的了。。。

本身生成一个证书

  • 生成私钥
openssl genrsa -out private.pem 1024复制代码
  • 建立证书请求
openssl req -new -key private.pem -out rsacert.csr复制代码
  • 生成证书并签名,有效期10年
openssl x509 -req -days 3650 -in rsacert.csr -signkey private.pem -out rsacert.crt复制代码
  • 将 PEM 格式文件转换成 DER 格式
openssl x509 -outform der -in rsacert.crt -out rsacert.der复制代码
  • 导出P12文件
openssl pkcs12 -export -out p.p12 -inkey private.pem -in rsacert.crt复制代码
image

注意:

  • 在iOS开发中,不能直接使用 PEM 格式的证书,由于其内部进行了Base64编码,应该使用的是DER的证书,是二进制格式的
  • OpenSSL默认生成的都是PEM格式的证书

代码演示:

// p12 是私钥
    // .der 是公钥
    // 非对称加密,使用公钥加密,私钥解密
    
    // 加载公钥
    [[RSACryptor sharedRSACryptor] loadPublicKey:[[NSBundle mainBundle] pathForResource:@"rsacert.der" ofType:nil]];
    
    // 对数据加密
    NSData *data = [[RSACryptor sharedRSACryptor] encryptData:[@"hahaha" dataUsingEncoding:NSUTF8StringEncoding]];
    
    // 对加密获得的密文进行base64编码打印
    NSLog(@"%@", [data base64EncodedStringWithOptions:kNilOptions]);
    
    // 输出结果:PflhCgTVNegcQXrb39RJOoxCRRIHuZ3LN0/hoxTDFBbC+8yKjp0m+/hxVUWBVsTo28WnNFCAFfrQ2of5SkqttD51a5eLb21R7bQSQRxg/gVZ5hePcE3vh7Slfcxm2qJM+J8hRWDP/MF4BiDLXI9ZqTpLCSS5mjJtmUBf2wNvI1Y=
    
    // 私钥解密
    
    // 加载私钥
    [[RSACryptor sharedRSACryptor] loadPrivateKey:[[NSBundle mainBundle] pathForResource:@"p.p12" ofType:nil] password:@"123456"];

    // 解密
    NSData *decryDeta = [[RSACryptor sharedRSACryptor] decryptData:data];
    
    NSLog(@"%@", [[NSString alloc] initWithData:decryDeta encoding:NSUTF8StringEncoding]);
    
    // 输出:hahaha复制代码

代码地址

总结

至此数据安全和加解密相关结算完毕,写博客的过程,也是学习的过程,断断续续的写了三四天,总算写完了,同时也对原来一些模糊的概念有了更清晰的认识,写的这篇文章看了文顶顶老师的视频,受益不浅,十分感谢,最近学习发现,学的越多,感受会的越少,时间十分的不够用。同时渴望遇到一些但愿进步、不甘平凡的同行!!!共勉!!!



做者:czj_warrior
连接:https://www.jianshu.com/p/b44927161081
此文章来源于第三方转载!!!

小编这呢,给你们推荐一个优秀的iOS交流平台,平台里的伙伴们都是很是优秀的iOS开发人员,咱们专一于技术的分享与技巧的交流,你们能够在平台上讨论技术,交流学习。欢迎你们的加入(想要进入的可加小编微信)。 13142121176

相关文章
相关标签/搜索