2017-03-21 44 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