- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我正在尝试从 Swift 调用 CCKeyDerivationPBKDF。
我已经在我的 Project-Bridging-Header.h 中导入了所需的 header :
#import <CommonCrypto/CommonKeyDerivation.h>
(顺便说一句,桥接 header 似乎可以正常工作以在我的项目中导入其他 Objective C 代码)。
在 Xcode 中,我可以从我的 .swift 文件跳转到此处显示的定义:
int
CCKeyDerivationPBKDF( CCPBKDFAlgorithm algorithm, const char *password, size_t passwordLen,
const uint8_t *salt, size_t saltLen,
CCPseudoRandomAlgorithm prf, uint rounds,
uint8_t *derivedKey, size_t derivedKeyLen)
最后,当我尝试像这样调用函数时:
let result = CCKeyDerivationPBKDF(CCPBKDFAlgorithm(kCCPBKDF2), NSString(password).UTF8String, size_t(passwordLength), UnsafePointer<UInt8>(salt.bytes), size_t(salt.length), CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256), uint(actualRoundCount), UnsafeMutablePointer<UInt8>(derivedKey.mutableBytes), size_t(derivedKey.length));
...我收到此编译器错误:
Cannot invoke 'init' with an argument list of type '(CCPBKDFAlgorithm, UnsafePointer, size_t, UnsafePointer, size_t, CCPseudoRandomAlgorithm, uint, UnsafeMutablePointer, size_t)'
我相信所有的转换都是正确的(实际上编译器错误帮助我识别每个参数的每个问题)——这让我认为编译器理解我调用 CCKeyDerivationPBKDF 的意图。
但是,在所有其他转换错误消失之后,编译器感到困惑,并认为我正在尝试构造一个带有初始化程序的类。
希望有人能指出我方法的错误。
(Xcode 6 测试版 7)
根据要求,上下文中的完整代码:
class func generateAesKeyForPassword(password: String, salt: NSData, roundCount: UInt?, error: NSErrorPointer) -> (key: NSData, actualRoundCount: UInt)?
{
let derivedKey = NSMutableData(length: kCCKeySizeAES256)
let passwordLength = size_t(password.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))
var actualRoundCount: UInt
if roundCount != nil
{
actualRoundCount = roundCount!
}
else
{
actualRoundCount = UInt(CCCalibratePBKDF(CCPBKDFAlgorithm(kCCPBKDF2), passwordLength, UInt(salt.length), CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256), UInt(derivedKey.length), UInt32(300) /* milliseconds */));
}
let result = CCKeyDerivationPBKDF(CCPBKDFAlgorithm(kCCPBKDF2), NSString(password).UTF8String, size_t(passwordLength), UnsafePointer<UInt8>(salt.bytes), size_t(salt.length), CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256), uint(actualRoundCount), UnsafeMutablePointer<UInt8>(derivedKey.mutableBytes), size_t(derivedKey.length));
if result != 0
{
let errorDescription = "CCKeyDerivationPBKDF failed with error: '\(result)'"
error.memory = MyError(domain: ClientErrorType.errorDomain, code: Int(result), descriptionText: errorDescription)
return nil
}
return (NSData(data: derivedKey), actualRoundCount)
}
最佳答案
基于密码的 key 派生既可用于从密码文本派生加密 key ,也可用于保存密码以进行身份验证。
可以使用多种哈希算法,包括此示例代码提供的 SHA1、SHA256、SHA512。
rounds 参数用于降低计算速度,这样攻击者就必须在每次尝试上花费大量时间。典型的延迟值在 100 毫秒到 500 毫秒之间,如果性能 Not Acceptable ,可以使用更短的值。
这个例子需要通用加密
必须要有项目的桥接头:
#import <CommonCrypto/CommonCrypto.h>
添加Security.framework
到项目。
参数:
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
}
示例用法:
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)")
示例输出:
derivedKey (SHA1): <6b9d4fa3 0385d128 f6d196ee 3f1d6dbf>
对实例方法的参数类型和类进行细微更改以进行测试。
func generateAesKeyForPassword(password: String, salt: NSData, roundCount: Int?, error: NSErrorPointer) -> (key: NSData, actualRoundCount: UInt32)?
{
let nsDerivedKey = NSMutableData(length: kCCKeySizeAES256)
var actualRoundCount: UInt32
// Create Swift intermediates for clarity in function calls
let algorithm: CCPBKDFAlgorithm = CCPBKDFAlgorithm(kCCPBKDF2)
let prf: CCPseudoRandomAlgorithm = CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256)
let saltBytes = UnsafePointer<UInt8>(salt.bytes)
let saltLength = size_t(salt.length)
let nsPassword = password as NSString
let nsPasswordPointer = UnsafePointer<Int8>(nsPassword.cStringUsingEncoding(NSUTF8StringEncoding))
let nsPasswordLength = size_t(nsPassword.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))
var nsDerivedKeyPointer = UnsafeMutablePointer<UInt8>(nsDerivedKey.mutableBytes)
let nsDerivedKeyLength = size_t(nsDerivedKey.length)
let msec: UInt32 = 300
if roundCount != nil {
actualRoundCount = UInt32(roundCount!)
}
else {
actualRoundCount = CCCalibratePBKDF(
algorithm,
nsPasswordLength,
saltLength,
prf,
nsDerivedKeyLength,
msec);
}
let result = CCKeyDerivationPBKDF(
algorithm,
nsPasswordPointer, nsPasswordLength,
saltBytes, saltLength,
prf, actualRoundCount,
nsDerivedKeyPointer, nsDerivedKeyLength)
if result != 0 {
let errorDescription = "CCKeyDerivationPBKDF failed with error: '\(result)'"
// error.memory = MyError(domain: ClientErrorType.errorDomain, code: Int(result), descriptionText: errorDescription)
return nil
}
return (nsDerivedKey, actualRoundCount)
}
//附加奖励:
func salt(#length:UInt) -> NSData {
let salt = NSMutableData(length: Int(length))
var saltPointer = UnsafeMutablePointer<UInt8>(salt.mutableBytes)
SecRandomCopyBytes(kSecRandomDefault, length, saltPointer);
return salt
}
//测试调用:
let password = "test pass"
let salt = self.salt(length:32)
let roundCount = 300
var error: NSError?
let result = self.generateAesKeyForPassword(password, salt:salt, roundCount:roundCount, error:&error)
println("result: \(result)")
输出:
result: Optional((<d279ab8d 8ace67b7 abec844c b9979d20 f2bb0a7f 5af70502 085bf1e4 1016b20c>, 300))
关于Swift:如何从 Swift 调用 CCKeyDerivationPBKDF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25691613/
我正在使用 CCKeyDerivationPBKDF 在并发环境中生成和验证密码哈希,我想知道它是否线程安全。该函数的文档根本没有提到线程安全,因此我目前使用锁是为了安全起见,但如果不需要,我宁愿不使
已阅读 Rob Napier 在 Properly Encrypting with CommonCrypto 上发表的博客文章我仍然无法理解为什么增加哈希迭代次数会使攻击者“浪费一些时间”。 CCKe
我正在尝试将密码加密功能写入我的应用程序,遵循 this article . 我编写了一个运行 CCCalibratePBKDF 函数并输出回合数的函数。 const uint32_t oneSeco
我在使用 CCKeyDerivationPBKDF 获取伪随机生成的派生 key 时遇到问题。 这是我使用的 @zaph 代码: // password password String
我正在尝试从 Swift 调用 CCKeyDerivationPBKDF。 我已经在我的 Project-Bridging-Header.h 中导入了所需的 header : #import (顺便
当我使用 CCKeyDerivationPBKDF 时来自 #import , 它返回 -1这是一个未定义的结果。我不知道我是否错过了什么。如果我使用 HMAC MD5 它可以返回成功或其他算法,并
我是一名优秀的程序员,十分优秀!