Android RSA 加密

238 阅读1分钟

在一些信息传输的过程中,需要对信息进行加解密。服务端使用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
    }
}