首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >颤振encrypt.dart属性的确定

颤振encrypt.dart属性的确定
EN

Stack Overflow用户
提问于 2021-07-23 21:37:41
回答 2查看 1.5K关注 0票数 1

我使用encrypt.dart加密基于32位密码(“密码”)的字符串(“文本”)如下:

代码语言:javascript
运行
复制
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”假设的密钥长度:

以下是我目前对海绵城堡实现的尝试,以供参考:

代码语言:javascript
运行
复制
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()
}
EN

Stack Overflow用户

回答已采纳

发布于 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代码并使其更加安全。这需要进行以下更改:

  • 为每个加密生成随机IV。
  • 应该禁用PKCS7填充。
  • 密码不检查密文的真实性/完整性。为此,必须应用附加身份验证标记(MAC)。建议从CTR模式切换到GCM模式,该模式基于CTR模式,但除了机密性(认证加密)之外,还包含数据的真实性/完整性,并隐式地生成标记。
  • 必须使用安全密钥派生(例如PBKDF2,请参阅Kotlin代码)。与此相结合,将为每个密钥派生(s也是其他答案)生成一个随机盐。
  • Salt和IV (都不是秘密)以及标记将与密文(salt|IV|ciphertext|tag)连接。注意,对于GCM,许多库隐式地执行密文和标记的连接。

当然,从技术角度看,可以将Dart代码移植到Kotlin,例如,

代码语言:javascript
运行
复制
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 ),但出于安全考虑,不应该使用该代码。

票数 2
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68505254

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档