来自iOS中X.509 ASN.1 RSA公钥的SecKeyRef

时间:2013-07-21 09:28:24

标签: iphone objective-c encryption rsa commoncrypto

我意识到我在Stack Overflow上已经提出的问题有很多类似的问题,但是没有一个问题有明确的答案可以满足我的需求,所以我们走了:

我的程序通过网络接收ASN.1编码的RSA公钥。我将数据存储在一个简单的NSData实例中。我希望使用该公钥来编码16个字节的数据并通过网络返回这些数据。根据我的研究,最好的方法是使用SecKeyRef。根据Apple提供的荒谬模糊的文档,可以使用一些代码来完成。但是,他们的代码存在问题。每次我想使用公钥时,我都需要将其添加到钥匙串并为其提供唯一标识符。这个问题是这个密钥只用一次。我正在寻找一种方法来获取一个不在钥匙串中的密钥的SecKeyRef,并且是从ASN.1编码密钥创建的。

我还考虑过通过base64编码将它转换为普通PEM并将其包装在'----- BEGIN PUBLIC KEY -----'和'----- END PUBLIC KEY--的可能性---'然后将它加载到SecKeyRef中,但我还没有看到这样做的方法。

另外,我在键,键格式等方面没有太多选择。它来自第三方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很容易,但随后会出现各种出口法规和其他问题。

1 个答案:

答案 0 :(得分:0)

问题显然是“证书”的来源,实际上并不比the key wrapped in some DER tags多。

由于这篇http://blog.wingsofhermes.org/?p=75博客文章中的黑魔法,我已成功地实现了我的大部分目标。

成功:

  • 从数据加载的密钥,而不是文件
  • java服务器成功读取的密钥(AES)密钥加密。

成功率较低:

  • 必须使用唯一标识符,但我重复使用它,因此不需要疯狂的命名方案。
  • 密钥暂时添加到钥匙串中,但我在一次使用后将其删除,因此也可以解决。

我仍然不太清楚if语句的数组与循环和魔法数字的数量完全相同,但至少它是有效的,因为密钥总是来自同一个源,它不应该破坏除非他们改变了java安全提供程序......哦等等,这实际上有点可能......哦......至少它在Java 7标准中有点具体。

* p * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *