下面是RSA的Kotlin实现
有个疑问的是:一般界面都是 128个字节限制,但是我用128个总是出错,看到说是要用256个,改成256后就没问题了,是不是我的Jdk版本的问题啊,我的IDEA是jdk10 然后Android studio用的jdk8 ,结果都是要用128的。jdk7就没测试了,有知道的告诉我。
object RSACrypt {
val transformation = "RSA"
val ENCRYPT_MAX_SIZE = 117
val DECRYPT_MAX_SIZE = 256
/**
* 私钥加密
*/
fun encryptByPrivateKey(str: String, privateKey: PrivateKey): String {
val byteArray = str.toByteArray()
val cipher = Cipher.getInstance(transformation)
cipher.init(Cipher.ENCRYPT_MODE, privateKey)
//定义缓冲区
var temp: ByteArray? = null
//当前偏移量
var offset = 0
val outputStream = ByteArrayOutputStream()
while (byteArray.size - offset > 0) {
//剩余的部分大于最大加密字段,则加密117个字节的最大长度
if (byteArray.size - offset >= ENCRYPT_MAX_SIZE) {
temp = cipher.doFinal(byteArray, offset, ENCRYPT_MAX_SIZE)
//偏移量增加117
offset += ENCRYPT_MAX_SIZE
} else {
//如果剩余的字节数小于117,则加密剩余的全部
temp = cipher.doFinal(byteArray, offset, (byteArray.size - offset))
offset = byteArray.size
}
outputStream.write(temp)
}
outputStream.close()
return Base64.encode(outputStream.toByteArray())
}
/**
* 公钥加密
*/
fun encryptByPublicKey(str: String, publicKey: PublicKey): String {
val byteArray = str.toByteArray()
val cipher = Cipher.getInstance(transformation)
cipher.init(Cipher.ENCRYPT_MODE, publicKey)
var temp: ByteArray? = null
var offset = 0
val outputStream = ByteArrayOutputStream()
while (byteArray.size - offset > 0) {
if (byteArray.size - offset >= ENCRYPT_MAX_SIZE) {
temp = cipher.doFinal(byteArray, offset, ENCRYPT_MAX_SIZE)
offset += ENCRYPT_MAX_SIZE
} else {
temp = cipher.doFinal(byteArray, offset, (byteArray.size - offset))
offset = byteArray.size
}
outputStream.write(temp)
}
outputStream.close()
return Base64.encode(outputStream.toByteArray())
}
/**
* 私钥解密
* 注意Exception in thread "main" javax.crypto.IllegalBlockSizeException:
* Data must not be longer than 256 bytes
* 关于到底是128个字节还是256个,我也很迷糊了,我写成128的时候就报这个错误,改成256后就没事了
*/
fun decryptByPrivateKey(str: String, privateKey: PrivateKey): String {
val byteArray = Base64.decode(str)
val cipher = Cipher.getInstance(transformation)
cipher.init(Cipher.DECRYPT_MODE, privateKey)
//定义缓冲区
var temp: ByteArray? = null
//当前偏移量
var offset = 0
val outputStream = ByteArrayOutputStream()
while (byteArray.size - offset > 0) {
//剩余的部分大于最大解密字段,则加密限制的最大长度
if (byteArray.size - offset >= DECRYPT_MAX_SIZE) {
temp = cipher.doFinal(byteArray, offset, DECRYPT_MAX_SIZE)
//偏移量增加128
offset += DECRYPT_MAX_SIZE
} else {
//如果剩余的字节数小于最大长度,则解密剩余的全部
temp = cipher.doFinal(byteArray, offset, (byteArray.size - offset))
offset = byteArray.size
}
outputStream.write(temp)
}
outputStream.close()
return String(outputStream.toByteArray())
}
/**
* 公钥解密
*/
fun decryptByPublicKey(str: String, publicKey: PublicKey): String {
val byteArray = Base64.decode(str)
val cipher = Cipher.getInstance(transformation)
cipher.init(Cipher.DECRYPT_MODE, publicKey)
var temp: ByteArray? = null
var offset = 0
val outputStream = ByteArrayOutputStream()
while (byteArray.size - offset > 0) {
if (byteArray.size - offset >= DECRYPT_MAX_SIZE) {
temp = cipher.doFinal(byteArray, offset, DECRYPT_MAX_SIZE)
offset += DECRYPT_MAX_SIZE
} else {
temp = cipher.doFinal(byteArray, offset, (byteArray.size - offset))
offset = byteArray.size
}
outputStream.write(temp)
}
outputStream.close()
return String(outputStream.toByteArray())
}
}
fun main(args: Array) {
/* val generator = KeyPairGenerator.getInstance("RSA")
val genKeyPair = generator.genKeyPair()
val privateKey = genKeyPair.private
val publicKey = genKeyPair.public
println("公钥:" + Base64.encode(publicKey.encoded))
println("公钥Length:" + Base64.encode(publicKey.encoded).length)
println("私钥:" + Base64.encode(privateKey.encoded))
println("私钥Length:" + Base64.encode(privateKey.encoded).length)*/
//秘钥对是一直变化的,不可能每次都生成
val publicKeyStr = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnvSR5VSoxCdhcgQzGkp8zSCOTUCP37YyVlJ8qzkRSxxNhB5OeKOP0OjhglAkn7v8i6SAR5ZDYwyLX6Y3W9+x5CoJ5bV3PpEzrq4qhv5JGBAE7q/ylR48y/3Aob/L04+4EuzFklzFILESmb7qsa5yKqtSO8Acvp2Ay0jJbzH6ZmhLkvW5C7+yoj/RnGWixop0EezxjV7wmI2aCHUAx4rUzbSoAhsonEYCRKS7MHx1t2M3vJBdinsnJEZ28tLXSdnTUrWzOK1gwYLfVW5ExQCLgOfGyweQ86ylgTDidjmeT4mpraqQHysLX/tv0FFhpUnxzK7P6DDWS3W0ep+o6eBvXQIDAQAB"
val privateKeyStr = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCe9JHlVKjEJ2FyBDMaSnzNII5NQI/ftjJWUnyrORFLHE2EHk54o4/Q6OGCUCSfu/yLpIBHlkNjDItfpjdb37HkKgnltXc+kTOuriqG/kkYEATur/KVHjzL/cChv8vTj7gS7MWSXMUgsRKZvuqxrnIqq1I7wBy+nYDLSMlvMfpmaEuS9bkLv7KiP9GcZaLGinQR7PGNXvCYjZoIdQDHitTNtKgCGyicRgJEpLswfHW3Yze8kF2KeyckRnby0tdJ2dNStbM4rWDBgt9VbkTFAIuA58bLB5DzrKWBMOJ2OZ5PiamtqpAfKwtf+2/QUWGlSfHMrs/oMNZLdbR6n6jp4G9dAgMBAAECggEAekLTFPmQ9Y70vKXOSKKSa5Rm37SQ9RlGjm7TxT8XthYG6WAGK3Ri4eS9z2WlRddp4F6e7HD/U+gKK3/FhL0CLuTGyBBTr6QvhGQiAcMEpaVspcpfY6LmUGDVEZRcSlV419WWAYWpegO4stjN2+y5k2hC0AJsGZE7xyAtD4H5f1nvEbob0z/c9vlEYIUVZGsBf2PC7IPev64FLuGQE7/AsoM6jFh2etiCEkAbOUzHbhH3RAHajO7GdIPLBvFKGwYNKUh8lAKxQ11uZRjUQ2CgsawkgILV/DyqYoXJupsa0Q+ss0NVOkDf3tRbLc0fAmnpOjG78AgUIXNodOGzIEskYQKBgQDrFE8OV6k1rriW5O84kIxlU1J/jHl67C1R/fjrdZzJ7YzjqKwQo0GQhUiWyAJtoqGmMhaLgVi3VrbGUCPGJiaN/NuTPRWxGi/VXaJMPs+K2yErSyMEWmo6lcGjD2kOW7ZMUDoWMp3loNlliZPjMZ8Y3mZ3WeIv/vuxhpt+F0GgrwKBgQCtGfe7qLFxqZfpICebM4MV9tjWwr2q9boWFWuNg0DxTw0WyWQHQfNa+0afOIj6qMIxBJlvzV0Bet71XW5XKTmWbuQhYcbeoUcBBFB0DdM2Glret1A46KJOzxMz3HNAdkVhK028hr784DlE+Tg1SEWAYWidSlC9u80L49XPZgd7swKBgD7sMrT+Fda+q74IDVgwqMO+Z8ioSyPx77eQqX4s/wi1ww506YmSiUwrwOBLLQs3itk3cv1oY9y/IzE15j11nMBIvGVO5m1/Oup7o6OQ9HCQcvJprDfQE7sWtrv0tgQX3FXU65dheQ4r3cTl7GXVtGYtsXOk5Xw/XhOImjpH81MVAoGAQgIX/OB8Icq5GfXgBIflIdgKogKKzwl7F3a9l64IcrxhUmIjmbzlbrlJGeg2G9eEjaqiVAbsw2a2ZLxnGienRR0uMyiU7Ep1yAZ8I3UuKIBuTGV82uajFghS20DiVh+Dn2Ui9JQxej6KuCmM7IyNrEH44Zn4JhHaRAFyg+71RY8CgYEAmZVTkXFJXoIw8TAcV4968Uf/hfTwqWXc6uHAc/TAP4JNyi2+7TJ4xRziNenETcT9JByV8iw3iBjGwgeXr8BOzvPzs91foyG9elCK+WHBfT5XC9EssTwFXNTGdtcxG3fusHomwZlJnsuaHcBe0bX5HB0MXxJ3n4PjhvVQ+8qwuv0="
val keyFactory = KeyFactory.getInstance("RSA")
val privateKey = keyFactory.generatePrivate(PKCS8EncodedKeySpec(Base64.decode(privateKeyStr)))
val publicKey = keyFactory.generatePublic(X509EncodedKeySpec(Base64.decode(publicKeyStr)))
//注意:加密长度不能超过117个字节
//注意:解密长度不能超过256个字节
val str = "我喜欢编程,我喜欢编程,我喜欢编程,我喜欢编程,我喜欢编程我喜欢编程我喜欢编程我喜欢编程," +
"我喜欢编程,我喜欢编程我喜欢编程我喜欢编程我喜欢编" + "我喜欢编程,我喜欢编程我喜欢编程我喜欢编程我喜欢编" +
"我喜欢编程,我喜欢编程我喜欢编程我喜欢编程我喜欢编" + "我喜欢编程,我喜欢编程我喜欢编程我喜欢编程我喜欢编"
println("加密的字段长度:" + str.length)
println("加密的字段字节长度:" + str.toByteArray().size)
val privateEnStartTime = System.currentTimeMillis()
val encyptByPrivateKey = RSACrypt.encryptByPrivateKey(str, privateKey)
println("私钥加密结果:$encyptByPrivateKey")
println("私钥加密时间:${System.currentTimeMillis() - privateEnStartTime}")
val publicDeStartTime = System.currentTimeMillis()
val decryptByPublicKey = RSACrypt.decryptByPublicKey(encyptByPrivateKey, publicKey)
println("公钥解密:$decryptByPublicKey")
println("公钥解密时间:${System.currentTimeMillis() - publicDeStartTime}")
val publicEnStartTime = System.currentTimeMillis()
val encyptByPublicKey = RSACrypt.encryptByPublicKey(str, publicKey)
println("公钥加密结果:$encyptByPublicKey")
println("公钥加密时间:${System.currentTimeMillis() - publicEnStartTime}")
val privateDeStartTime = System.currentTimeMillis()
val decryptByPrivateKey = RSACrypt.decryptByPrivateKey(encyptByPublicKey, privateKey)
println("私钥解密:$decryptByPrivateKey")
println("私钥解密时间:${System.currentTimeMillis() - privateDeStartTime}")
}
由图可以看出来:
- RSA的公钥要短于私钥
- RSA的公钥加解密都要快于私钥加解密