Swift Language
PBKDF2 Nyckeldivation
Sök…
Lösenordsbaserad nyckeldivation 2 (Swift 3)
Lösenordsbaserad nyckelavledning kan användas både för att hämta en krypteringsnyckel från lösenordstext och spara ett lösenord för autentiseringsändamål.
Det finns flera hashalgoritmer som kan användas inklusive SHA1, SHA256, SHA512 som tillhandahålls med detta exempelkod.
Rundparametern används för att göra beräkningen långsam så att en angripare måste spendera betydande tid på varje försök. Typiska fördröjningsvärden faller mellan 100 och 500 m, kortare värden kan användas om det är oacceptabla prestanda.
Detta exempel kräver Common Crypto
Det är nödvändigt att ha en överbryggande rubrik till projektet:
#import <CommonCrypto/CommonCrypto.h>
Lägg till Security.framework
till projektet.
parametrar:
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:CCPBKDFAlgorithm(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
}
Exempel på användning:
let password = "password"
//let salt = "saltData".data(using: String.Encoding.utf8)!
let salt = Data(bytes: [0x73, 0x61, 0x6c, 0x74, 0x44, 0x61, 0x74, 0x61])
let keyByteCount = 16
let rounds = 100000
let derivedKey = pbkdf2SHA1(password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds)
print("derivedKey (SHA1): \(derivedKey! as NSData)")
Exempel på utgång:
derivedKey (SHA1): <6b9d4fa3 0385d128 f6d196ee 3f1d6dbf>
Lösenordsbaserad nyckeldivation 2 (Swift 2.3)
Se Swift 3-exempel för användningsinformation och anteckningar
func pbkdf2SHA1(password: String, salt: [UInt8], keyCount: Int, rounds: Int) -> [UInt8]? {
return pbkdf2(CCPBKDFAlgorithm(kCCPRFHmacAlgSHA1), password:password, salt:salt, keyCount:keyCount, rounds:UInt32(rounds))
}
func pbkdf2SHA256(password: String, salt: [UInt8], keyCount: Int, rounds: Int) -> [UInt8]? {
return pbkdf2(CCPBKDFAlgorithm(kCCPRFHmacAlgSHA256), password:password, salt:salt, keyCount:keyCount, rounds:UInt32(rounds))
}
func pbkdf2SHA512(password: String, salt: [UInt8], keyCount: Int, rounds: Int) -> [UInt8]? {
return pbkdf2(CCPBKDFAlgorithm(kCCPRFHmacAlgSHA512), password:password, salt:salt, keyCount:keyCount, rounds:UInt32(rounds))
}
func pbkdf2(hash :CCPBKDFAlgorithm, password: String, salt: [UInt8], keyCount: Int, rounds: UInt32!) -> [UInt8]! {
let derivedKey = [UInt8](count:keyCount, repeatedValue:0)
let passwordData = password.dataUsingEncoding(NSUTF8StringEncoding)!
let derivationStatus = CCKeyDerivationPBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
UnsafePointer<Int8>(passwordData.bytes), passwordData.length,
UnsafePointer<UInt8>(salt), salt.count,
CCPseudoRandomAlgorithm(hash),
rounds,
UnsafeMutablePointer<UInt8>(derivedKey),
derivedKey.count)
if (derivationStatus != 0) {
print("Error: \(derivationStatus)")
return nil;
}
return derivedKey
}
Exempel på användning:
let password = "password"
// let salt = [UInt8]("saltData".utf8)
let salt = [UInt8]([0x73, 0x61, 0x6c, 0x74, 0x44, 0x61, 0x74, 0x61])
let rounds = 100_000
let keyCount = 16
let derivedKey = pbkdf2SHA1(password, salt:salt, keyCount:keyCount, rounds:rounds)
print("derivedKey (SHA1): \(NSData(bytes:derivedKey!, length:derivedKey!.count))")
Exempel på utgång:
derivedKey (SHA1): <6b9d4fa3 0385d128 f6d196ee 3f1d6dbf>
Lösenordsbaserad nyckeldivationskalibrering (Swift 2.3)
Se Swift 3-exempel för användningsinformation och anteckningar
func pbkdf2SHA1Calibrate(password:String, salt:[UInt8], msec:Int) -> UInt32 {
let actualRoundCount: UInt32 = CCCalibratePBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
password.utf8.count,
salt.count,
CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1),
kCCKeySizeAES256,
UInt32(msec));
return actualRoundCount
}
Exempel på användning:
let saltData = [UInt8]([0x73, 0x61, 0x6c, 0x74, 0x44, 0x61, 0x74, 0x61])
let passwordString = "password"
let delayMsec = 100
let rounds = pbkdf2SHA1Calibrate(passwordString, salt:saltData, msec:delayMsec)
print("For \(delayMsec) msec delay, rounds: \(rounds)")
Exempel på utgång:
För fördröjning på 100 ms, omgångar: 94339
Lösenordsbaserad nyckeldivationskalibrering (Swift 3)
Bestäm antalet PRF-rundor som ska användas för en specifik fördröjning på den aktuella plattformen.
Flera parametrar är som standard för representativa värden som inte borde väsentligt påverka rundantalet.
password Sample password.
salt Sample salt.
msec Targeted duration we want to achieve for a key derivation.
returns The number of iterations to use for the desired processing time.
func pbkdf2SHA1Calibrate(password: String, salt: Data, msec: Int) -> UInt32 {
let actualRoundCount: UInt32 = CCCalibratePBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
password.utf8.count,
salt.count,
CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1),
kCCKeySizeAES256,
UInt32(msec));
return actualRoundCount
}
Exempel på användning:
let saltData = Data(bytes: [0x73, 0x61, 0x6c, 0x74, 0x44, 0x61, 0x74, 0x61])
let passwordString = "password"
let delayMsec = 100
let rounds = pbkdf2SHA1Calibrate(password:passwordString, salt:saltData, msec:delayMsec)
print("For \(delayMsec) msec delay, rounds: \(rounds)")
Exempel på utgång:
For 100 msec delay, rounds: 93457