如何从SecCertificate中提取或比较kSecPropertyKeyValue

时间:2018-03-26 10:45:40

标签: swift security certificate keychain

需要解析和比较证书值,但其中一些值将作为Data返回,并且不会作为字符串进行解析。大多数属性都以数字或字符串形式返回,但kSecPropertyKeyValueCFData的数组。需要将此类证书信息显示为Keychain Access。

import Foundation
import Security

let query: [CFString: Any] = [
    kSecClass: kSecClassCertificate,
    kSecReturnAttributes: kCFBooleanTrue,
    kSecReturnRef: kCFBooleanTrue,
    kSecReturnData: kCFBooleanTrue,
    kSecMatchLimit: kSecMatchLimitAll
]

var result: AnyObject?
SecItemCopyMatching(query as CFDictionary, &result)
let certs: [SecCertificate] = (result as? [[CFString: Any]])?.map({ $0[kSecValueRef] as! SecCertificate }) ?? []

for cert in certs {
    if let values: [CFString:Any] = (SecCertificateCopyValues(cert, [kSecOIDExtendedKeyUsage] as CFArray, nil) as? [CFString:Any])?[kSecOIDExtendedKeyUsage] as? [CFString:Any] {

        // Expect to find `kSecOIDExtendedUseCodeSigning` value or something else
        // meaningful. How do I do that?

        print(
            "type:", values[kSecPropertyKeyType]!,
            "||| data values:", values[kSecPropertyKeyValue] as! [Data],
            "||| cString:", (values[kSecPropertyKeyValue] as! [CFData]).map({ String(cString: CFDataGetBytePtr($0)) }),
            "||| string:", (values[kSecPropertyKeyValue] as! [Data]).map({ String(data: $0, encoding: .utf8) })
        )
    }
}

粘贴在游乐场,打印:

type: array ||| data values: [8 bytes] ||| cString: ["+\u{06}\u{01}\u{05}\u{05}\u{07}\u{03}\u{04}"] ||| string: [Optional("+\u{06}\u{01}\u{05}\u{05}\u{07}\u{03}\u{04}")]
type: array ||| data values: [9 bytes] ||| cString: ["*�H��cd\u{04}\t"] ||| string: [nil]

有些看起来像unicode转义,有些看起来像无效字符串。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:0)

显然,OID值没有可读的字符串表示形式,但它们是常量,可以在google/der-ascii中找到。

例如,+\u{06}\u{01}\u{05}\u{05}\u{07}\u{03}\u{04}的上述输出与0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x04匹配,email protection+0x2b,以字节为单位)。