我意识到有很多与我即将在 Stack Overflow 上提出的问题类似的问题,但没有一个有明确的答案可以真正满足我的需求,所以我们开始吧:
我的程序通过网络接收 ASN.1 编码的 RSA 公钥。我将数据存储在一个简单的 NSData 实例中。我希望使用该公钥对 16 个字节的数据进行编码并通过网络返回这些数据。根据我的研究,最好的方法似乎是使用 SecKeyRef。根据 Apple 提供的含糊不清的文档,这可以使用一些代码来完成。但是,他们的代码存在问题。每次我想使用公钥时,我都需要将它添加到钥匙串中并给它一个唯一标识符。问题是这个密钥只能使用一次。我正在寻找一种方法来获取不在钥匙串中并且由 ASN.1 编码的密钥创建的密钥的 SecKeyRef。
我还考虑了通过 base64 编码将其转换为通用 PEM 并将其包装在 '-----BEGIN PUBLIC KEY-----' 和 '-----END PUBLIC KEY----- 中的可能性' 然后将其加载到 SecKeyRef 中,但我也没有看到这样做的方法。
此外,我在密钥类型、密钥格式等方面没有太多选择。它来自第 3 方 java 服务器。耶。
我目前有这种加载密钥的替代方法(可能)不会将它们添加到密钥链中,但显然密钥(通过反复试验:D)不是 DER 格式,因此我不能像这样加载它。
SecCertificateRef certificateRef = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)data); //data contains the public key - received over the network
SecPolicyRef policyRef = SecPolicyCreateBasicX509();
SecTrustRef trustRef;
OSStatus status = SecTrustCreateWithCertificates(certificateRef, policyRef, &trustRef);
NSAssert(status == errSecSuccess, @"SecTrustCreateWithCertificates failed.");
SecTrustResultType trustResult;
status = SecTrustEvaluate(trustRef, &trustResult);
NSAssert(status == errSecSuccess, @"SecTrustEvaluate failed.");
SecKeyRef publicKey = SecTrustCopyPublicKey(trustRef); //The Result :)
NSAssert(publicKey != NULL, @"SecTrustCopyPublicKey failed.");
if (certificateRef) CFRelease(certificateRef);
if (policyRef) CFRelease(policyRef);
if (trustRef) CFRelease(trustRef);
PS:为什么苹果这么难?静态链接 OpenSSL 很容易,但随之而来的是各种出口法规和其他问题。