加密算法
简单来讲, 所有的加密算法都是依托于强大的数学基础之上的上层建筑, 关于主要的加密算法以及各种验证流程, 以下这篇文章有兴趣的可好好尝试一番 数学验证
HASH加密
哈希函数加密算法无需借助任何秘钥,Hash算法严格上来说并不属于加密算法,而是与加密算法属于并列关系的一种算法。 概括来说,哈希(Hash)是将目标文本转换成具有相同长度的、不可逆的杂凑字符串(或叫做消息摘要),而加密(Encrypt)是将目标文本转换成具有不同长度的、可逆的密文。
在开发中我们要遵循的基本原则就是:
- 不可以在本地保存用户的明文隐私信息
- 不可以在网络中传入用户的明文隐私信息
算法特点:
- 算法公开
- 相同的数据加密结果一样, 不同的数据加密结果可能一样.
- 不同的数据加密结果一样, 加密的结果长度是一样的.
- 不可逆运算.
常用种类
- MD5, RIPEMD-160
- SHA1
- 不同的数据加密结果一样, 加密的结果长度是一样的.
- 不可逆运算.
MD5
MD5即Message-Digest Algorithm 5(信息摘要算法5), 用于确保信息传输完整一致.是计算机广泛使用的散列算法之一(译摘要算法, 哈希算法). 将数据运算为一个固定长度的数值,是散列算法的基本原理. MD5的前身有MD4,MD3和MD2.
MD5是输入不定长的信息, 输出固定长度128-bits的算法. 最后是生成32位16进制的字符, 联合起来成为一个128-bits的散列. 基本方式为,求余、取余、调整长度、与链接变量进行循环运算。得出结果。
- 从两个角度理解MD5不可逆, 且相对安全
- 最简单的理解就是, 10 mod 3 = 1. 1就是MD5加密后的结果, 3就认为一个不变的除数, 10就是我们输入的可变信息, 所以不管我们输入10, 7, 4等等都可以得到1.而我们知道1和3, 却不能反算出到底是4, 7, 10, 13等等.
- 第二个就是MD5输出只有128比特, 2的128次方个数据, 但是输入的数据是无限的.所以无限的数据经过换算得到一个有限的结果, 结果就一定会产生冲突, 所以得到一个结果无法准确的得到输入数据.
- 衡量一个好的哈希算法的时候, 更小的哈希冲突是一个非常重要的标准, 但是加密的韩系函数和我们数据结构中学的哈希并不是一样的. 数据结构中的哈希设计目的主要是快速查找,并非安全性. 而密码学中的哈希加密主要是为了安全性(可参考欧拉函数x^n mod y = z, xy互为质数, z的结果很好的分散了哈希,简单的认知).
MD5在OC中的代码调用
在OC中CommonCrypto库中有CC_MD5的方法可供调用:
使用的时候, 加入头文件 #import <CommonCrypto/CommonCrypto.h>
函数定义
extern unsigned char *CC_MD5(const void *data, CC_LONG len, unsigned char *md)
const void *data; 数据的指针
CC_LONG len; 数据的长度
unsigned char *md; 结果的指针
YY作者在YYDiskCache中的调用:
CC_MD5_DIGEST_LENGTH = 16;
static NSString *_YYNSStringMD5(NSString *string) {
if (!string) return nil;
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5(data.bytes, (CC_LONG)data.length, result);
return [NSString stringWithFormat:
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
result[0], result[1], result[2], result[3],
result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11],
result[12], result[13], result[14], result[15]
];
}
abc1123加密的MD5为:fdc860609fd2d8c39ebbba81ab0b79e8
a加密的MD5为: 0cc175b9c0f1b6a831c399e269772661
字符串abc1123和a的加密结果均为16个字节, 结果的长度总是一样.
MD5的主要用途
- 一致性验证, 从网上下载各种资料,有些文件会提供MD5的文件信息, 可以利用MD5的效验软件来对文件进行效验, 从而得知文件是否与传输的一致. MD5的文件效验, 在数据库, 下载, 系统安全, 图片下载包括水印等等应用场景非常多.
- 数字证书, 对一段txt文件进行MD5加密,获取一个文件的MD5值, 获取到文件之后对文件进行MD5的效验就可以知道文件是否被篡改. 如果有个第三方机构对HASH值进行验证, 就叫所谓的数字签名.
- 密码加密, 只需要对密码的MD5进行验证即可, 不需要知道明文密码.
- 鉴权协议
- 09年已被破解
MD5的16, 32, 128位?
网上很多人说MD5是128位, 16位, 32位等等.
实际上MD5是生成128位二进制位, 相当于32个16进制位, 相当于16个字节(1个字节=8个bit位).
比如a的MD5加密结果是: 0cc1 75b9 c0f1 b6a8 31c3 99e2 6977 2661,在8个字节表示的时候用: c0f1 b6a8 31c3 99e2, 前面去8位,后面去8位的形式表示.
所以归根结底都是一套算法, 最后的展现形式是由32或者16个16进制表示.
MD5不可破解?以及安全性
MD5不可逆, 所以反向破解不可能实现, 但是如果暴力破解对比hash还是有可能破解的.
反向查询网站cmd5
所以MD5单独使用的话, 可以加盐, 或者动态盐提高安全程度. 参考 MD5的安全性文中写到10年以前MD5已经被破解, 所以目前并不适用真正的安全环境, 可以做一些文件错误检查,下载完整性之类的应用.
SHA-1
SHA-1在许多安全协议中广为使用,包括TLS和SSL、PGP、SSH、S/MIME和IPsec,曾被视为是MD5(更早之前被广为使用的散列函数)的后继者。但SHA-1的安全性如今被密码学家严重质疑 维基百科 可以看一下维基百科, 里面说了SHA-0和SHA-1的破解, SHA-0大概在05年,SHA-1大概在17年.
SHA-2
SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256并称为SHA-2
SHA-1在17年被谷歌等大部分顶尖巨头弃用了, 所以目前SHA2和3在安全应用上应该比SHA1要多, 发展肯定都是向更高效和更安全的对齐
语言不多,但是224,256, 384, 512的区别讲的挺清晰的. 百科
SHA-3
SHA-3,之前名为Keccak算法,是一个加密杂凑算法。百科
SHA-3并不是要取代SHA-2,因为SHA-2目前并没有出现明显的弱点。 从百科中的图对比了SHA家族的不同:
根据图中所示, 目前我们在选择SHA的时候, 选择SHA2中的SHA-256应用最为合适.
终端示例: SHA-1加密结果为20个字节, 160位.
SHA-256加密结果为32个字节, 256位.
SHA-256加密结果为64个字节, 512位.
RipeMD-160,320
RIPEMD-160 是一个 160 位加密哈希函数。百科
它旨在用于替代 128 位哈希函数 MD4、MD5 和 RIPEMD。
RIPEMD 是在 EU 项目 RIPE(RACE Integrity Primitives Evaluation,1988-1992)的框架中开发的。
百科中比较核心点的意思就是, RipeMD是基于MD4的基础上开发的, 不管是160还是320只是减少了碰撞, 并没有提高安全性, 算法基本一致输出不一致, 大致了解一下即可, 基本不用.
WHIRLPOOL
WHIRLPOOL是基于分组密码的散列算法,与AES的Rijndael算法非常相似。 不过因为Whirlpool的分组长度和密钥均为512比特,所以效率是AES-128算法的一半。 Whirlpool算法具有强大的安全性,被国际标准组织ISO和国际电子技术协会IEC采用作为ISO/IEC 10118-3国际标准。
Whirlpool算法是由Vincent Rijmen和Paulo S.L.M.Barreto于2000年提出的,号称最安全的摘要算法,其摘要长度为512位,已被列入ISO标准。从发布至今共经历了三个版本,分别为whirlpool-O、Whirlpool-T和Whirlpool。
加密框架除支持标准的摘要长度为512位的Whirlpool算法i外,还支持摘要长度分别为256和384位的Whirlpool算法,分别记为wp512、wp256和wp384,其实现代码为wp512.c。
既然是号称最安全的摘要算法(光看下面终端加密的结果长度就能知道他为什么敢号称了)了解一下,github上很多可以随便找找看看.wp512.c
其他的哈希加密函数
仅标准的密码哈希函数就有Argon2、 bcrypt 、 scrypt 或 PBKDF2 。所有的加密方式, 需要在项目中实际使用的时候在深入进行研究吧, 不然世界这么大, 知识也是学不完的
我应该使用什么样的哈希算法?(摘抄自 如何正确对用户密码进行加密?)
可以使用:
精心设计的密钥扩展算法如 PBKDF2 、 bcrypt 和 scrypt 。 OpenWall 的的 Portable PHP password hashing framework 。 PBKDF2 在 PHP、C#、Java 和 Ruby 的实现。 crypt 的安全版本。
不可使用:
快速加密哈希函数,如 MD5 、SHA1、SHA256、SHA512、RipeMD、WHIRLPOOL、SHA3 等。
crypt() 的不安全版本。
任何自己设计的加密算法。只应该使用那些在公开领域中的、由经验丰富的密码学家完整测试过的技术。
原文中里面提到了一种奇特的破解方式, 大致的意思就是, 根据每一次登录比较的时间可以一个一个获取对应的字符, 并且已经被认定可行有兴趣可自行查看.
原文:
首先攻击者准备 256 个字符串,它们的哈希值的第一字节包含了所有可能的情况。他将每个字符串发送给在线系统尝试登陆,并记录系统响应所消耗的时间。耗时最长的字符串就是第一字节相匹配的。攻击者知道第一字节后,并可以用同样的方式继续猜测第二字节、第三字节等等。一旦攻击者获得足够长的哈希值片段,他就可以在自己的机器上来破解,不受在线系统的限制。
OC中的SHA的使用
CommonCrypto框架中的CC_SHA1, 224, 256, 384,512算法 代码中的简单调用, 对应的点击CC_SHA512去切换对应的长度就行, 都是系统级的定义不会有错.
不管是任何加密, 单一使用都是不安全的, 所谓的安全是相对安全, 只有多种加密方案结合, 才能做到相对的绝对安全.
HAMC和PBKDF2
HAMC
HMAC密钥散列消息认证码(英语:Keyed-hash message authentication code),又称散列消息认证码. 是一种通过特别计算方式之后产生的消息认证码(MAC),使用密码散列函数,同时结合一个加密密钥。它可以用来保证资料的完整性,同时可以用来作某个消息的身份验证。 首先看一下OC中的定义:
看一下HMAC的参数:
- CCHmacAlgorithm:选择一种摘要, 证明HAMC必须要使用一种摘要算法, 内部枚举有六种,SHA1, SHA2和MD5.
- key: 选择一个key, 证明HMAC必须要一个密钥, 系统默认为64个16进制字符也就是32字节,不同的加密算法, 要求key的长度不同, 系统定义的宏都有对应的长度.
- 剩余的参数应该都清楚了, 长度, 数据, 数据长度, 输出结果的指针. 在代码中的使用:
所以从代码来看, HMAC本质上就是将一个key混入摘要的一种算法.输出的长度和原加密结果长度一致
验证哈希值时,需要原始的输入数据和key。
从命令中openssl dgst -sha256 -hmac "key"中就可以看出, dgst -sha256代表的是哈希加密的算法模式的结果给到hamc, -hmac是加密方案需要一个key的参数, 对应了上面所说的hamc的本质.
PBKDF
PBKDF2将伪随机函数(例如基于哈希的消息认证代码(HMAC))与盐值一起应用于输入密码或密码短语,并重复多次此过程以生成派生密钥,然后可以将该密钥用作加密密钥在后续操作中。增加的计算工作使密码破解变得更加困难,这被称为密钥扩展。
OC代码中的PBKDF 先上图:
是一种用来密钥扩展的算法.
PBKDF2主要是通过一个伪随机函数导出密钥,导出的密钥的长度本质上是没有限制的,但是可以设置进行多次计算。将明文和一个盐值作为参数,最后生成密钥。加盐之后生成的密钥可以增加抗碰撞性,大大加强了抵御“彩虹表”的攻击能力。
CommonKeyDerivation库中CCPseudoRandomAlgorithm的枚举包含了, kCCPRFHmacAlgSHA1 = 1, kCCPRFHmacAlgSHA224 = 2, kCCPRFHmacAlgSHA256 = 3, kCCPRFHmacAlgSHA384 = 4, kCCPRFHmacAlgSHA512 = 5,五种哈希加密方案可供使用.
一个加密的三方框架RNCryptor可以了解一下
对称加密
对称加密是一种最快速, 简单的加密模式, 加密和解密都是使用同一种密钥. 对称加密有很多种算法, 由于效率很高,被经常使用于多种加密协议核心中.本文主要讨论AES和DES.
实际使用中, 对称加密最核心的问题就是密钥的传递
文章开头已经说过了, 所有的加密算法都是基于强大的数学基础, 如果有兴趣的可以自行翻阅查找, 这里只是对经常用到的做一个记录.
工作模式
优先对称密钥加密设计的块密码工作模式要求输入明文长度必须是块长度的整数倍,因此信息必须填充至满足要求。
对称加密模式 主要对称加密模式,分别是:
- ECB(电子密码本模式)
-
- 每8个字符(64位)作为一块,然后使用一个相同的64位的密钥对每个块进行加密,最后一块不足64位,就补齐后再进行加密. 相互独立, 每一块加密结果不受到其他加密结果的影响, 各自为营.
-
- 因为每一块都是用同样的密钥进行加密的, 所以非常容易获取密文进行破解, 因为每一块都是相互独立的, 有时候可以替换掉其中一块也可以打到目的.优点就是简单快捷(因为每一段都是相对独立的, 在已知填充模式的情况下, 可以并行解密出结果)
- CBC(密码链式模式)
-
- 每一段密文是前一段加密块的密文与下一块要加密的明文进行异或运算, 将计算结果用密钥在进行加密, 由于第一段密文前面没有所以需要一个初始化向量,OC中默认为8个字节.
-
- 由于加密的原因, 所以在解密的时候就必须要等待前一段密文加密成功之后才能解密后一段密文.由于必须要接受长度够了之后才能解密所以整体效率偏低.
-
- 如果实时性要求比较高, 场景就不一定适用了.
- CFB(加密反馈模式)
-
- 主要就是加了一个寄存器,处理CBC模式必须要拿到一定长度后才能解密的问题.文中写到由于一个比特错误就影响到8个字节(64个比特)的正确结果,导致鲁棒性太差,所以就又提出了下面的加密模式OFB。
- OFB(输出反馈模式)
-
- 主要是为了解决CFB的模式产生的, 在本模式下,如果一个比特发生错误了,那么只会影响其本身对应的一个比特,而不会影响别的。但是相对于其它模式,因为数据之间相关性小,这种加密模式是比较不安全的,所以在应用的时候除非特别需要,一般不提倡应用OFB模式。
- CTR(计数器模式)
-
- 大致知道概念, 没有具体了解 后面三种有兴趣可以自己查一查详细的资料
填充
分组加密模式中,有些情况下无法进行流加密,这个时候就需要对明文数据分组,最后不满足的块长度要求的就要进行填充 对于CBC,EBC是要填充的,CFB,OFB等是不需要填充的.
每种填充模式不同, 对明文的要求不同,加密后的数据长度不同.填充了解
看一下OC中的对称加密
同样是 #import <CommonCrypto/CommonCrypto.h> 框架内部的CCCrypt函数, 看一下下图:
关于函数的使用看一下命名和注释应该都能理解, 重点看一下CCAlgorithm加密算法, 看看系统提供了多少种:
上图可知, 苹果一共提供了AES, DES, 3DES, CAST, RC4, RC2, Blowfish7中对称加密方案. 在使用中需要知道每一种加密方式的优劣点, 然后根据不同的场景有选取不同加密方式的能力就可以了.
重点了解一下DES和AES
DES/3DES
数据加密标准 DES(Data Encryption Standard) 数据加密标准 IBM提供的加密方案,98年后不断被破解,在使用过程中不安全,一般开发中不使用DES,DES更多出现在介绍或者案例,或者比较老的案例中。
AES
高级加密标准
AES出现的原因就是DES的不断产生的安全问题和3DES产生的效率低下问题.
- AES是目前使用最多的对称加密算法
- AES的优势之一是至今尚未被破解
- AES通常用于移动通信系统加密以及基于SSH协议的软件(比如SSH Client、SecureCRT)
AES是美国联邦政府采用的一种区块加密标准。
不带模式和填充来获取AES算法的时候,其默认使用ECB/PKCS5Padding。
写的太累了, 直接看看代码注释吧, 有兴趣的可以私聊我.
需要注意的是, 加解密的密钥key要一致, 向量iv要一致. 没有向量的时候默认为ECB模式, 有向量的时候为CBC模式.
DES是较旧的算法,而AES是高级算法,它比DES更快,更安全。
终端指令openssl可以执行很多加密命令, 网上有很多demo可以自行搜查.代码和终端对比就知道加解密是否正确了. 加密 解密
总结:
写的太多了有点乱, 没有时间整理检查, 仅此做一个记录, 有错误的地方欢迎指出讨论, 后续慢慢改正. 下一篇重点想聊一下, 非对称加密, 应用重签名, https等对加密方式的运用.