_ivanC

Open Source Projects
Code that Might be Useful to You

Talks I've Given
On Technologies and Ideas

Follow Me On

GitHub
If coding is your thing

Twitter
If you tweet

Facebook
If you like something new

Weibo
If you like sharing

简书
If you like writing

RSA 入门介绍及应用


RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥

关于RSA的密钥

-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKiMx2aFW1L5aceZ6j0AxFaz38aPgadH
AOZyxEHG/7g6ia/pWgDw73JWpUP65mkpVymfbln/GqJJoMxtXDnUGOMCAwEAAQ==
-----END PUBLIC KEY-----

生成一个RSA的Keypair

$ openssl genrsa -out private.pem 1024
$ openssl rsa -in private.pem -out public.pem -outform PEM -pubout
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0);
    OSStatus SecKeyGeneratePair(CFDictionaryRef parameters, 
            SecKeyRef *publicKey,
               SecKeyRef *privateKey) 

使用RSA进行加密和解密

$ openssl rsautl -encrypt -inkey public.pem -pubin -in file.txt -out file.ssl
$ openssl rsautl -decrypt -inkey private.pem -in file.ssl -out decrypted.txt
OSStatus SecKeyEncrypt(SecKeyRef key, SecPadding padding, const uint8_t *plainText, size_t plainTextLen, uint8_t *cipherText, size_t *cipherTextLen) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0);
OSStatus SecKeyDecrypt(SecKeyRef     key,         /* Private key */
               SecPadding     padding,      /* kSecPaddingNone,
                                                               kSecPaddingPKCS1,
                                                                           kSecPaddingOAEP */
              const uint8_t   *cipherText,
                                        size_t        cipherTextLen,  /* length of cipherText */
                                        uint8_t       *plainText, 
                                        size_t        *plainTextLen)  /* IN/OUT */
                      __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0);

使用RSA进行签名和验证

在App上使用

这样的字符串一般会放在一个.pem的文件里面,可以供openssl直接使用,但是正常来说,pem明显是不适用的,而且因为是明文,安全性不高

因此我们可以通过以下方法来生成一个证书对,也可以给其他方通用

openssl req -new -key rsaPrivate.pem -out rsaCertReq.csr
openssl x509 -req -days 3650 -in rsaCertReq.csr -signkey rsaPrivate.pem -out rsaCert.crt
openssl x509 -outform der -in rsaCert.crt -out rsaCert.der
openssl pkcs12 -export -out rsaPrivate.p12 -inkey rsaPrivate.pem -in rsaCert.crt

从这里你会发现,Publickey是可以从Privatekey生成的,因为他们的modulus是一样的,而Publickey的exponent基本上固定是e(65537), 而且得到的结果是一个p12,是不是很熟悉?和我们开发者证书gen给其他人用的时候是一样的

得到这2个证书之后,就可以利用oc的代码来获取到SecKeyRef的对象,进行相关的操作了,具体可以看我封装的RSAKithttps://github.com/IvanChan/RSAKit,如果后续有需要使用RSA加解密和签名的话,也可以用这个通用接口来实现。

签名机制

再来回想一下,RSA用公钥encrypt,私钥decrypt,个人猜测,这样的做法是为了让个人信息在本地保存,外部不知道个人隐私信息,例如开发者证书。

回到我们的实际用途上,我们肯学希望用的是私钥在服务器加密,公钥在客户端解密,这样可以保证证书不会在客户端被他人破解获取到,伪造一些数据。所以我们使用RSA的签名机制,用私钥sign,公钥verify。

所谓的签名,就像你把数据给别人之前,先打一个胎记,然后到使用这个数据的时候,看一下有没有这个胎记,才认这份数据。

简单看一下流程

参考

https://www.openssl.org/docs/apps/rsa.html https://www.openssl.org/docs/apps/rsautl.html https://www.devco.net/archives/2006/02/13/public_-_private_key_encryption_using_openssl.php