如何使用swift 3在iOS上散列文件?

我有许多文件将存在于服务器上。 用户可以在设备上创建这些类型的文件(plist),然后上传到所述服务器(CloudKit)。 我想通过内容使它们独一无二(唯一的方法应该能够适应创建日期的变化)。 我的理解是我应该散列这些文件以获取它们的唯一文件名。 我的问题是:

  1. 我的理解是正确的,我想要的是哈希函数吗?
  2. 我应该使用哪种function(来自CommonCrypto)。
  3. 我需要的是摘要?
  4. 我将如何在代码中进行操作? (我假设这应该在NSData实例上进行哈希处理?)。 我从谷歌搜索的理解是,我需要一个桥接头,但除此之外,使用CommonCrypto困扰我。 如果使用第一方API(Apple)有一种更简单的方法,我很满意(我希望尽可能避免使用第三方代码)。

非常感谢!

创建每个文件的加密哈希值,您可以将其用于唯一性比较。 SHA-256是一个当前的哈希函数,在iOS上使用Common Crypto非常快,在iPhone 6S上SHA256将处理大约1GB /秒减去I / O时间。 如果您需要更少的字节,只需截断哈希。

使用Common Crypto(Swift3)的示例

对于散列字符串:

func sha256(string: String) -> Data { let messageData = string.data(using:String.Encoding.utf8)! var digestData = Data(count: Int(CC_SHA256_DIGEST_LENGTH)) _ = digestData.withUnsafeMutableBytes {digestBytes in messageData.withUnsafeBytes {messageBytes in CC_SHA256(messageBytes, CC_LONG(messageData.count), digestBytes) } } return digestData } let testString = "testString" let testHash = sha256(string:testString) print("testHash: \(testHash.map { String(format: "%02hhx", $0) }.joined())") let testHashBase64 = testHash.base64EncodedString() print("testHashBase64: \(testHashBase64)") 

输出:
testHash:4acf0b39d9c4766709a3689f553ac01ab550545ffa4544dfc0b2cea82fba02a3
testHashBase64:Ss8LOdnEdmcJo2ifVTrAGrVQVF / 6RUTfwLLOqC + 6AqM =

注意:添加到您的桥接标题:

 #import  

对于散列数据:

 func sha256(data: Data) -> Data { var digestData = Data(count: Int(CC_SHA256_DIGEST_LENGTH)) _ = digestData.withUnsafeMutableBytes {digestBytes in data.withUnsafeBytes {messageBytes in CC_SHA256(messageBytes, CC_LONG(data.count), digestBytes) } } return digestData } let testData: Data = "testString".data(using: .utf8)! print("testData: \(testData.map { String(format: "%02hhx", $0) }.joined())") let testHash = sha256(data:testData) print("testHash: \(testHash.map { String(format: "%02hhx", $0) }.joined())") 

输出:
testData:74657374537472696e67
testHash:4acf0b39d9c4766709a3689f553ac01ab550545ffa4544dfc0b2cea82fba02a3

另见马丁的链接。

解决方案也适用于大型文件,因为它不需要整个文件在内存中:

 func sha256(url: URL) -> Data? { do { let bufferSize = 1024 * 1024 // Open file for reading: let file = try FileHandle(forReadingFrom: url) defer { file.closeFile() } // Create and initialize SHA256 context: var context = CC_SHA256_CTX() CC_SHA256_Init(&context) // Read up to `bufferSize` bytes, until EOF is reached, and update SHA256 context: while autoreleasepool(invoking: { // Read up to `bufferSize` bytes let data = file.readData(ofLength: bufferSize) if data.count > 0 { data.withUnsafeBytes { _ = CC_SHA256_Update(&context, $0, numericCast(data.count)) } // Continue return true } else { // End of file return false } }) { } // Compute the SHA256 digest: var digest = Data(count: Int(CC_SHA256_DIGEST_LENGTH)) digest.withUnsafeMutableBytes { _ = CC_SHA256_Final($0, &context) } return digest } catch { print(error) return nil } } 

使用以前创建的名称为fileURL URL类型的实例:

 if let digestData = sha256(url: fileURL) { let calculatedHash = digestData.map { String(format: "%02hhx", $0) }.joined() DDLogDebug(calculatedHash) }