Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use salt as an array of bytes instead of String #18

Merged
merged 4 commits into from
Apr 6, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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)