对于RSA加解密来讲,在iOS的API中一样也是提供了这两种形式的方法。git
SecKeyEncrypt(加密)
SecKeyDecrypt(解密)
复制代码
openssl 一样也提供了一系列的方法:github
RSA_public_encrypt
RSA_private_encrypt
RSA_public_decrypt
RSA_private_decrypt
复制代码
相比较而言,openssl 提供的方法更为明确,好比:公钥解密,私钥解密,私钥加密,公钥解密。虽然 iOS 原生给出的只是加密和解密的方法,可是在方法注释中明确说了,加密用的就是公钥,解密用的就是私钥。算法
其实公钥加密私钥解密也是最经常使用的方式,私钥加密公钥解密用的并很少,可是私钥加密公钥解密有的时候也是须要的。若是真的须要私钥加密公钥解密,openssl 会更方便一点,但其实 iOS 也能够作私钥加密公钥解密。安全
这里大体说一下RSA加解密的过程:bash
1.生成密钥加密
公钥 (E,N)
私钥 (E,D,N)
复制代码
2.加解密spa
密文 = 明文E % N 明文 = 密文D % N
咱们经过一个具体的例子来直观体验下,通过计算咱们如今获得一对具体的密钥对:code
公钥=(E,N) = (5,323) 私钥=(D,N) = (29,323) B = AE mod N = pow(123, 5) % 323 = 225 A = BD mod N = pow(225, 29) % 323 = 123
若是 A(123) 为明文,那上面的过程就是 公钥加密私钥解密;
若是 B(225) 为明文,那上面的过程就是 私钥加密公钥解密;ssl
换一下顺序可能会更清除一点:get
A = BD mod N = pow(225, 29) % 323 = 123 (私钥加密) B = AE mod N = pow(123, 5) % 323 = 225 (公钥解密)
这样一来咱们就会发现,其实加解密是同一个方法。那为何会有加密和解密两个方法呢?个人理解是:
加密就是,传入数据直接作计算(就像上面的那样)
解密就是,传入数据直接作计算(仍是上面的那样),不过会根据填充模式作数据处理,把填充的随机数剔除掉。
因此从原理上来讲私钥加密公钥解密是行的通的,只是须要本身作一些数据上的处理。具体实现能够看Demo。
RSA算法自己要求加密内容也就是明文长度 m 必须 0<m<n ,也就是说内容这个大整数不能超过 n,不然就出错。那么若是 m=0,RSA加密器会直接返回全0结果。因此在对较长的数据进行加密的时候要把数据分段,每一段的数据长度不能大于模数长度(密钥长度)。
在实际的 RSA 加密中,分段的长度跟填充模式也有必定的关系:
填充方式 | 最大输入长度 | 输出长度 | 填充内容 |
---|---|---|---|
PKCS1 | keySize - 11 | keySize | 随机数 |
NONE | keySize - 1 | keySize | 00 |
有的文章说 padding 为 NONE 是的最大输入长度为 keySize,其实这样是有风险的。若是明文长度跟密钥长度同样的话,明文就有可能大于模数,这样在加密的时候就会出错。因此这里建议 padding 为 NONE 是明文的分段长度取 keySize - 1
。
分段加密以后就要分段解密了,在实际的RSA加密中,加密出来的密文老是等于密钥的长度,因此在分段解密的时候密文的分段大小直接取密钥长度。
RSA在实际应用为了提升安全性防范各类攻击,在加解密过程当中都须要添加必定的随机因素。为了让同一明文每次加密产生的密文都不同,加密前先填充一部分随机数,这个不止RSA有,DES等对称加密也都有,称为padding。加密标准里有各类类型的padding标准,好比PCKS1。
对于PKCS1,这个填充格式会要求每次加密的数据比密钥长度短至少11个字节(keySize - 11),填充格式以下:
PS 为随机填充数,M为明文
00 02 | PS | 00 | M (公钥加密)
00 01 | PS | 00 | M (私钥加密)
复制代码
以 00 开头填充同时也保证了待加密数据不会大于密钥的模数。
还有一个比较经常使用的就是None(不填充),若是明文比密钥短的话会在明文的前面填充零(0)
0000 | M
复制代码