密码学是研究编制密码和破译密码的技术科学。研究密码变化的客观规律,应用于编制密码以保守通讯秘密的,称为编码学;应用于破译密码以获取通讯情报的,称为破译学,总称密码学。html
密码学的历史大体能够追溯到两千年前,相传古罗马名将凯撒大帝为了防止敌方截获情报,用密码传送情报。凯撒的作法很简单,就是对二十几个罗马字母创建一张对应表。这样,若是不知道密码本,即便截获一段信息也看不懂。git
从凯撒大帝时代到上世纪70年代这段很长的时间里,密码学的发展很是的缓慢,由于设计者基本上靠经验。没有运用数学原理。程序员
在1976年之前,全部的加密方法都是同一种模式:加密、解密使用同一种算法。在交互数据的时候,彼此通讯的双方就必须将规则告诉对方,不然无法解密。那么加密和解密的规则(简称密钥),它保护就显得尤为重要。传递密钥就成为了最大的隐患。这种加密方式被成为对称加密算法(symmetric encryption algorithm)github
1976年,两位美国计算机学家 迪菲(W.Diffie)、赫尔曼( M.Hellman ) 提出了一种崭新构思,能够在不直接传递密钥的状况下,完成密钥交换。这被称为“迪菲赫尔曼密钥交换”算法。开创了密码学研究的新方向,非对称加密算法(asymmetric cryptographic algorithm)算法
1977年三位麻省理工学院的数学家 罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一块儿设计了一种算法,能够实现非对称加密。这个算法用他们三我的的名字命名,叫作RSA算法。vim
若是让你设计一个加密容易,破解很难的算法,会想到什么呢? 方案: ,问x是多少? x可能的值为x=16k + 13,k为正整数,这样的x有多个,根本无法肯定是哪一个安全
对正整数n,在小于n的正整数之中,与n构成互质关系的数有多少个? 对这个问题的首位研究者叫做欧拉,是一个神同样的厉害人物,因此把对这个问题的解答称做欧拉函数,用φ(n)来表示服务器
如φ(8)表示计算8的欧拉函数,和8互质的数有,1,3,5,7因此φ(8) = 4; 如φ(7)表示计算7的欧拉函数,有1,2,3,4,5,6因此φ(7) = 6;微信
欧拉对这个问题进行研究以后,获得了欧拉函数的两个性质:markdown
结合以上两条性质可得,若A,B都是质数,则φ(A * B) = φ(A) * φ(B) = (A - 1) * (B - 1)
若是两个正整数m和n互质,那么m的φ(n)次方减去1,能够被n整除
针对上面的欧拉定理,费马又来了个小定理若是两个正整数m和n互质,并且n为质数,那么m的n-1次方减去1,能够被n整除
若是两个正整数e和x互质,那么必定能够找到整数d,使e * d - 1被x整除,那么d就是e相对于x的模反元素
把欧拉定理和模反元素结合起来推导
由于1 ^ k = 1,因此 两边同时k次方后获得
由于1 * m = m,因此上式两边同时乘上m后获得
将模反元素 变形后获得
再结合上述两个式子就能够获得
其中m,n互质,e与φ(n)互质,知足条件的d必定能够找到,咱们能够举几个例子验证一下
令m = 3,n = 17,e = 5,m,n互质,e和φ(17)互质,根据模反元素求的可能的d = ,k取4的时候,d为13,代入上式中验证 结果肯定等于3
多试几个m,n以后会发现,只要m < n,上面的等式就一直成立,再也不须要互质了...至于为何,俺也搞不明白,知道就行了,若是有大神知道的,还请不吝赐教
此时,m<n,e与φ(n)互质,d =
其实获得 以后,离咱们实际使用RSA算法很是接近了,实际使用中 ,这个过程叫做加密,再求 会发现结果仍是m,这个过程叫做解密,其中公钥就是n和e,私钥就是n和d,m表明明文,c表明密文
说明:
总共生成6个数字:p一、p二、n、φ(n)、e、d,除了公钥用到了n和e其他的4个数字是不公开的,目前皮杰RSA获得d的方式以下:
Mac电脑的终端能够直接使用OpenSSL进行RSA的命令运行。因为Mac系统内置OpenSSL(开源加密库),因此咱们能够直接在终端上使用命令来玩RSA. OpenSSL中RSA算法经常使用指令主要有三个:
生成RSA私钥,密钥长度为1024bit:openssl genrsa -out private.pem 1024
从私钥中提取公钥:openssl rsa -in private.pem -pubout -out public.pem
能够查看一下公钥和私钥的内容
还可使用命令openssl rsa -in private.pem -text -out private.txt
将私钥转成文本,并查看里面的内容
接下来咱们使用公钥对一段文本进行加密:openssl rsautl -encrypt -in message.txt -inkey public.pem -pubin -out enc.txt
能够看到message.txt的内容由密码123456已经变成了一堆乱码,(没使用过vim编辑器的同窗也能够直接建立一个txt文件)
使用私钥进行解密:openssl rsautl -decrypt -in enc.txt -inkey private.pem -out dec.txt
在macOS中咱们是不能直接使用pem文件的,须要使用的der格式和p12格式的文件
首先须要一个证书请求文件,这个作过iOS开发的同窗应该都很熟悉了openssl req -new -key private.pem -out rsacert.csr
通常咱们配置证书的时候,是使用上面生成的证书请求文件去苹果服务器签名后获得证书,可是如今咱们只是演示,就本身签名了:openssl x509 -req -days 3650 -in rsacert.csr -signkey private.pem -out rsacert.crt
经过crt文件生成p12文件:openssl pkcs12 -export -out p.p12 -inkey private.pem -in rsacert.crt
设置密码并再次确认以后获得p12文件
其实在平时平常开发中,证书这些东西,咱们iOS开发者直接使用就好了,基本是不会须要咱们iOS开发来生成配置
在iOS系统中,crt文件也不能直接使用,须要转成der文件,命令以下:
openssl x509 -outform der -in rsacert.crt -out rsacert.der
加载公钥和私钥其中
RSACryptor
是已经封装好的RSA工具类,有须要的能够本身去下载
加密hello world
并输出加密结果
解密过程
Hash,通常翻译作“散列”,也有直接音译为“哈希”的,就是把任意长度的输入经过散列算法变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间一般远小于输入的空间,不一样的输入可能会散列成相同的输出,因此不可能从散列值来肯定惟一的输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数
网络上通常是不会传输用户的密码明文数据的,不然当用户的帐号密码泄露以后,是会被追究法律责任的;如今市面上为何没有找回密码的功能,就是由于用户的密码并非以明文的形式保存在服务器上的;
咱们先使用最简单方式,来对用户的密码进行加密处理:(本文基于iOS平台,使用到的第三方能够在这下载)
直接对密码进行MD5可使用终端来验证一下上面加密的结果是否正确,终端命令以下:
md5 -s "123456"
能够看到加密的结果是一致的;可是有一些网站,它专门记录了经常使用的密码对应的md5值,好比:www.cmd5.com;这样咱们经常使用的密码,即便使用了md5加密,要破解出来也是太简单了...有什么更好的加密办法呢?
MD5 + 盐(一段任意的字符串)这样加密出来的结果,会比上面单纯的使用MD5会好一点,可是这个盐一旦泄露以后,要破解出密码来也是垂手可得,上面的那个网站依然能够很好的查询出来
HMAC加密方案
以用户注册为例,当用户把输入完帐号的时候,如今不少APP或者网站都会让用户去检测帐号的合法性,服务器验证合法就会生成这个帐号对应的key,并发送给客户端;客户端将服务器返回的key记录在本地,并跟用户输入的密码进行一次hmac加密,将加密的结果发送给服务器记录并保存;这样就算是注册成功了!当用户下次登陆的时候,客户端查找本地的帐号对应的key,和用户输入的密码进行hmac运算以后,发送给服务器验证;这样相比较于上面的仅仅加盐的方式,安全性又高了一些;
在用户更换设备进行登陆的时候,此时客户端没有帐号对应的key了,那就须要在输入完帐号密码登陆的时候,先去请求服务器获取key值;服务器收到这个请求以后,能够查询当前帐号是否开启了设备锁,若是开了设备锁,那么就去询问有key值的设备是否容许当前设备登陆,不一样意那么新设备就天然登陆失败;赞成的话,就将帐号对应的key值返回给请求的设备,这样用户在新设备上进行登陆所需的key也有了,再与密码进行hmac后发送给服务器验证登陆;是否是在QQ,微信之类有设备锁的APP上见过
HMAC + 时间戳
使用上述的hmac加密方案以后,密码的安全性确实高了很多;可是还能够在安全一点,那就是再加上时间戳;在用户输入帐号密码,点击登陆以后,用生成的hmac密码,再拼接上一个到分钟的当前时间,好比202106120112,再进行一次MD5加密获得的结果发送给服务器;此时服务器也会用已经存起来的hmac密码拼接当前分钟的时间戳,进行一次MD5,和客户端发送过来的结果进行匹配,若是一致则登陆成功;若是不一致,那么就使用上一分钟的时间戳,再进行一次MD5,再匹配客户端发送过来的结果(为何再试一次上一分钟,由于有可能在发送的过程当中,时间加了一分钟);这样用户登陆的时候,密码的时效最多只有2分钟,过了这2分钟,密码又不同了...黑客会很懵逼
主要是用于拆词搜索,每一个词语进行hash运算后的结果都是同样的,好比上海,iOS,程序员在百度上搜索,不论怎么样排列这三个词语,可能都会搜到同一条新闻,就是由于这三个词对应的hash值相加以后的结果,不论这三个词怎么排列,都是同样的;
百度云上传电影的时候,有些电影会有秒传的功能;就是比对hash值是同样的,再比对一些额外的信息,就能够肯定是同一部电影了,就不须要重复上传了; 视频网站YouTube之类的,会对用户上传的视频文件进行hash并记录,这样用户上传每一个视频都有了一个身份证相似的id了
什么是数字签名?老外喜欢用签名,刷信用卡消费以后有一个帐单,须要信用卡持卡人签名确认;签名的目的就是表示被签名的东西是属于签名人的;数字签名的意思就是对一串二进制数据进行签名,用于确认是谁的二进制数据
举个例子:你在网上购买了一件100元的商品,你的消费信息发送给服务器,服务器收到了你的消费信息后,在你的帐户下面扣除100元,而后把扣款结果返回给用户,这个世界原本是这么简单的;可是中间若是有不怀好意的黑客,他篡改了你发送给服务器的消费信息,改成你消费了1000元,而后服务器收到这条消息后,在你的帐户里扣除了1000元,并将扣款结果返回,这个时候黑客再将服务器返回给你的扣款信息篡改,告诉你成功消费100元,你们都没察觉出什么问题,回过头你发现你不知去向了900元...因此服务器须要确认消费信息是由你发出的并且是没有通过第三方篡改的消费信息,怎么作到呢?
首先使用hash将消费信息进行加密获得一个128位的结果,而后使用RSA的公钥对结果进行加密,而后将消费信息,RSA公钥加密的消费信息hash值全发送给服务器,服务器收到结果后,使用RSA的私钥解密获得一个消费信息的hash值,再使用收到的消费信息进行一次hash加密,比较两个hash值是都相同,相同就表明消费信息没有被第三方修改,不相同就表明消费信息被修改过了;这里面被RSA加密的消费信息的hash值就叫做数字签名
对称加密(也叫私钥加密)指加密和解密使用相同密钥的加密算法。有时又叫传统密码算法,就是加密密钥可以从解密密钥中推算出来,同时解密密钥也能够从加密密钥中推算出来。而在大多数的对称算法中,加密密钥和解密密钥是相同的,因此也称这种加密算法为秘密密钥算法或单密钥算法。它要求发送方和接收方在安全通讯以前,商定一个密钥。对称算法的安全性依赖于密钥,泄漏密钥就意味着任何人均可以对他们发送或接收的消息解密,因此密钥的保密性对通讯的安全性相当重要。
对称加密算法的特色是算法公开、计算量小、加密速度快、加密效率高。
数据加密标准,如今用的少,由于强度低
使用3个密钥,对相同的数据执行三次加密
高级加密标准,包括苹果的钥匙串访问,美国国家安全局都在使用的加密方式
ECB:(Electronic Code Book),电子密码本模式,每一块数据独立加密;最基本的加密模式,也就是一般理解的加密,相同的明文将永远加密成相同的密文,无初始向量,容易受到密码本重放攻击,通常状况下不多用。
CBC:(Cipher Block Chainning),密码分组连接模式;明文被加密前要与前面的密文进行异或运算后再加密,所以只要选择不一样的初始向量,相同的密文加密后会造成不一样的密文,这是目前应用最普遍的模式。CBC加密后的密文是上下文相关的,但明文的错误不会传递到后续分组,但若是一个分组丢失,后面的分组将所有做废(同步错误)。CBC能够有效的保证秘闻的完整性,若是一个数据块在传递时丢失或者改变,后面的数据将没法正常解密。
还有一些模式,但不是很常见,好比Cipher Feedback Mode(CFB)加密反馈模式,Output Feedback Mode(OFB)输出反馈模式
明文message.txt内容以下:
使用DES算法ECB模式加密,key为abc:openssl enc -des-ecb -K 616263 -nosalt -in message.txt -out msg1.bin
将明文中的某个数字修改一下
再使用一样的加密方式,生成第二份密文msg2.bin:openssl enc -des-ecb -K 616263 -nosalt -in message.txt -out msg2.bin
对比一下生成的两份密文msg1.bin和msg2.bin,发现明文就只是改动了一个数字,对应的密文是一整块都修改了,这也形象的表示了ECB模式的原理
而后咱们试一下CBC模式:
openssl enc -des-cbc -iv 0102030405060708 -K 616263 -nosalt -in message.txt -out msg3.bin
将明文内容修改回最初的样子后再使用CBC模式生成msg4.bin文件
openssl enc -des-cbc -iv 0102030405060708 -K 616263 -nosalt -in message.txt -out msg4.bin
对比msg3.bin和msg4.bin发现,CBC模式下改动了一处后,后面的总体都发生了改变,两次对比很形象的说明了ECB模式和CBC模式的区别
使用AES算法,ECB模式进行加密(EncryptionTools下载) 再用终端来验证一下结果:
echo -n hello | openssl enc -aes-128-ecb -K 616263 -nosalt | base64
使用AES算法,CBC模式进行加密 终端验证结果:
echo -n hello | openssl enc -aes-128-cbc -K 616263 -nosalt -iv 0102030405060708 | base64
终端验证解密结果:
echo -n u3W/N816uzFpcg6pZ+kbdg== | base64 -D | openssl enc -aes-128-cbc -K 616263 -iv 0102030405060708 -nosalt -d
[EncryptionTools sharedEncryptionTools]
单例默认使用的就是AES算法,若是想使用其余的算法,能够自行指定[EncryptionTools sharedEncryptionTools].algorithm = <#CCAlgorithm#>
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
self.algorithm,
option,
cKey,
self.keySize,
cIv,
[data bytes],
[data length],
buffer,
bufferSize,
&encryptedSize);
复制代码
参数1: kCCEncrypt 表明加密,kCCDecrypt 表明解密
参数2: 加密算法,AES,DES...
参数3: 加密模式:ECB,CBC...
参数4: 加密所需的密钥
参数5: 密钥的长度
参数6: iv 初始化向量(若是是CBC模式须要传入,ECB不须要)
参数7: 加密的数据,也就是明文
参数8: 加密的数据的长度,明文的长度
参数9: 密文的内存地址
参数10: 密文缓冲区的大小
参数11: 加密结果的大小
在iOS中,使用了对称加密的最终都会走到这个函数,若是有人对你开发的APP有些想法,就会调试你的应用,对这个CCCrypt下一个符号断点,就能够拿到这个函数的全部参数信息了,那用户的明文密码就泄露无疑了... 寄存器读这个函数的第七个参数就是
register read x6
(x0是第一个)明文数据