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

arj*_*nyg 6 iphone encryption rsa objective-c 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);
Run Code Online (Sandbox Code Playgroud)

PS:为什么苹果这么难?静态链接OpenSSL很容易,但随后出现各种出口法规和其他问题.

arj*_*nyg 0

问题显然出在“证书”的来源上,它实际上只不过是包裹在一些 DER 标签中的密钥

从好的方面来说,感谢这篇http://blog.wingsofhermes.org/?p=75博客文章中的黑魔法,我成功地实现了我的大部分目标。

成功:

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

成功率较低:

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

我仍然不太清楚与循环和大量幻数混合的 if 语句数组到底做了什么,但至少它有效,并且由于密钥始终来自同一源,因此它不应该中断,除非它们更改了java 安全提供程序...哦等等,这实际上有点可能...哦好吧...至少它在 Java 7 标准中有点具体。

*交叉手指* *希望没有破损*