1

我有一个简单的加密例程,每次执行时都会产生不同的结果。任何人都可以识别问题吗?下面的代码只显示了三个不同时间的相同调用,您可以看到每次调用的结果都不同。

import SwiftUI
import CryptoKit

struct ContentView: View {
    @State var password = "TopSecret"
    @State var text = "My text"
    
    var body: some View {
        VStack {
            TextField("Password", text: $password)
            TextField("Text", text: $text)
            Text(try! encrypt(password: password, text: text).hexEncodedString())
            Text(try! encrypt(password: password, text: text).hexEncodedString()).foregroundColor(Color.blue)
            Text(try! encrypt(password: password, text: text).hexEncodedString())
        }
    }
}

func encrypt(password: String, text: String) throws -> Data {
    let x = [UInt8](text.utf8)
    return try encrypt(password: password, input: x)
}

func encrypt(password: String, input: [UInt8]) throws -> Data {
    let pwd = password.padding(toLength: 32, withPad: "@", startingAt: 0)
    let key = SymmetricKey(data: pwd.data(using: String.Encoding.utf8)!)
    let sealedBox = try AES.GCM.seal(input, using: key)
    return sealedBox.combined!
}

extension Data {
    struct HexEncodingOptions: OptionSet {
        let rawValue: Int
        static let upperCase = HexEncodingOptions(rawValue: 1 << 0)
    }
    func hexEncodedString(options: HexEncodingOptions = []) -> String {
        let format = options.contains(.upperCase) ? "%02hhX" : "%02hhx"
        return self.map { String(format: format, $0) }.joined()
    }
}
4

1 回答 1

2

这是该seal方法等安全加密方案的一个特点。包含一个随机值(称为“nonce”)以确保每个加密都是唯一的。所有这些都将正确解密。

如果您需要一致(不安全)的加密结果,例如在单元测试中,您可以通过将nonce参数传递给seal.

请注意,您的密钥派生非常不安全。您不能只将 ASCII 字符串填充到 AES 密钥中。它破坏了密钥空间。对于计算机生成的密钥,您应该生成一个随机的 32 个字节。对于人工生成的密码,您需要一个 PBKDF(例如 PBKDF2 或 scrypt)来拉伸密钥。不幸的是,我不相信 CryptoKit 提供任何工具来支持基于密码的加密。只有随机密钥加密。您需要使用 CommonCrypto 或 CryptoSwift 之类的工具手动执行密钥拉伸,或者您需要使用支持密码的工具,例如 Themis 或 RNCryptor。

于 2021-08-27T17:49:50.287 回答