作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在服务器上有这个 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 对其进行解密。
ByteArray
? 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
}
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。
关于python - 如何在 Kotlin 中解密 AES/CBC 加密字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66841666/
我是一名优秀的程序员,十分优秀!