Swift SecKeyRawSign返回错误-1,“1”;一般性错误;?
我正在开发一个iOS应用程序,该应用程序需要在设备上生成密钥对,将私钥存储在安全Enclave中,然后稍后访问它以用于签名(永远不需要导出)。当我签名时,我总是使用SHA256对数据进行散列,然后是几个堆栈溢出答案,当我打印结果时,它似乎工作正常。但是,在从密钥链获取有效的私钥引用、对要签名的数据进行散列并指定它是SHA256散列之后,SecKeyRawSign仍然返回-1。这只是列为“一般错误”,我的设置似乎应该是有效的。如果您能深入了解问题所在,我们将不胜感激。以下是我生成和签名的方法:Swift SecKeyRawSign返回错误-1,“1”;一般性错误;?,swift,security,public-key-encryption,sha256,Swift,Security,Public Key Encryption,Sha256,我正在开发一个iOS应用程序,该应用程序需要在设备上生成密钥对,将私钥存储在安全Enclave中,然后稍后访问它以用于签名(永远不需要导出)。当我签名时,我总是使用SHA256对数据进行散列,然后是几个堆栈溢出答案,当我打印结果时,它似乎工作正常。但是,在从密钥链获取有效的私钥引用、对要签名的数据进行散列并指定它是SHA256散列之后,SecKeyRawSign仍然返回-1。这只是列为“一般错误”,我的设置似乎应该是有效的。如果您能深入了解问题所在,我们将不胜感激。以下是我生成和签名的方法: p
private func genKeyPair() -> (privateAlias: String, publicKey: NSData)? {
// Generate a keyhandle, which will be returned as an alias for the private key
let numBytes = Int(keyHandleLength)
var randomBytes = [UInt8](count: numBytes, repeatedValue: 0)
SecRandomCopyBytes(kSecRandomDefault, numBytes, &randomBytes)
let data = NSData(bytes: &randomBytes, length: numBytes)
let alias = data.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
let access = SecAccessControlCreateWithFlags(nil, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, .TouchIDCurrentSet, nil)!
// Key pair parameters
var keyParams: [String:AnyObject] = [
kSecAttrKeyType as String: kSecAttrKeyTypeEC,
kSecAttrKeySizeInBits as String: 256
]
// Private key parameters
keyParams[kSecPrivateKeyAttrs as String] = [
kSecAttrIsPermanent as String: true,
kSecAttrLabel as String: alias,
kSecAttrApplicationTag as String: applicationTag,
kSecAttrAccessControl as String: access
]
// Public key parameters
keyParams[kSecPublicKeyAttrs as String] = [
kSecAttrIsPermanent as String: true,
kSecAttrLabel as String: alias + "-pub",
kSecAttrApplicationTag as String: applicationTag
]
var pubKeyRef, privKeyRef: SecKey?
var err = SecKeyGeneratePair(keyParams, &pubKeyRef, &privKeyRef)
guard let _ = pubKeyRef where err == errSecSuccess else {
print("Error while generating key pair: \(err).")
return nil
}
// Export the public key for application use
let query = [
kSecClass as String: kSecClassKey,
kSecAttrLabel as String: alias + "-pub",
kSecAttrKeyType as String: kSecAttrKeyTypeEC,
kSecReturnData as String: true
]
var pubKeyOpt: AnyObject?
err = SecItemCopyMatching(query, &pubKeyOpt)
if let pubKey = pubKeyOpt as? NSData where err == errSecSuccess {
print("Successfully retrieved public key!")
return (alias, pubKey)
} else {
print("Error retrieving public key: \(err).")
return nil
}
}
private func sign(bytes data: NSData, usingKeyWithAlias alias: String) -> NSData? {
let query = [
kSecClass as String: kSecClassKey,
kSecAttrLabel as String: alias,
kSecAttrApplicationTag as String: applicationTag,
kSecAttrKeyType as String: kSecAttrKeyTypeEC,
kSecReturnRef as String: true
]
var privateKey: AnyObject?
var error = SecItemCopyMatching(query, &privateKey)
guard error == errSecSuccess else {
print("Could not obtain reference to private key with alias \"\(alias)\", error: \(error).")
return nil
}
print("\nData: \(data)")
print("Length: \(data.length)")
let hashedData = NSMutableData(length: Int(CC_SHA256_DIGEST_LENGTH))!
CC_SHA256(data.bytes, CC_LONG(data.length), UnsafeMutablePointer(hashedData.mutableBytes))
print("\nHashed data: \(hashedData)")
print("Length: \(hashedData.length)")
var signedHashLength = SecKeyGetBlockSize(privateKey as! SecKeyRef)
let signedHash = NSMutableData(length: signedHashLength)!
error = SecKeyRawSign(privateKey as! SecKeyRef, .PKCS1SHA256, UnsafePointer<UInt8>(hashedData.mutableBytes), hashedData.length, UnsafeMutablePointer<UInt8>(signedHash.mutableBytes), &signedHashLength)
print("\nSigned hash: \(signedHash)")
print("Length: \(signedHashLength)\n")
guard error == errSecSuccess else {
print("Failed to sign data, error: \(error).")
return nil
}
return signedHash
}
private func genKeyPair()->(privateAlias:String,publicKey:NSData)?{
//生成一个keyhandle,它将作为私钥的别名返回
设numBytes=Int(keyHandleLength)
var randomBytes=[UInt8](计数:numBytes,repeatedValue:0)
SecRandomCopyBytes(kSecRandomDefault、numBytes和randomBytes)
let data=NSData(字节:&randomBytes,长度:numBytes)
让alias=data.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue:0))
让access=SecAccessControlCreateWithFlags(nil,ksecattraccessiblewwhenpasscodestetthissdeviceonly,.TouchIDCurrentSet,nil)!
//密钥对参数
var keyParams:[字符串:AnyObject]=[
kSecAttrKeyType作为字符串:KSECATTRKEYTYPEC,
kSecAttrKeySizeInBits作为字符串:256
]
//私钥参数
keyParams[kSecPrivateKeyAttrs作为字符串]=[
kSecAttrIsPermanent作为字符串:true,
kSecAttrLabel作为字符串:别名,
kSecAttrApplicationTag作为字符串:applicationTag,
kSecAttrAccessControl作为字符串:访问
]
//公钥参数
keyParams[kSecPublicKeyAttrs作为字符串]=[
kSecAttrIsPermanent作为字符串:true,
kSecAttrLabel作为字符串:别名+“-pub”,
kSecAttrApplicationTag作为字符串:applicationTag
]
var pubKeyRef,privKeyRef:SecKey?
var err=SecKeyGeneratePair(keyParams、&pubKeyRef、&privKeyRef)
guard let=pubKeyRef,其中err==errSecSuccess-else{
打印(“生成密钥对时出错:\(错误)。”)
归零
}
//导出公钥以供应用程序使用
让查询=[
kSecClass作为字符串:kSecClassKey,
kSecAttrLabel作为字符串:别名+“-pub”,
kSecAttrKeyType作为字符串:KSECATTRKEYTYPEC,
kSecReturnData作为字符串:true
]
var pubKeyOpt:AnyObject?
err=SecItemCopyMatching(查询和pubKeyOpt)
如果让pubKey=pubKeyOpt作为NSData,其中err==errSecSuccess{
打印(“已成功检索公钥!”)
return(别名,pubKey)
}否则{
打印(“检索公钥时出错:\(错误)。”)
归零
}
}
专用func符号(字节数据:NSData,usingKeyWithAlias别名:String)->NSData?{
让查询=[
kSecClass作为字符串:kSecClassKey,
kSecAttrLabel作为字符串:别名,
kSecAttrApplicationTag作为字符串:applicationTag,
kSecAttrKeyType作为字符串:KSECATTRKEYTYPEC,
kSecReturnRef作为字符串:true
]
var privateKey:任何对象?
var error=SecItemCopyMatching(查询和私钥)
保护错误==errSecSuccess-else{
打印(“无法获取对别名为\(别名)\”的私钥的引用,错误:\(错误)。”
归零
}
打印(“\n数据:\(数据)”)
打印(“长度:\(data.Length)”)
让hashedData=NSMutableData(长度:Int(CC_SHA256_DIGEST_length))!
CC_SHA256(data.bytes,CC_LONG(data.length),unsafemtablepointer(hashedData.mutableBytes))
打印(“\n隐藏数据:\(哈希数据)”)
打印(“长度:\(hashedData.Length)”)
var signedHashLength=SecKeyGetBlockSize(privateKey为!SecKeyRef)
让signedHash=NSMutableData(长度:signedHashLength)!
error=SecKeyRawSign(privateKey为!SecKeyRef、.PKCS1SHA256、UnsafePointer(hashedData.mutableBytes)、hashedData.length、UnsafeMutablePointer(signedHash.mutableBytes)和signedHashLength)
打印(“\n签名哈希:\(签名哈希)”)
打印(“长度:\(signedHashLength)\n”)
保护错误==errSecSuccess-else{
打印(“签署数据失败,错误:\(错误)。”)
归零
}
返回签名哈希
}