Browse Source

Update README with Password-Based Key Derivation Function example. Add test for PBKDF2

Marcin Krzyżanowski 9 years ago
parent
commit
d3910aae8f
3 changed files with 28 additions and 9 deletions
  1. 4 4
      CryptoSwiftTests/PBKDF2Tests.swift
  2. 13 3
      README.md
  3. 11 2
      Sources/CryptoSwift/PKCS5/PBKDF2.swift

+ 4 - 4
CryptoSwiftTests/PBKDF2Tests.swift

@@ -20,10 +20,10 @@ class PBKDF2Tests: XCTestCase {
     }
 
     func test1() {
-        let p = try! PKCS5.PBKDF2(password: "s33krit".utf8.map({ $0 }), salt: "nacl".utf8.map({ $0 }), iterations: 2, keyLength: 123, hashVariant: .sha1)
-        let value = p.calculate()
-        print(value.toHexString());
-        print("done")
+        let password: [UInt8] = "s33krit".utf8.map {$0}
+        let salt: [UInt8] = "nacl".utf8.map {$0}
+        let value = try! PKCS5.PBKDF2(password: password, salt: salt, iterations: 2, keyLength: 123, hashVariant: .sha1).calculate()
+        XCTAssert(value.toHexString() == "a53cf3df485e5cd91c17c4978048e3ca86e03cced5f748fb55eff9c1edfce7f9f490c0beee768b85c1ba14ec5750cf059fea52565ffd9e4f9dba01c5c953955e7f1012b6a9eb40629ce767982e598df9081048e22781b35187c16d61ac43f69b88630a9e80233b4c58bdc74ea5c06b5bb1b2c2a86e3ddc2775b852c4508ac85a6a47c0e23a3d8dc6e4dca583", "PBKDF2 fail")
     }
 
 }

+ 13 - 3
README.md

@@ -53,13 +53,13 @@ Good mood
 - Output Feedback ([OFB](http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Output_Feedback_.28OFB.29))
 - Counter ([CTR](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_.28CTR.29))
 
+#####Password-Based Key Derivation Function
+- [PBKDF2](http://tools.ietf.org/html/rfc2898#section-5.2) (Password-Based Key Derivation Function 2)
+
 #####Data padding
 - [PKCS#7](http://tools.ietf.org/html/rfc5652#section-6.3)
 - NoPadding
 
-#####Password-Based Key Derivation Function
-- [PBKDF2](http://tools.ietf.org/html/rfc2898#section-5.2) (Password-Based Key Derivation Function 2)
-
 ##Why
 [Why?](https://github.com/krzyzanowskim/CryptoSwift/issues/5) [Because I can](https://github.com/krzyzanowskim/CryptoSwift/issues/5#issuecomment-53379391).
 
@@ -196,6 +196,16 @@ let mac: [UInt8] = try! Authenticator.Poly1305(key: key).authenticate(message)
 let hmac: [UInt8] = try! Authenticator.HMAC(key: key, variant: .sha256).authenticate(message)
 ```
 
+#####Password-Based Key Derivation Function
+
+```swift
+let password: [UInt8] = "s33krit".utf8.map {$0}
+let salt: [UInt8] = "nacl".utf8.map {$0}
+
+let value = try! PKCS5.PBKDF2(password: password, salt: salt, iterations: 4096, hashVariant: .sha256).calculate()
+value.toHexString() // print Hex representation
+```
+
 #####Data Padding
     
 Some content-encryption algorithms assume the input length is a multiple of k octets, where k is greater than one. For such algorithms, the input shall be padded.

+ 11 - 2
Sources/CryptoSwift/PKCS5/PBKDF2.swift

@@ -20,11 +20,18 @@ public extension PKCS5 {
         private let numBlocks: UInt  // l
         private let prf: HMAC
 
-        init(password: [UInt8], salt: [UInt8], iterations: Int /* c */, keyLength: Int /* dkLen */ , hashVariant: HMAC.Variant = .sha256) throws {
+        init(password: [UInt8], salt: [UInt8], iterations: Int = 4096 /* c */, keyLength: Int? = nil /* dkLen */ , hashVariant: HMAC.Variant = .sha256) throws {
             guard let prf = HMAC(key: password, variant: hashVariant) where (iterations > 0) && (password.count > 0) && (salt.count > 0) else {
                 throw Error.InvalidInput
             }
 
+            let keyLengthFinal: Int
+            if let kl = keyLength {
+                keyLengthFinal = kl
+            } else {
+                keyLengthFinal = hashVariant.size
+            }
+
             let hLen = Double(prf.variant.size)
             if keyLength > Int(((pow(2,32) as Double) - 1) * hLen) {
                 throw Error.InvalidInput
@@ -33,7 +40,9 @@ public extension PKCS5 {
             self.salt = salt
             self.iterations = iterations
             self.prf = prf
-            self.numBlocks = UInt(ceil(Double(keyLength) / hLen))  // l = ceil(keyLength / hLen)
+
+
+            self.numBlocks = UInt(ceil(Double(keyLengthFinal) / hLen))  // l = ceil(keyLength / hLen)
         }
 
         func calculate() -> [UInt8] {