#swift #macos #keychain
#swift #macos #связка ключей
Вопрос:
Я заметил разницу между определенными ключами в связке ключей в отношении того, как они отображаются в диалоговом окне подписи цепочки ключей, и я не могу понять, почему некоторые отображаются определенным образом, а другие — нет.
Вот некоторый тестовый код для использования идентификаторов в цепочке ключей для подписи образца бита данных.
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, amp;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, amp;privateKey).check()
var error: Unmanaged<CFError>?
let signature = SecKeyCreateSignature(privateKey, .rsaSignatureMessagePKCS1v15SHA1, data as CFData, amp;error)!
if let error = error {
throw error.takeRetainedValue()
}
print(signature)
}
}
Когда код пытается использовать один из ключей, установленных Xcode для подписи кода, результирующее диалоговое окно выглядит следующим образом:
Однако, когда код пытается использовать ключ, который я установил, независимо от того, какая метка на ключе в связке ключей, она всегда выглядит так:
Когда мое приложение пытается использовать ключ для подписи, я бы хотел, чтобы пользователь видел имя ключа, который приложение хочет использовать, вместо обычного «PrivateKey», но я не могу найти, где эта информация может храниться в ключе.
Я проверил kSecAttrLabel
и kSecAttrApplicationLabel
атрибуты обоих идентификаторов и закрытых ключей и не могу найти текст, который появляется в диалогах.
Комментарии:
1. Я полагаю, что вышеупомянутый создается с использованием сертификата вместо закрытого ключа . Я не слишком уверен в процессе подписания приложения, но я полагаю, что вы создаете CSR с использованием сертификата или создаете сертификат как CA. В любом случае, приведенный выше, вероятно, получает имя из поля сертификата, а не из поля ключа
Ответ №1:
Я нашел это. Это свойство списка управления доступом элемента цепочки ключей. См. Параметр ‘descriptor’ для SecAccessCreate .
Если вы не укажете пользовательский ACL при импорте ключа, по умолчанию он будет «PrivateKey».
Я использовал SecPKCS12Import для импорта .pfx
файла. Я попытался установить kSecImportExportAccess
ключ в options
параметре для пользовательского 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, amp;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(amp;keychain).check()
try SecItemImport(data as CFData, filename, amp;inputFormat, amp;itemType, [], amp;params, keychain, amp;outItems).check()
}
Импорт идентификатора, как указано выше, приведет к отображению «Лицензионного ключа» в диалоговом окне подписи, а не «PrivateKey».