2017-03-21 56 views
3

我有一些将在服务器上生存的文件。用户可以在设备上创建这些类型的文件(plist),然后将其上传到所述服务器(CloudKit)。我想通过内容来区分它们(独特方法应该能够适应创建日期的变化)。我的理解是我应该散列这些文件,以便为它们获取唯一的文件名。我的问题是:如何使用swift 3在iOS上散列文件?

  1. 我的理解是正确的,我想要的是散列函数?
  2. 我应该使用哪种函数(来自CommonCrypto)。
  3. 我需要的是一个摘要?
  4. 我将如何在代码中进行介绍? (我认为这应该在NSData实例上散列?)。我从Google上搜索的理解是,我需要一个桥接头,但除此之外,使用CommonCrypto让我感到困惑。如果使用第一方API(Apple)的方法更简单,那么我都非常喜欢(我想尽可能避免使用第三方代码)。

非常感谢!

+0

这里的各种哈希方法:http://stackoverflow.com/questions/25388747/sha256-in-swift。 –

+0

大警告。散列函数不会生成唯一的标识符。碰撞是可能的,你应该处理它。 – Sulthan

+0

@Sulthan虽然这是真的,但密码哈希可以安全地用于识别文件,请参阅Git。 – zaph

回答

5

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

使用普通的加密(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 <CommonCrypto/CommonCrypto.h> 

对于散列数据:

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

也看到马丁的链接。

+0

感谢您的照明快速回复!我读你的代码是函数散列一个字符串,我怎么去散列plist(我假设通过一个Data对象)?另外,你调用base64EncodedString只是一个截断的例子吗? (对不起,我不知道密码学......) –

+0

转换为UTF-8 *不能*失败 - 我们之前有过这种讨论吗? –

+0

@马丁啊,是的,我正在复制我的旧代码,正在纠正。自从我纠正另一个人以来,双重尴尬。 – zaph