0

我已经使用以下代码在我的钥匙串中检索了一组证书:

    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, &result)
    //[Check status]

    guard let certificateData = result as? [CFData] else {
        //[Handle]
    }

从这里,我循环certificateData并收集有关证书的信息,但我还需要获取证书的 SHA1 哈希。我从研究中收集到我需要使用import CommonCryptoand CC_SHA1,但我读过的内容没有使用CFData.

有没有从这一点到它的 SHA1 的好方法?

4

1 回答 1

2

您可以通过自己执行哈希来实现它。指纹不是证书本身的一部分。更多关于这里的信息。

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), &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), &digest)
        return Data(digest)
    }
}

我想提一下,自 2017 年以来,证书的 SHA-1 哈希值已被弃用,网站和科技巨头开始放弃对它们的支持。

游乐场示例

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) }

于 2021-01-18T17:44:06.397 回答