我有一个要求,其中字符串将从flutter网络应用程序使用dart 加密.加密后的字符串将被发送到服务器,iOS Swift也会使用.

DART文件文件


String encryptString(Uint8List key) {
   try {
    final encryptionKey = Key(key);
    final iv = IV.fromLength(16); // 16 bytes IV for AES-GCM
    final macValue = utf8.encode("");
    final encrypter = Encrypter(AES(encryptionKey, mode: AESMode.gcm));
    final encrypted = encrypter.encrypt(
      this,
      iv: iv,
      associatedData: macValue,
    );
    final concatenatedBytes = Uint8List.fromList([...iv.bytes, ...encrypted.bytes, ...macValue]);
    final base64Encoded = base64.encode(concatenatedBytes);
    return base64Encoded;
  } catch (e) {
    print('Error while encrypting: $e');
    return '';
  }
  }

然而,加密文本我无法在Swift中解密.我总是得到CryptoKit.CryptoKit错误.身份验证失败

swift代码

func decrypt(withKey key: SymmetricKey) throws -> String {
    guard let encryptedData = Data(base64Encoded: self) else { throw EncryptionError.invalidData }
    
    // Open the sealed box using the encryption key
    do {
      let sealedBox = try AES.GCM.SealedBox(combined: encryptedData)
      // Decrypt the data
      let decryptedData = try AES.GCM.open(sealedBox, using: key)
      // Convert decrypted data to string
      guard let decryptedString = String(data: decryptedData, encoding: .utf8) else {
        throw EncryptionError.decryptionFailed
      }
      return decryptedString
    } catch {
      print(error.localizedDescription)
      throw EncryptionError.invalidData
    }
  }

我试过上面的片段.似乎不起作用,请帮忙:)

推荐答案

Although GCM is not listed as a supported operation mode in the encrypt package documentation (Usage section), as you have already found out yourself, newer versions support GCM (see issue#259 and GCM-example), so this package can be used.
Note that encrypt is only a high level wrapper for some PointyCastle functionalities, and that PointyCastle could be used directly as well.

Apart from the incorrect operation mode (see other answer), both codes are still incompatible even after changing the Dart code to GCM mode. This is due to the nonce size of 16 bytes applied.
For GCM, a 12 byte nonce is recommended, which should be adhered to for performance and compatibility reasons.
The Swift library supports a 16 bytes nonce, but not in the combined representation, which is used in the current code and which may only be used for a 12 bytes nonce.
Instead, the nonce, ciphertext and tag must be specified explicitly, i.e. they must be separated in the Swift code. Since the encrypt package uses the default tag length of 16 bytes and automatically appends the tag to the ciphertext, the data has the following structure: nonce (16 bytes) | ciphertext | tag (16 bytes), so that the parts can be separated using the known lengths of tag and nonce, e.g:

let keyData = Data(base64Encoded: "MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDE=")
let retrievedKey = SymmetricKey(data: keyData!)
...
let data = Data(base64Encoded: "fzKLLUhOLMW7qJ6YhfFnv5TX6sD5gg2F6JxWkwhu07RpceWCu12EXzxgCqyB8VHXkXDHOOczaMXHLiDmlZqBJjgEb8IpmKJc/aLc")! // generated with Dart code
let dataSize = data.count
let noncebytes = data[0..<16]
let ciphertext = data[16..<dataSize-16]
let tag = data[dataSize-16..<dataSize]

let nonce = try AES.GCM.Nonce(data: noncebytes)
let sealedBox = try AES.GCM.SealedBox(nonce: nonce, ciphertext: ciphertext, tag:tag)
let decryptedData = try AES.GCM.open(sealedBox, using: key)

print(String(data: decryptedData, encoding: .utf8)!) // The quick brown fox jumps over the lazy dog

请记住,在12字节的随机数的情况下,可以使用combined表示.在这种情况下,数据必须具有以下 struct :nonce (12 bytes) | ciphertext | tag (16 bytes).

Note that the name macValue in the Dart code is misleading. MAC is used as a synonym for the authentication tag. However, what you refer to as macValue is not the authentication tag but the additional authenticated data (AAD). This is data that does not need to be encrypted but should nevertheless be authenticated in order to ensure its integrity and authenticity.
In contrast, the authentication tag (or MAC) is generated automatically during encryption (and, depending on the library, either appended to the ciphertext or returned separately). This tag is used during decryption to check the integrity and authenticity of the data.

当前代码使用了一个空字符串作为AAD,即实际上没有AAD,因此在Swift代码中不需要考虑.然而,如果要使用AAD:在combined表示的情况下,AAD不能被连接,或者必须在传递给AES.GCM.SealedBox()之前被移除.AAD在AES.GCM.open()中明确指定(参见authenticating).

顺便说一句,如果AAD像在当前代码中那样级联(这是相当不寻常的),解密侧必须知道它们的长度(至少如果密文长度不知道),以便分离是可能的.

Ios相关问答推荐

AlGolia InstantSearch Swift Package Manager引发编译错误

UITableViewCell编程约束问题

在flatter_riverpod中,如果没有ref对象,我们如何访问提供程序?

SwiftUI-工作表不显示导航标题

OBJC @selector 在另一个实现中不起作用

在 iOS 上以后台模式安排任务(屏幕时间 API)

如何在 Android 上的 Flutter 应用中录制内部音频?

为什么applicationState发布者只发布一次?

Flutter iOS 构建失败:DVTCoreDeviceEnabledState_Disabled

Swiftui为什么在点击第二行之前背景不起作用

从视图模型中更新 EnvironmentObject

通过MatchedGeometryEffect向上滑动视图

UICollectionView - 水平滚动,水平布局?

如何从一个特定的视图控制器中隐藏导航栏

如何获取 iTunes 连接团队 ID 和团队名称?

应用程序不包含正确的测试版权利

在 React Native 中保存敏感数据

检测应用程序何时进入我的视图背景的最佳方法是什么?

在 SKScene 中设置按钮

UITableView 中的圆形 UIImageView 没有性能影响?