#macos #certificate #keychain #sha1 #cfdata
#macos #сертификат #связка ключей #sha1 #cfdata
Вопрос:
Я извлек набор сертификатов в своей цепочке ключей, используя этот код:
let query: [String: Any] = [
kSecClass as String: kSecClassCertificate,
kSecMatchLimit as String: kSecMatchLimitAll,
kSecReturnAttributes as String: false,
kSecReturnData as String: true
]
var result: CFTypeRef?
var results : Set<CertsResult> = []
let status = SecItemCopyMatching(query as CFDictionary, amp;result)
//[Check status]
guard let certificateData = result as? [CFData] else {
//[Handle]
}
Отсюда я просматриваю certificateData
и собираю информацию о сертификатах, но мне также нужно получить хэш SHA1 сертификатов. Я понял из исследования, что мне нужно использовать import CommonCrypto
и CC_SHA1
, но то, что я прочитал, не использует CFData
.
Есть ли хороший способ перейти от этой точки к ее SHA1?
Ответ №1:
Вы можете добиться этого, выполнив хэш самостоятельно. Отпечатки пальцев не являются частью самого сертификата. Подробнее об этом здесь.
import CryptoKit
let certificate = ...
let der = SecCertificateCopyData(certificate) as Data
let sha1 = Insecure.SHA1.hash(data: der)
let sha256 = SHA256.hash(data: der)
Это также может быть создано в расширении. Я использовал CommonCrypto в расширении.
import CommonCrypto
extension SecCertificate {
var sha1: Data {
var digest = [UInt8](repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH))
let der = SecCertificateCopyData(self) as Data
_ = CC_SHA1(Array(der), CC_LONG(der.count), amp;digest)
return Data(digest)
}
var sha256: Data {
var digest = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
let der = SecCertificateCopyData(self) as Data
_ = CC_SHA256(Array(der), CC_LONG(der.count), amp;digest)
return Data(digest)
}
}
Я хотел бы упомянуть, что хэши сертификатов SHA-1 устарели с 2017 года, а веб-сайты и технологические гиганты начинают отказываться от их поддержки.
Пример игровой площадки
import CryptoKit
import Foundation
class CertificateStuff: NSObject, URLSessionDelegate {
func urlSession(
_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void
) {
guard let serverTrust = challenge.protectionSpace.serverTrust else {
completionHandler(.rejectProtectionSpace, nil)
return
}
for index in 0 ..< SecTrustGetCertificateCount(serverTrust) {
let certificate = SecTrustGetCertificateAtIndex(serverTrust, index)!
let der = SecCertificateCopyData(certificate)
let sha1 = Insecure.SHA1.hash(data: der as Data)
let sha256 = SHA256.hash(data: der as Data)
print(certificate)
print(sha1)
print(sha256)
print()
}
completionHandler(.performDefaultHandling, nil)
}
func request(_ done: @escaping (Result<Data, Error>) -> Void) {
let url = URL(string: "https://security.stackexchange.com/questions/14330/what-is-the-actual-value-of-a-certificate-fingerprint")!
let request = URLRequest(url: url)
URLSession(configuration: .default, delegate: self, delegateQueue: nil).dataTask(with: request) { (d, r, e) in
if let e = e {
print(e)
return
}
print(d!)
}.resume()
}
}
CertificateStuff().request { result in print(result) }
Комментарии:
1. Спасибо! И спасибо за предупреждение об устаревании SHA-1, это будет полезно в некоторых предстоящих обсуждениях
2. Ах, потрясающее обновление! Знаете ли вы, есть ли какие-либо способы сделать это до версии 10.15? Я предполагаю, что будет задействован CC_SHA1…
3. @ZAD-Man проверьте обновленный ответ. Я добавил общее криптографическое расширение к объекту SecCertificate
4. О, чувак, большое спасибо. Я был так близок, но я все еще новичок в Swift и не мог понять, как преобразовать данные в то, что
CC_SHA1
нужно.