在一些信息传输的过程中,需要对信息进行加解密。服务端使用RSA进行加解密。但是有一个问题,使用服务端提供的公私钥,在测试类运行的结果服务端能正常解密,在真机环境中结果服务端却无法解密。
后面发现是服务端rsa加密方式与Android端rsa加密方式不一致、服务端的Base64编码与Android使用的Base64编码不一致,导致服务端对客户端传来的加密数据解密失败。
Android的rsa加密方式是RSA/ECB/NoPadding,而标准jdk是RSA/ECB/PKCS1Padding。所以在Android加解密的时候需要使用标准jdk的加密方式,服务端才能正常地加解密。
import java.security.KeyFactory
import java.security.interfaces.RSAPrivateKey
import java.security.interfaces.RSAPublicKey
import java.security.spec.PKCS8EncodedKeySpec
import java.security.spec.X509EncodedKeySpec
import javax.crypto.Cipher
import android.util.Base64
object RSAUtil {
//设置标准jdk RSA 算法及填充模式
private const val RSA_ALGORITHM = "RSA/ECB/PKCS1Padding"
// 公钥加密
fun encryptByPublicKey(data: String): String {
val cipher = Cipher.getInstance(RSA_ALGORITHM)
val publicKey = getPublicKey(PUBLIC_KEY)//替换为服务端使用的公钥
cipher.init(Cipher.ENCRYPT_MODE, publicKey)
val encryptedBytes = cipher.doFinal(data.toByteArray(Charsets.UTF_8))
return Base64.encodeToString(encryptedBytes, Base64.NO_WRAP)
}
// 私钥解密
fun decryptByPrivateKey(data: String): String {
val cipher = Cipher.getInstance(RSA_ALGORITHM)
val privateKey = getPrivateKey(PRIVATE_KEY)//替换为服务端使用的私钥
cipher.init(Cipher.DECRYPT_MODE, privateKey)
val decryptedBytes = cipher.doFinal(Base64.decode(data, Base64.NO_WRAP))
return String(decryptedBytes, Charsets.UTF_8)
}
// 从 Base64 获取公钥
private fun getPublicKey(publicKey: String): RSAPublicKey {
val keyBytes = Base64.decode(publicKey, Base64.NO_WRAP)
val keySpec = X509EncodedKeySpec(keyBytes)
val keyFactory = KeyFactory.getInstance("RSA")
return keyFactory.generatePublic(keySpec) as RSAPublicKey
}
// 从 Base64 获取私钥
private fun getPrivateKey(privateKey: String): RSAPrivateKey {
val keyBytes = Base64.decode(privateKey, Base64.NO_WRAP)
val keySpec = PKCS8EncodedKeySpec(keyBytes)
val keyFactory = KeyFactory.getInstance("RSA")
return keyFactory.generatePrivate(keySpec) as RSAPrivateKey
}
}