RSA 加密在iOS 中的使用
RSA 使用public & private 两种密钥对数据进行加密,可以更加安全的保护用户敏感数据,既可以在服务端与客户端之前共同使用,也可以单独中客户端中使用。
1. RSA 运用在服务器与客户端之间
RSA有一对密钥,一个是公钥,一个是私钥,他们都是在客户端生成,客户端请求api 数据的时候,将公钥通过api 请求传给服务端,服务端则用收到的公钥对数据进行加密,然后将加密过的数据传回给客户端,客户端收到加密的数据后,用对应的私钥解密,得到原始数据并显示到view.
也就是说,在generate RSA时,是同时生成一对公私钥的,公钥用来加密,私钥用来解密,公钥不能用来解密,私钥也不能用来加密,各有各的责任。而且这对公私钥必须是对应的,不对应的公私钥解密会失败,相当于一把钥匙对应一把锁,用其他钥匙是打不开这把锁的。公钥在传输过程中就算泄露了也不会对数据安全造成严重的影响。举个例子就是用charles抓api 请求数据包,就算抓到了加密的数据也无法解开,因为私钥是在客户端的。
需要注意的是,因为公私钥是对应的,所以每次创建得到的一对公私钥需要保存好,或者即创即用,比如:
比如有一个通过一个key来创建公私钥方法:
let securityKeyPairProvider = SecurityKeyPairProvider(tag: "test tag")
// 拿到它的public key
let publicKey = try securityKeyPairProvider.retrievePublicKey()
// 通过api 发给服务端,服务端加密后将加密后数据返回来
let response = try await self.service.getEncryptDataFromServiceByKey(publicKey: publicKey)
// 解密
let myData = try securityKeyPairProvider.decrypt(response: response.name)
...
这样即完成了一次即创即用的加解密过程。
假如通过这样拿到加密过和数据后,用户将此未解密的数据保存了起来,下次重新来到这个页面,然后重新创建了一个新的
let securityKeyPairProvider2 = SecurityKeyPairProvider(tag: "test tag")
然后想用此securityKeyPairProvider2去解密刚才的保存的未解密数据,是不会成功的,即使这个securityKeyPairProvider2是用同一个test tag创建的也不行,因为它已经不是加密用的public key对应的私钥了,除非在第一次时将生成的私钥也保存起来,然后再次进来时也取出这个私钥对数据进行解密才行。
2. RSA 运用在客户端内
继续上面说的,用户可以一次创建,将公私钥匙都保存起来,每次用同样的公钥加密,每次也用同样的私钥解密也是可以的,但这个情况下就要对保存的公私钥匙要妥善处理了,通常是将它们保存在钥匙串中,keychain.也是苹果推荐的方法。 这样就可以将数据在本地加密,然后可以将加密后的数据缓存在沙盒,下次启动app进到页面时再用保存的私钥解密并显示了。
ps.
// 看加密的方法,是加密字符串的还是data的,需要互相转换下
// string -> data
let stringToEncrypt = Data(string.utf8)
// encrypt (-> data)
let encryptedData = rsaEncryptor.encrypt(stringToEncrypt)
// data -> string
let decryptedString = String(data decryptedData, encoding: .utf8)
// 以上是加密过程,解密过程则要反过来
// 比如将一个加密字符串 解密
// string -> data
let encryptedData = Data(base64Encoded: encryptedString)
// decrypt (-> data)
let decryptedData = rsaEncryptor.decrypt(encryptedData ?? Data())
// data -> string
let displayString = String(data: decryptedData, encoding: .utf8)