Semanik

TestRsa.kt

Oct 10th, 2020
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 6.34 KB | None | 0 0
  1. /*
  2.  * Copyright 2020 Punch Through Design LLC
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *     http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16.  
  17. package com.punchthrough.blestarterappandroid
  18.  
  19. import android.util.Base64
  20. import java.security.KeyFactory
  21. import java.security.MessageDigest
  22. import java.security.PrivateKey
  23. import java.security.spec.PKCS8EncodedKeySpec
  24. import java.util.Arrays
  25. import javax.crypto.Cipher
  26. import javax.crypto.spec.IvParameterSpec
  27. import javax.crypto.spec.SecretKeySpec
  28.  
  29. class TestRsa {
  30.     private var SessionKey: ByteArray? = null
  31.     private var SessionIV: ByteArray? = null
  32.     private val SHA1_LEN = 20 //SHA1 result length
  33.     private val AES_LEN = 16 //AES block size
  34.     private val KEY_LEN = 64 //Length of RSA encoded AES session keys (with SHA1 and padding)
  35.     private val CMD_LEN = 32 //Length of AES encoded command / status (with SHA1 and padding)
  36.  
  37.     fun getPrivateKey(): PrivateKey? {
  38.         try {
  39.             val kf = KeyFactory.getInstance("RSA")
  40.             val res = kf.generatePrivate(
  41.                 PKCS8EncodedKeySpec(
  42.                     Base64.decode(
  43.                         """
  44.                MIICWwIBAAKBgQDhWLOSU0FxsQkkLY2qghpG4L3/yoTlYJ39acLqHhOBXWWK5wRc
  45.                Ms2Xk54Bo8ZaOmbzf9U+FmWwJzjtyTUcYDUl4WsU8WJ30dC+ncbLWCSeq7ltvL2f
  46.                Jmc3anaYRrvFLJbZljQ1rZKROKcKgLahR4rCeatAhSNjdmZofNW4fWJpQwIDAQAB
  47.                AoGAFYk/Io31x38Zj9oRdTxMdTEKwRS8Dhnlb3yskpuMoxGBRomc7cMzL9HKFeXV
  48.                Ho/NtM0nD/FFbaGjlXuw9jguZY75G0gm6uULLh/k/5Y4Fx+wS7Mp2EOWtyI5rSbW
  49.                DXYuWbcajLyx2+STjppj851Y1NoxDpJzu0QHyeuGv+g51jkCQQDsBbuDUONuPKLB
  50.                KDb6Ff/axCvhTHergD2bFwA7pxDXd10EHvJq0nUFDsZOyxJhfVWgUCz7rba+o/S4
  51.                FeAGIurbAkEA9GujL+BVe57/qyqO48QWL8+u4z0fKkbnZSTeVhD8LYAMnPX2782J
  52.                lqxMkWSpIYmC+gy6chaciaknYmoLJjxjuQJAJ4zWXSziz4gtpbx9ae7hzuDskXZk
  53.                30JAEIsMKPLX6aNA3P3qlWfq4AwXwwBYdimwfYqx3wK/CrcivO49egnD3QJAPdiq
  54.                nyetma0+1knbhCiO0KRFhXxm0WTFkmNE2xRLKxw2lNTsGfuxL+4DJdsJrNHF0Y28
  55.                87di/rZNn+pjTdaECQJAIFxoxYwSIUyZpiTF/t7ceNr/7ADQIaJYpgsK8vrS56Fw
  56.                EulO24ONOWs5GwuGp0Gk/PjBb4ZR20tVwGLXZi3/3A==        
  57.                """.trimIndent(),
  58.                         Base64.DEFAULT
  59.                     )
  60.                 )
  61.             )
  62.             return res
  63.         } catch (e: Exception) {
  64.             e.printStackTrace()
  65.         }
  66.         return null
  67.     }
  68.  
  69.     fun setupSession(encodedKey: ByteArray): Boolean {
  70.         SessionKey = null
  71.         SessionIV = null
  72.         val res = false
  73.         try {
  74.             //RSA decryption (used only here)
  75.             val cipher = Cipher.getInstance("RSA")
  76.             cipher.init(Cipher.DECRYPT_MODE, getPrivateKey())
  77.             var decodedKey = cipher.doFinal(encodedKey)
  78.             decodedKey =
  79.                 Arrays.copyOfRange(decodedKey, decodedKey.size - KEY_LEN, decodedKey.size)
  80.  
  81.             if (checkSHA(decodedKey)) {
  82.                 SessionKey = Arrays.copyOfRange(decodedKey, 0, AES_LEN)
  83.                 SessionIV = Arrays.copyOfRange(decodedKey, AES_LEN, AES_LEN * 2)
  84.                 return true
  85.             }
  86.         } catch (e: Exception) {
  87.             e.printStackTrace()
  88.         }
  89.         return false
  90.     }
  91.  
  92.     private fun checkSHA(`in`: ByteArray?): Boolean {
  93.         try {
  94.             val crypt =
  95.                 MessageDigest.getInstance("SHA-1")
  96.             crypt.reset()
  97.             crypt.update(Arrays.copyOfRange(`in`, 0, `in`!!.size - SHA1_LEN))
  98.             val SHA = crypt.digest()
  99.             val inSHA =
  100.                 Arrays.copyOfRange(`in`, `in`.size - SHA1_LEN, `in`.size)
  101.             if (!Arrays.equals(SHA, inSHA)) {
  102.                 print("Decode fail")
  103.                 return false
  104.             }
  105.             return true
  106.         } catch (e: Exception) {
  107.             e.printStackTrace()
  108.         }
  109.         return false
  110.     }
  111.  
  112.     private fun cryptAES(opmode: Int, `in`: ByteArray?): ByteArray? {
  113.         try {
  114.             val IV = Arrays.copyOf(SessionIV, SessionIV!!.size)
  115.             val cipher = Cipher.getInstance("AES/CBC/NoPadding")
  116.             cipher.init(
  117.                 opmode,
  118.                 SecretKeySpec(SessionKey, "AES"),
  119.                 IvParameterSpec(IV)
  120.             )
  121.             val out = cipher.doFinal(`in`)
  122.             return out
  123.         } catch (e: Exception) {
  124.             e.printStackTrace()
  125.         }
  126.         return null
  127.     }
  128.  
  129.     private fun cryptAES(mode: Int, base64: String): String {
  130.         val out = cryptAES(mode, Base64.decode(base64, Base64.DEFAULT))
  131.         val res = Base64.encodeToString(out, Base64.DEFAULT).trim('\n')
  132.         return res
  133.     }
  134.  
  135.     private fun setupSession(base64Encoded: String): Boolean {
  136.         return setupSession(Base64.decode(base64Encoded, Base64.DEFAULT))
  137.     }
  138.  
  139.     fun test(): Boolean {
  140.  
  141.         // RSA
  142.         val RSA_BASE64_ENCODED = "hIThGsuxSQDcypPVVijM58KTUo0neU6ESSPf2N1E1JxiYbGdRrTEdNCO2CB73LNl/8Tk2eARhI2U\n" +
  143.             "F2c9Npsf4kYrYAD6SBzwiXkcNEmSIyBibpfAxGHKNCmHPbQHU8ME37rcZ3RLHlQv5IAaZ+H4SXBg\n" +
  144.             "/bb+oEYcw/7UIUyO/T8="
  145.  
  146.         if (!setupSession(RSA_BASE64_ENCODED)) {
  147.             throw Exception("setupSession fail")
  148.         }
  149.  
  150.  
  151.         // AES ENCRYPT
  152.         val AES_ENCRYPT = "zXqCnP0jj6wMDwVtNVMTktqn5jqzTt2mHDxJfMochB0="
  153.         val AES_ENCRYP_COMP = "FlGFXeDrU5A3GPz75FmBhC/sguVvcllloFGh0hT1e5Q="
  154.  
  155.         if (cryptAES(Cipher.ENCRYPT_MODE, AES_ENCRYPT) != AES_ENCRYP_COMP) {
  156.             throw Exception("cryptAES ENCRYPT_MODE fail")
  157.         }
  158.  
  159.  
  160.         // AES DECRYPT
  161.  
  162.         val AES_DECRYPT = "ch76T/vpXwjZMAN9S4b+DA4+pSs1sGAdqxsQbncW8sA="
  163.         val AES_DECRYPT_COMP = "gODxATvDSPzt8rgr23Ye7xeron3SrBOtfdwWsTcXkJQ="
  164.  
  165.         if (cryptAES(Cipher.DECRYPT_MODE, AES_DECRYPT) != AES_DECRYPT_COMP) {
  166.             throw Exception("cryptAES DECRYPT_MODE fail")
  167.         }
  168.  
  169.  
  170.         return true
  171.     }
  172. }
Add Comment
Please, Sign In to add comment