SecKeyCreateSignature 从哪里获取钥匙串签名授权对话框的密钥名称?
Where does SecKeyCreateSignature get the key name for Keychain signing authorization dialog?
我注意到 Keychain 中的某些键在 Keychain 签名对话框中的显示方式有所不同,我无法弄清楚为什么有些键以特定方式显示,而另一些则不是。
这里是一些测试代码,使用钥匙串中的身份来签署数据样本位。
func testCreateSignature() throws {
let query: [String: Any] = [kSecClass as String: kSecClassIdentity,
kSecMatchLimit as String: kSecMatchLimitAll,
kSecReturnAttributes as String: false,
kSecReturnRef as String: true,
kSecReturnData as String: true]
var resultsRef: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &resultsRef)
guard status == errSecSuccess else { throw SecurityError.unhandledError(status: status) }
guard let results = resultsRef as? [[String:Any]] else {
throw SecurityError.unexpectedCertificateData
}
let data = Data([0xDE, 0xAD, 0xBE, 0xEF])
var privateKey: SecKey!
for result in results {
let secIdentity = result[kSecValueRef as String] as! SecIdentity
try SecIdentityCopyPrivateKey(secIdentity, &privateKey).check()
var error: Unmanaged<CFError>?
let signature = SecKeyCreateSignature(privateKey, .rsaSignatureMessagePKCS1v15SHA1, data as CFData, &error)!
if let error = error {
throw error.takeRetainedValue()
}
print(signature)
}
}
当代码尝试使用 Xcode 安装的密钥之一进行代码签名时,生成的对话框如下所示:
但是,当代码尝试使用我安装的密钥时,无论钥匙串中密钥上的标签是什么,它总是如下所示:
当我的应用程序尝试使用密钥进行签名时,我希望用户看到该应用程序要使用的密钥名称,而不仅仅是通用的“privateKey”,但我找不到此信息可能在哪里存储在密钥上。
我已经检查了身份和私钥的 kSecAttrLabel
和 kSecAttrApplicationLabel
属性,但找不到出现在对话框中的文本。
我找到了。它是钥匙串项的访问控制列表的 属性。参见 'descriptor' param for SecAccessCreate。
如果您在导入密钥时没有指定自定义 ACL,它将默认为“privateKey”。
我正在使用 SecPKCS12Import 导入 .pfx
文件。我试图将 options
参数中的 kSecImportExportAccess
键设置为自定义 SecAccess
对象,但它始终会使用默认 ACL 导入。
我最终重构了代码以使用 SecItemImport 而不是导入 .pfx
文件并提供了自定义 SecAccess
实例:
static func importIdentity(contentsOf url: URL, password: String) throws {
let data = try Data.init(contentsOf: url)
var access: SecAccess!
try SecAccessCreate("License Key" as CFString, nil, &access).check()
var keychain: SecKeychain!
var outItems: CFArray?
let filename: CFString? = url.isFileURL ? url.lastPathComponent as CFString : nil
var inputFormat: SecExternalFormat = .formatPKCS12
var itemType: SecExternalItemType = .itemTypeAggregate
let unmanagedPassword = Unmanaged<AnyObject>.passRetained(password as AnyObject)
let unmanagedAccess = Unmanaged<SecAccess>.passRetained(access)
var params: SecItemImportExportKeyParameters = SecItemImportExportKeyParameters(version: UInt32(SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION),
flags: .importOnlyOne,
passphrase: unmanagedPassword,
alertTitle: nil,
alertPrompt: nil,
accessRef: unmanagedAccess,
keyUsage: nil,
keyAttributes: nil)
try SecKeychainCopyDefault(&keychain).check()
try SecItemImport(data as CFData, filename, &inputFormat, &itemType, [], ¶ms, keychain, &outItems).check()
}
如上导入身份将导致在签名对话框中显示“许可证密钥”而不是“privateKey”。
我注意到 Keychain 中的某些键在 Keychain 签名对话框中的显示方式有所不同,我无法弄清楚为什么有些键以特定方式显示,而另一些则不是。
这里是一些测试代码,使用钥匙串中的身份来签署数据样本位。
func testCreateSignature() throws {
let query: [String: Any] = [kSecClass as String: kSecClassIdentity,
kSecMatchLimit as String: kSecMatchLimitAll,
kSecReturnAttributes as String: false,
kSecReturnRef as String: true,
kSecReturnData as String: true]
var resultsRef: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &resultsRef)
guard status == errSecSuccess else { throw SecurityError.unhandledError(status: status) }
guard let results = resultsRef as? [[String:Any]] else {
throw SecurityError.unexpectedCertificateData
}
let data = Data([0xDE, 0xAD, 0xBE, 0xEF])
var privateKey: SecKey!
for result in results {
let secIdentity = result[kSecValueRef as String] as! SecIdentity
try SecIdentityCopyPrivateKey(secIdentity, &privateKey).check()
var error: Unmanaged<CFError>?
let signature = SecKeyCreateSignature(privateKey, .rsaSignatureMessagePKCS1v15SHA1, data as CFData, &error)!
if let error = error {
throw error.takeRetainedValue()
}
print(signature)
}
}
当代码尝试使用 Xcode 安装的密钥之一进行代码签名时,生成的对话框如下所示:
但是,当代码尝试使用我安装的密钥时,无论钥匙串中密钥上的标签是什么,它总是如下所示:
当我的应用程序尝试使用密钥进行签名时,我希望用户看到该应用程序要使用的密钥名称,而不仅仅是通用的“privateKey”,但我找不到此信息可能在哪里存储在密钥上。
我已经检查了身份和私钥的 kSecAttrLabel
和 kSecAttrApplicationLabel
属性,但找不到出现在对话框中的文本。
我找到了。它是钥匙串项的访问控制列表的 属性。参见 'descriptor' param for SecAccessCreate。
如果您在导入密钥时没有指定自定义 ACL,它将默认为“privateKey”。
我正在使用 SecPKCS12Import 导入 .pfx
文件。我试图将 options
参数中的 kSecImportExportAccess
键设置为自定义 SecAccess
对象,但它始终会使用默认 ACL 导入。
我最终重构了代码以使用 SecItemImport 而不是导入 .pfx
文件并提供了自定义 SecAccess
实例:
static func importIdentity(contentsOf url: URL, password: String) throws {
let data = try Data.init(contentsOf: url)
var access: SecAccess!
try SecAccessCreate("License Key" as CFString, nil, &access).check()
var keychain: SecKeychain!
var outItems: CFArray?
let filename: CFString? = url.isFileURL ? url.lastPathComponent as CFString : nil
var inputFormat: SecExternalFormat = .formatPKCS12
var itemType: SecExternalItemType = .itemTypeAggregate
let unmanagedPassword = Unmanaged<AnyObject>.passRetained(password as AnyObject)
let unmanagedAccess = Unmanaged<SecAccess>.passRetained(access)
var params: SecItemImportExportKeyParameters = SecItemImportExportKeyParameters(version: UInt32(SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION),
flags: .importOnlyOne,
passphrase: unmanagedPassword,
alertTitle: nil,
alertPrompt: nil,
accessRef: unmanagedAccess,
keyUsage: nil,
keyAttributes: nil)
try SecKeychainCopyDefault(&keychain).check()
try SecItemImport(data as CFData, filename, &inputFormat, &itemType, [], ¶ms, keychain, &outItems).check()
}
如上导入身份将导致在签名对话框中显示“许可证密钥”而不是“privateKey”。