我使用encrypt.dart加密基于32位密码(“密码”)的字符串(“文本”)如下:
encryptPass(String text, String password) {
final key = getKey(password);
final iv = encrypt.IV.fromLength(16);
final encrypter = encrypt.Encrypter(encrypt.AES(key)); //Uses AES/SIC/PKCS7
final e = encrypter.encrypt(text, iv: iv);
String encryptedString = e.base64.toString();
return encryptedString;
}
getKey(String masterPass) {
String keyString = masterPass;
if (keyString.length < 32) {
int count = 32 - keyString.length;
for (var i = 0; i < count; i++) {
keyString += ".";
}
}
final keyReturn = encrypt.Key.fromUtf8(keyString);
return keyReturn;
}
附带注意:这是可行的,但是它每次为给定的输入字符串生成相同的值,即使我的"iv“和"salt”应该是随机的。这是怎么发生的?
的主要问题:,我正在尝试使用科特林的海绵城堡重新创建这个过程。问题是我不知道encrypt.dart AES函数的某些重要属性。所使用的值是:
盐长: 16,32,128,256?("desiredKeyLength“变量在encrypted.dart中)迭代计数:(我认为这是100,但我不确定。)秘密密钥算法:基于encrypted.dart的“最终pbkdf2”假设的。密钥长度:?
以下是我目前对海绵城堡实现的尝试,以供参考:
fun encryptAESBasic(input: String, password: String): String {
Security.insertProviderAt(org.spongycastle.jce.provider.BouncyCastleProvider(), 1)
val masterpw = password.toCharArray()
val random = SecureRandom()
val salt = ByteArray(256)
random.nextBytes(salt)
val factory: SecretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1")
val spec: KeySpec = PBEKeySpec(masterpw, salt, 100, 128)
val tmp: SecretKey = factory.generateSecret(spec)
val key: SecretKey = tmp
val cipher = Cipher.getInstance("AES/SIC/PKCS7PADDING", "SC")
val iv = ByteArray(16)
SecureRandom().nextBytes(iv)
cipher.init(Cipher.ENCRYPT_MODE, key, IvParameterSpec(iv))
val cipherText: ByteArray = cipher.doFinal(input.toByteArray())
return cipherText.toString()
}
发布于 2021-07-24 09:52:27
Dart代码使用零IV (仅由0x00
值组成的IV ),这就是为什么总是生成相同的密文。
正如您已经知道的,Dart代码默认应用SIC模式和PKCS7填充。SIC模式是CTR模式的另一个名称,它是流密码模式,因此不需要任何填充。因此,在Dart代码中使用的PKCS7填充是不必要的。
请注意,将CTR模式与静态IV (例如零IV)结合使用是一个致命的错误,通常非常不安全(s. 这里)。
作为密钥派生,Dart代码将密码与.
交换,直到密钥大小为32字节为止,这是AES-256所需的。这个键派生也非常不安全。在使用密码时,应该始终使用可靠的密钥派生函数(如PBKDF2 )(如Kotlin代码中的那样)。
因此,在移植到Kotlin之前,应该修改Dart代码并使其更加安全。这需要进行以下更改:
salt|IV|ciphertext|tag
)连接。注意,对于GCM,许多库隐式地执行密文和标记的连接。当然,从技术角度看,可以将Dart代码移植到Kotlin,例如,
fun encryptPass(text: String, password: String): String {
val secretKeySpec = SecretKeySpec(getKey(password), "AES") // Apply a reliable key derivation function (getKey() is insecure)
val cipher = Cipher.getInstance("AES/CTR/PKCS5PADDING") // Disable padding (CTR doesn't require padding)
val iv = ByteArray(16) // Generate random IV (CTR with static IV is extremely insecure)
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, IvParameterSpec(iv))
val cipherText: ByteArray = cipher.doFinal(text.toByteArray(Charset.forName("UTF-8"))) // Authenticity/integrity missing
return Base64.encodeToString(cipherText, Base64.DEFAULT); // Concatenation of salt, IV, ciphertext and authentication tag missing
}
fun getKey(masterPass: String): ByteArray {
return masterPass.padEnd(32, '.').toByteArray(Charset.forName("UTF-8"))
}
这给出了与Dart代码相同的结果(不需要使用SpongyCastle ),但出于安全考虑,不应该使用该代码。
https://stackoverflow.com/questions/68505254
复制相似问题