Получите хэш SHA1 сертификата цепочки ключей macOS в Swift

#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 нужно.