如何从 SecCertificate 中提取或比较 kSecPropertyKeyValue
How to extract or compare kSecPropertyKeyValue from SecCertificate
需要解析和比较证书值,但其中一些返回为 Data
,不解析为字符串。大多数属性以数字或字符串形式返回,但 kSecPropertyKeyValue
是 CFData
的数组。需要这个来显示与 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({ [=10=][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([=10=])) }),
"||| string:", (values[kSecPropertyKeyValue] as! [Data]).map({ String(data: [=10=], 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 转义,有些看起来像无效字符串。任何帮助表示赞赏。
显然 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
字节)。
需要解析和比较证书值,但其中一些返回为 Data
,不解析为字符串。大多数属性以数字或字符串形式返回,但 kSecPropertyKeyValue
是 CFData
的数组。需要这个来显示与 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({ [=10=][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([=10=])) }),
"||| string:", (values[kSecPropertyKeyValue] as! [Data]).map({ String(data: [=10=], 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 转义,有些看起来像无效字符串。任何帮助表示赞赏。
显然 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
字节)。