如何序列化 SecTrustRef 对象?
How to serialize a SecTrustRef object?
我有一个来自系统的 SecTrustRef
对象,我想对自己进行评估。只需调用 SecTrustEvaluateAsync
就足以完成这项工作。问题是,我必须在不同的进程中对其进行评估,因为只有这个其他进程才能访问存储 CA 证书的钥匙串,这可能会导致评估成功。
这两个进程有一个 IPC link,允许我在它们之间交换任意字节数据,但我没有看到任何方法可以轻松地将 SecTrustRef
序列化为字节数据并反序列化该数据回到另一个进程的对象。 SecTrustRef
.
似乎没有持久存储机制
所以我是不是忽略了一些重要的东西,还是我真的必须获得所有证书 (SecTrustGetCertificateAtIndex
) 和所有政策 (SecTrustCopyPolicies
) 并自己序列化这些?
如果是这样,我将如何序列化政策?
对于证书(SecCertificateRef
),这很容易,我只是调用SecCertificateCopyData
,然后调用SecCertificateCreateWithData
。
但是对于策略我只能在一侧调用 SecPolicyCopyProperties
然后在 SecPolicyCreateWithProperties
上调用,但是后者需要第二个参数,一个 policyIdentifier
我看不出有什么办法从现有策略中获取该值。我错过了什么?
通读 source of the Security framework,我终于弄明白了如何复制 SecPolicyRef
:
SecPolicyCreateWithProperties
想要一个 "policyIdentifier"。它是一个常量,如 kSecPolicyAppleIPsec
.
- 这不会直接由函数存储,它比较值并调用专用内部 "initializers"(如
SecPolicyCreateIPsec
)。
- 这些依次调用
SecPolicyCreate
(这是私有的)。他们最终传递的标识符值与您传递给 SecPolicyCreateWithProperties
. 的标识符值相同
- 然后这个值按原样存储在
_oid
字段中!
标识符实际上是OID。您可以通过 SecPolicyCopyProperties(policy)
(使用键 kSecPolicyOid
存储在字典中)或通过 SecPolicyGetOID
(但 returns 不方便 CSSM_OID
)来获取它。其中一些专门的初始化程序还使用传递给 SecPolicyCreateWithProperties
的属性字典中的值,这些值应该已经存在于复制的属性字典中。
所以这给了我们:
序列化:
CFDictionaryRef createSerializedPolicy(SecPolicyRef policy) {
// Already contains all the information needed.
return SecPolicyCopyProperties(policy);
}
反序列化:
SecPolicyRef createDeserializedPolicy (CFDictionaryRef serialized) {
CFStringRef oid = CFDictionaryGetValue(serialized, kSecPolicyOid);
if (oid == NULL || CFGetTypeID(oid) != CFStringGetTypeID()) {
return NULL;
}
return SecPolicyCreateWithProperties(oid, serialized);
}
为了尽可能接近地复制原始的 SecTrustRef,锚点也需要被复制。设置锚点后,内部变量 _anchorsOnly
会设置为 true
。不幸的是,没有办法查询这个值,例如,我看到它在 NSURLSession
传递的信任中是 false
。还不知道如何以 public 的方式获得这个值。
另一个有问题的位是异常:如果 _exceptions
为 NULL 但您通过 SecTrustCopyExceptions(trust)
查询它们,您确实获得了数据!如果您通过 SecTrustSetExceptions(trust, exceptions)
将其分配给反序列化的信任,您突然会遇到以前不存在的异常,并且可以更改评估结果! (我已经看到那些突然出现的异常导致 "proceed" 而不是 "recoverable trust failure" 的评估结果)。
我有一个来自系统的 SecTrustRef
对象,我想对自己进行评估。只需调用 SecTrustEvaluateAsync
就足以完成这项工作。问题是,我必须在不同的进程中对其进行评估,因为只有这个其他进程才能访问存储 CA 证书的钥匙串,这可能会导致评估成功。
这两个进程有一个 IPC link,允许我在它们之间交换任意字节数据,但我没有看到任何方法可以轻松地将 SecTrustRef
序列化为字节数据并反序列化该数据回到另一个进程的对象。 SecTrustRef
.
所以我是不是忽略了一些重要的东西,还是我真的必须获得所有证书 (SecTrustGetCertificateAtIndex
) 和所有政策 (SecTrustCopyPolicies
) 并自己序列化这些?
如果是这样,我将如何序列化政策?
对于证书(SecCertificateRef
),这很容易,我只是调用SecCertificateCopyData
,然后调用SecCertificateCreateWithData
。
但是对于策略我只能在一侧调用 SecPolicyCopyProperties
然后在 SecPolicyCreateWithProperties
上调用,但是后者需要第二个参数,一个 policyIdentifier
我看不出有什么办法从现有策略中获取该值。我错过了什么?
通读 source of the Security framework,我终于弄明白了如何复制 SecPolicyRef
:
SecPolicyCreateWithProperties
想要一个 "policyIdentifier"。它是一个常量,如kSecPolicyAppleIPsec
.- 这不会直接由函数存储,它比较值并调用专用内部 "initializers"(如
SecPolicyCreateIPsec
)。 - 这些依次调用
SecPolicyCreate
(这是私有的)。他们最终传递的标识符值与您传递给SecPolicyCreateWithProperties
. 的标识符值相同
- 然后这个值按原样存储在
_oid
字段中!
标识符实际上是OID。您可以通过 SecPolicyCopyProperties(policy)
(使用键 kSecPolicyOid
存储在字典中)或通过 SecPolicyGetOID
(但 returns 不方便 CSSM_OID
)来获取它。其中一些专门的初始化程序还使用传递给 SecPolicyCreateWithProperties
的属性字典中的值,这些值应该已经存在于复制的属性字典中。
所以这给了我们:
序列化:
CFDictionaryRef createSerializedPolicy(SecPolicyRef policy) {
// Already contains all the information needed.
return SecPolicyCopyProperties(policy);
}
反序列化:
SecPolicyRef createDeserializedPolicy (CFDictionaryRef serialized) {
CFStringRef oid = CFDictionaryGetValue(serialized, kSecPolicyOid);
if (oid == NULL || CFGetTypeID(oid) != CFStringGetTypeID()) {
return NULL;
}
return SecPolicyCreateWithProperties(oid, serialized);
}
为了尽可能接近地复制原始的 SecTrustRef,锚点也需要被复制。设置锚点后,内部变量 _anchorsOnly
会设置为 true
。不幸的是,没有办法查询这个值,例如,我看到它在 NSURLSession
传递的信任中是 false
。还不知道如何以 public 的方式获得这个值。
另一个有问题的位是异常:如果 _exceptions
为 NULL 但您通过 SecTrustCopyExceptions(trust)
查询它们,您确实获得了数据!如果您通过 SecTrustSetExceptions(trust, exceptions)
将其分配给反序列化的信任,您突然会遇到以前不存在的异常,并且可以更改评估结果! (我已经看到那些突然出现的异常导致 "proceed" 而不是 "recoverable trust failure" 的评估结果)。