2017-06-26 100 views
0

我使用CCKeyDerivationPBKDF獲取僞隨機生成的派生密鑰時遇到問題。使用CCKeyDerivationPBKDF獲取派生密鑰

這裏是我使用的@zaph代碼:

// password  password String 
// salt   salt Data 
// keyByteCount number of key bytes to generate 
// rounds  Iteration rounds 
//  
// returns  Derived key 


func pbkdf2SHA1(password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? { 
    return pbkdf2(hash:CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1), password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds) 
} 

func pbkdf2SHA256(password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? { 
    return pbkdf2(hash:CCPBKDFAlgorithm(kCCPRFHmacAlgSHA256), password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds) 
} 

func pbkdf2SHA512(password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? { 
    return pbkdf2(hash:CCPBKDFAlgorithm(kCCPRFHmacAlgSHA512), password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds) 
} 

func pbkdf2(hash :CCPBKDFAlgorithm, password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? { 
    let passwordData = password.data(using:String.Encoding.utf8)! 
    var derivedKeyData = Data(repeating:0, count:keyByteCount) 

    let derivationStatus = derivedKeyData.withUnsafeMutableBytes {derivedKeyBytes in 
     salt.withUnsafeBytes { saltBytes in 

      CCKeyDerivationPBKDF(
       CCPBKDFAlgorithm(kCCPBKDF2), 
       password, passwordData.count, 
       saltBytes, salt.count, 
       hash, 
       UInt32(rounds), 
       derivedKeyBytes, derivedKeyData.count) 
     } 
    } 

    if (derivationStatus != 0) { 
     print("Error: \(derivationStatus)") 
     return nil; 
    } 



    return derivedKeyData 
} 

我的問題是,它使生成的每個調用相同的派生的密鑰。 我試圖解密是與Rfc2898DeriveBytes .Net的側加密的數據:

var saltBytes = Encoding.ASCII.GetBytes(salt); 
var key = new Rfc2898DeriveBytes(Inputkey, saltBytes); 

var aesAlg = new RijndaelManaged(); 
aesAlg.Key = key.GetBytes(aesAlg.KeySize/8); // default keySize 256 
aesAlg.IV = key.GetBytes(aesAlg.BlockSize/8); // default blockSize 128 

在.NET方面,Rfc2898DeriveBytes返回新的隨機字節集,但我的銀行代碼只產生每個調用相同的順序。 Swift那邊的序列生成有什麼問題?

編輯1:當我使用從.net生成的Rfc2898DeriveBytes的密鑰和IV字節序列試圖解密在.net中加密的數據時,它工作正常。

編輯2:好的,我發現Rfc2898DeriveBytes第一次使用GetBytes方法的結果與Swift PBKDF2結果相同。第二個調用GetBytes給出了完全不同的結果。這是爲什麼?如果我爲此解決方案,那麼我的解密應該工作。

aesAlg.Key = key.GetBytes(aesAlg.KeySize/8); // (1) - the same result as in Swift implementation 
aesAlg.IV = key.GetBytes(aesAlg.BlockSize/8); // (2) - completly different result 

我是否錯誤地初始化了Swift中的IV?

+1

您需要在生產中每次使用不同的鹽。在加密和解密中需要使用相同的IV,一種常見的方法是使用IV來加密數據的前綴,而不需要保密。在aesAlg.IV的情況下,函數初始化了一次,並且對它進行了兩次調用。多次使用同一個密鑰的同一個IV是一個安全問題。 – zaph

+0

@ zaph非常感謝您的回覆。對不起,我還是不明白。對於AES256,IV總是長16字節?你的意思是,GetBytes方法不應該在同一個實例上調用兩次?我可能會問很愚蠢的問題,因爲我在這個主題上是新的。 – PiotrCh

+1

AES IV總是16字節。每次使用相同的加密密鑰時,它需要不同。它最好作爲加密數據的一部分通過解密,通常用於加密數據。只要是隨機的,IV並不重要。如果使用一種方法爲同一個不安全的密鑰生成相同的IV。 – zaph

回答

0

.NET實現實際上是一個流。要從Apple版本獲得相同的答案,您應該在一次調用中要求提供您需要的總字節數,然後將其分成您需要的任何部分。

+0

謝謝你的迴應我會檢查。 – PiotrCh