gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 18:51:26 25 4
gpt4 key购买 nike

我在服务器上有这个 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, AES.MODE_CBC, 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。在那里,我想通过相同的共享 key 对其进行解密。
  • 我以什么格式将上面的字节保存到数据库中?
  • 到达 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 以消除内存开销。
    Python:
        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 iv + cipher.encrypt(raw.encode())
    所以这已经不可能了。
    enc = AESCipher('abc').encrypt("myLife")
    value_to_save_in_db = enc.decode("utf8")
    所以我需要找到一种方法将字节数组直接存储在数据库中。我想我应该能够做到这一点。但是仍然存在一些挑战,例如如何通过 API 将字节数组作为 JSON 的一部分发送到 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, 0, ivBytes, 0, ivBytes.size)
    System.arraycopy(dataToDecrypt, ivBytes.size, cipherBytes, 0, 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 派生 key 。但是,如果 key 是从密码派生的,出于安全原因,不是 SHA256,而是可靠的 key 派生函数,例如应使用 Argon2 或 PBKDF2。
    Kotlin 代码首先对 Python 数据进行 Base64 解码,然后将 IV 和实际密文分开。然后,通过生成密码的 SHA256 哈希来导出 key 。最后解密数据。

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

    关于python - 如何在 Kotlin 中解密 AES/CBC 加密字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66841666/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com