Android RSA加密

794 阅读2分钟

RSA加密算法

RSA加密 RSA加密是一种非对称加密算法,它使用一对公钥和私钥进行加密和解密。公钥用于加密数据,私钥用于解密数据。RSA加密可以确保数据在传输过程中的安全性,因为只有持有私钥的人才能解密加密后的数据。 优势

  1. 安全性高:RSA加密算法是非常安全的,即使是攻击者知道了公钥,他们也无法破解私钥。
  2. 可靠性强:RSA加密算法已经被广泛应用于各种场景,例如电子商务、金融交易、安全通信等。

应用场景

  1. 安全通信:RSA加密可以确保在客户端和服务器之间传输的数据安全。
  2. 数字签名:RSA加密可以用于验证数据的完整性和真实性。
  3. 身份验证:RSA加密可以用于验证用户身份,确保只有授权用户才能访问系统。

在Android中进行RSA公钥解密的流程如下:

  1. 请求接口,获取后端RSA公钥
  2. 用公钥进行请求加密后发送给服务器端
  3. 服务器用私钥进行解密

获取后端RSA公钥

在接口请求头部添加一个参数 random_str 这个参数为随机唯一字符串 长度小于16位 方法如下 :

fun generateUniqueIdentifier(minLength: Int = 2, maxLength: Int = 15): String {
    require(minLength in 1..maxLength) {
	"minLength must be greater than 0 and less than or equal to maxLength"
	}
    val length = Random.nextInt(minLength, maxLength + 1) // 生成随机长度
    val chars = ('A'..'Z') + ('a'..'z') + ('0'..'9') // 可用的字符集合

    return (1..length)
            .map { chars.random() } // 随机选择字符
            .joinToString("") // 连接成字符串
}

用公钥进行请求加密后发送给服务器端

  1. 将公钥转换为X509证书
  2. 使用X509证书初始化Cipher对象
  3. 使用Cipher对象进行解密操作
  4. 请求头需要和获取公钥的random_str相同,(后台要求)
  5. 然后将请求body 一般是map格式转换成json 然后加密成密文(都是post请求)

注意事项

项目中常常会遇到Android前端使用后端提供的公钥加密数据的场景。需要注意Java后端的java.util.Base64默认Base64标准和Android的android.util.Base64是不一样的。

此外,RSA算法标准也需要前后端显式约定。

1. 其中,加密结果用Base64.NO_WRAP编码

2. 公钥用Base64.DEFAULT解码

3. 加密算法是RSA/None/PKCS1Padding

详细代码如下 :

fun encryptWithPublicKey(map: HashMap<String, Any>? = null, publicKey: String?): String {
    val date = Gson().toJson(map)
    if (publicKey.isNullOrEmpty()) return ""
    // 去掉公钥字符串中的头尾和换行符
    val publicKeyPEM = publicKey.trimIndent().replace("-----BEGIN PUBLIC KEY-----", "")
            .replace("-----END PUBLIC KEY-----", "")
            .replace("\n", "")
    var outStr = ""
    try {
        // base64编码的公钥
        val decoded: ByteArray = Base64.decode(publicKeyPEM, Base64.DEFAULT)
        val pubKey = KeyFactory.getInstance("RSA")
                .generatePublic(X509EncodedKeySpec(decoded)) as RSAPublicKey
        // RSA加密
        val cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding")
        cipher.init(Cipher.ENCRYPT_MODE, pubKey)
        outStr = Base64.encodeToString(
                cipher.doFinal(date.toByteArray(charset("UTF-8"))),
                Base64.NO_WRAP
        )
    } catch (e: Exception) {

        e.printStackTrace()
    }
    return outStr
}