程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了如何在 Kotlin 中解密 AES/CBC 加密字符串?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决如何在 Kotlin 中解密 AES/CBC 加密字符串??

开发过程中遇到如何在 Kotlin 中解密 AES/CBC 加密字符串?的问题如何解决?下面主要结合日常开发的经验,给出你关于如何在 Kotlin 中解密 AES/CBC 加密字符串?的解决方法建议,希望对你解决如何在 Kotlin 中解密 AES/CBC 加密字符串?有所启发或帮助;

我在服务器上有这个 Python 方法来将字符串加密为字节 (AES/CBC)

class AESCipher(object,key):
    def __init__(self,key): 
        self.bs = AEs.BLOCK_SIZE
        self.key = hashlib.sha256(key.encode()).digest()

    def encrypt(self,raw):
        raw = self._pad(raw)
        iv = Random.new().read(AEs.BLOCK_SIZE)
        cipher = AEs.new(self.key,AEs.MODE_CBC,iv)
        return base64.b64encode(iv + cipher.encrypt(raw.encode()))

    def decrypt(self,enC):
        enc = base64.b64decode(enC)
        iv = enc[:AEs.BLOCK_SIZE]
        cipher = AEs.new(self.key,iv)
        return self._unpad(cipher.decrypt(enc[AEs.BLOCK_SIZE:])).decode('utf-8')

    def _pad(self,s):
        return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)

encrypt() 的输出在 bytes是这样的b'PMgMOkBkciIKfWy/DfntVMyAcKtVsM8LwEwnTYE5IXY='

我想将其存储到数据库中,并通过 API 将其作为字符串发送到 Kotlin。在那里我想通过相同的共享密钥解密它。

  1. 我以什么格式将上述字节保存到数据库中?
  2. 到达 Kotlin 客户端后,如何将该字符串转换为 ByteArray

我的理论是我必须在数据库中将字节存储为 base64 字符串。 另一方面,我必须将字符串作为 base64 解码为字节。这种方法是否正确?使用下面的代码,加密/解密会像这样端到端地工作吗?

    fun decrypt(context:Context,dataToDecrypt: ByteArray): ByteArray {
            val cipher = Cipher.geTinstance("AES/CBC/PKCS5padding")
            val ivSpec = IvParameterSpec(getSavedInitializationVector(context))
            cipher.init(Cipher.DECRYPT_MODE,getSavedSecretKey(context),ivSpeC)
            val cipherText = cipher.doFinal(dataToDecrypt)
            val sb = StringBuilder()
            for (b in cipherText) {
                sb.append(b.tochar())
            }   
            return cipherText
    }
    
    fun getSavedSecretKey(context: Context): SecretKey {
            val sharedPref = PreferenceManager.getDefaultSharedPreferences(context)
            val strSecretKey = sharedPref.getString("secret_key","")
            val bytes = androID.util.base64.decode(strSecretKey,androID.util.base64.DEFAulT)
            val ois = ObjecTinputStream(ByteArrayinputStream(bytes))
            val secretKey = ois.readobject() as SecretKey
            return secretKey
    }
    
    fun getSavedInitializationVector(context: Context) : ByteArray {
            val sharedPref = PreferenceManager.getDefaultSharedPreferences(context)
            val StrinitializationVector = sharedPref.getString("initialization_vector","")
            val bytes = androID.util.base64.decode(StrinitializationVector,androID.util.base64.DEFAulT)
            val ois = ObjecTinputStream(ByteArrayinputStream(bytes))
            val initializationVector = ois.readobject() as ByteArray
            return initializationVector
        }

更新

我已尝试删除 Base64 以消除建议的内存开销。

蟒蛇:

    def encrypt(self,iv)
        return iv + cipher.encrypt(raw.encode())

所以这不再可能。

enc = AESCipher('abc').encrypt("mylife")
value_to_save_in_db = enc.decode("utf8")

所以我需要找到一种方法将字节数组直接存储在数据库中。我想我应该能够做到这一点。但是,如何将字节数组作为 JsON 的一部分通过 API 发送到 AndroID 设备仍然存在一些挑战。我想我必须再次将其转换为 Base64 字符串。不知道在那种情况下我是否得到了什么......

解决方法

以下 Kotlin 代码:

val decrypted = decrypt("bLeoKMQtUbNOzJbvEkL2gNhjF+qQ/ZK84f2ADu8xyUFme6uBhNYqvEherF/RRO9YRImz5Y04/ll+T07kqv+ExQ==");
println(decrypted);

解密 Python 代码的密文。这里的 decrypt() 是:

fun decrypt(dataToDecryptB64 : String) : String {

    // Base64 decode Python data
    val dataToDecrypt = Base64.getDecoder().decode(dataToDecryptB64)

    // Separate IV and Ciphertext
    val ivBytes = ByteArray(16)
    val cipherBytes = ByteArray(dataToDecrypt.size - ivBytes.sizE)
    System.arraycopy(dataToDecrypt,ivBytes,ivBytes.sizE)
    System.arraycopy(dataToDecrypt,ivBytes.size,cipherBytes,cipherBytes.sizE)

    // Derive key
    val keyBytes = messageDigest.geTinstance("SHA256").digest("abc".toByteArray(CharsetS.UTF_8))

    // Decrypt
    val cipher = Cipher.geTinstance("AES/CBC/PKCS5PADDING")
    cipher.init(Cipher.DECRYPT_MODE,SecretKeySpec(keyBytes,"AES"),IvParameterSpec(ivBytes))
    val cipherText = cipher.doFinal(cipherBytes)

    return String(cipherText,Charsets.ISO_8859_1)
}

为此,密文是使用发布的 Python 类 AESCipher 生成的,如下所示:

plaintext = 'The quick brown fox jumps over the lazy dog'
cipher = AESCipher('abc')
ciphertext = cipher.encrypt(plaintext)
print(ciphertext.decode('utf8')) # Base64 String,which can be stored e.g. in a DB

我应用了最初发布的 Python 实现,该实现使用 SHA256 导出密钥。但是,如果密钥是从密码派生的,出于安全原因,不是 SHA256,而是可靠的密钥派生函数,例如应使用 Argon2 或 PBKDF2。

Kotlin 代码首先对 Python 数据进行 Base64 解码,然后将 IV 和实际密文分开。然后,通过生成密码的 SHA256 哈希来派生密钥。最后解密数据。


当前 Python 代码 Base64 对数据进行编码,以便将其作为字符串存储在数据库中。或者,可以修改 Python 代码,以便不执行 Base64 编码,并且可以存储原始数据(这需要更少的内存,Base64 开销:33%)。
根据选择的解决方案,Kotlin 代码可能需要也可能不需要对数据进行 Base64 解码。

大佬总结

以上是大佬教程为你收集整理的如何在 Kotlin 中解密 AES/CBC 加密字符串?全部内容,希望文章能够帮你解决如何在 Kotlin 中解密 AES/CBC 加密字符串?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。