美文网首页
RSA加解密Kotlin实现

RSA加解密Kotlin实现

作者: Q大疯zi | 来源:发表于2018-09-16 22:41 被阅读103次

    下面是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<String>) {
        /* 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}")
    }
    
    运行结果.png

    由图可以看出来:

    • RSA的公钥要短于私钥
    • RSA的公钥加解密都要快于私钥加解密

    相关文章

      网友评论

          本文标题:RSA加解密Kotlin实现

          本文链接:https://www.haomeiwen.com/subject/ovdqnftx.html