Skip to content

Commit

Permalink
Merge pull request #18 from andredsp/master
Browse files Browse the repository at this point in the history
Use salt as an array of bytes instead of String
  • Loading branch information
iosdevzone committed Apr 6, 2016
2 parents 24c1180 + 91f7ce3 commit cf09559
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 3 deletions.
3 changes: 2 additions & 1 deletion DemoPlayground.playground/section-1.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ sha1String

// MARK: - Key Digest Demo
// Data from RFC 6070
let tests = [ ("password", "salt", 1, 20, "0c60c80f961f0e71f3a9b524af6012062fe037a6")]
let tests = [ ("password", "salt", 1, 20, "0c60c80f961f0e71f3a9b524af6012062fe037a6"),
("password", arrayFromString("salt"), 1, 20, "0c60c80f961f0e71f3a9b524af6012062fe037a6")]
for (password, salt, rounds, dkLen, expected) in tests
{
let key = PBKDF.deriveKey(password, salt: salt, prf: .SHA1, rounds: uint(rounds), derivedKeyLength: UInt(dkLen))
Expand Down
22 changes: 22 additions & 0 deletions IDZSwiftCommonCrypto/KeyDerivation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,28 @@ public class PBKDF
return derivedKey
}

///
/// Derives key material from a password and salt.
///
/// -parameter password: the password string, will be converted using UTF8
/// -parameter salt: the salt array of bytes
/// -parameter prf: the pseudo random function
/// -parameter round: the number of rounds
/// -parameter derivedKeyLength: the length of the desired derived key, in bytes.
/// -returns: the derived key
///
public class func deriveKey(password : String, salt : [UInt8], prf: PseudoRandomAlgorithm, rounds: uint, derivedKeyLength: UInt) -> [UInt8]
{
var derivedKey = Array<UInt8>(count:Int(derivedKeyLength), repeatedValue: 0)
let status : Int32 = CCKeyDerivationPBKDF(CCPBKDFAlgorithm(kCCPBKDF2), password, password.lengthOfBytesUsingEncoding(NSUTF8StringEncoding), salt, salt.count, prf.nativeValue(), rounds, &derivedKey, derivedKey.count)
if(status != Int32(kCCSuccess))
{
NSLog("ERROR: CCKeyDerivationPBDK failed with stats \(status).")
fatalError("ERROR: CCKeyDerivationPBDK failed.")
}
return derivedKey
}

//MARK: - Low-level Routines
///
/// Derives key material from a password buffer.
Expand Down
12 changes: 12 additions & 0 deletions IDZSwiftCommonCrypto/Utilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ public func arrayFromHexString(s : String) -> [UInt8]
return a
}

///
/// Converts a Swift UTF-8 String to a Swift array.
///
/// - parameter s: the string
/// - returns: a Swift array
///
public func arrayFromString(s : String) -> [UInt8]
{
let array = [UInt8](s.utf8)
return array
}

///
/// Converts a string of hexadecimal digits to an `NSData` object.
///
Expand Down
19 changes: 18 additions & 1 deletion IDZSwiftCommonCryptoTests/IDZSwiftCommonCryptoTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,8 @@ class IDZSwiftCommonCryptoTests: XCTestCase {
// MARK: - KeyDerivation tests
// See: https://www.ietf.org/rfc/rfc6070.txt
func test_KeyDerivation_deriveKey()
{
{
// Tests with String salt
let tests = [ ("password", "salt", 1, 20, "0c60c80f961f0e71f3a9b524af6012062fe037a6"),
("password", "salt", 2, 20, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957"),
("password", "salt", 4096, 20, "4b007901b765489abead49d926f721d065a429c1"),
Expand All @@ -486,6 +487,22 @@ class IDZSwiftCommonCryptoTests: XCTestCase {
XCTAssertEqual(key, arrayFromHexString(expected), "Obtained correct key (\(keyString) == \(expected)")
}

// Tests with Array salt
let tests2 = [ ("password", arrayFromString("salt"), 1, 20, "0c60c80f961f0e71f3a9b524af6012062fe037a6"),
("password", arrayFromString("salt"), 2, 20, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957"),
("password", arrayFromString("salt"), 4096, 20, "4b007901b765489abead49d926f721d065a429c1"),
// ("password", "salt", 16777216, 20, "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984"),
("passwordPASSWORDpassword", arrayFromString("saltSALTsaltSALTsaltSALTsaltSALTsalt"), 4096, 25, "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038"),
("pass\0word", arrayFromString("sa\0lt"), 4096, 16, "56fa6aa75548099dcc37d7f03425e0c3"),
]
for (password, salt, rounds, dkLen, expected) in tests2
{
let key = PBKDF.deriveKey(password, salt: salt, prf: .SHA1, rounds: uint(rounds), derivedKeyLength: UInt(dkLen))
let keyString = hexStringFromArray(key)

XCTAssertEqual(key, arrayFromHexString(expected), "Obtained correct key (\(keyString) == \(expected)")
}

}

// MARK: - Random tests
Expand Down
2 changes: 1 addition & 1 deletion README.playground/section-17.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
let keys6 = PBKDF.deriveKey("password", salt: "salt", prf: .SHA1, rounds: 1, derivedKeyLength: 20)
let keys6 = PBKDF.deriveKey("password", salt: arrayFromString("salt"), prf: .SHA1, rounds: 1, derivedKeyLength: 20)
// RFC 6070 - Should derive 0c60c80f961f0e71f3a9b524af6012062fe037a6
let expectedRFC6070 = arrayFromHexString("0c60c80f961f0e71f3a9b524af6012062fe037a6")
assert(keys6 == expectedRFC6070)

0 comments on commit cf09559

Please sign in to comment.