将PEM公钥读入iOS

Dar*_*ren 17 java ssl rsa objective-c ios

我有一个base64公钥,由java使用此代码生成:

RSAPublicKeySpec rsaKS = new RSAPublicKeySpec(modulus, pubExponent);
RSAPublicKey rsaPubKey = (RSAPublicKey) kf.generatePublic(rsaKS);
byte[] encoded = rsaPubKey.getEncoded();
String base64 = Base64.encodeToString(encoded, Base64.DEFAULT);
Log.e(null, "base64: " + base64);
Run Code Online (Sandbox Code Playgroud)

这会产生Base64字符串.

在OSX中,我可以使用以下代码获取SecKeyRef:

// Create the SecKeyRef using the key data
CFErrorRef error = NULL;
CFMutableDictionaryRef parameters = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL);
CFDictionarySetValue(parameters, kSecAttrKeyType, kSecAttrKeyTypeRSA);
CFDictionarySetValue(parameters, kSecAttrKeyClass, kSecAttrKeyClassPublic);
SecKeyRef keyRef = SecKeyCreateFromData(parameters, (__bridge CFDataRef)[pubKey base64DecodedData], &error);
Run Code Online (Sandbox Code Playgroud)

但是在iOS中没有SecKeyCreateFromData方法.

我可以在iOS中使用Base64字符串,使用此代码将其添加到钥匙串,然后再次检索它,SecKeyRef但是我不必将证书添加到钥匙串,只是为了能够检索它以使用它一次.

做一些研究,似乎我应该能够使用SecCertificateCreateWithData从我的Base64字符串创建在iOS中使用的证书,但是在使用此代码时我总是得到一个NULL证书:

NSString* pespublicKey = @"MIGfMA0GCSqGSIb3....DCUdz/y4B2sf+q5n+QIDAQAB";
NSData* certData = [pespublicKey dataUsingEncoding:NSUTF8StringEncoding];
SecCertificateRef cert;
if ([certData length]) {
    cert = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certData);
    if (cert != NULL) {
        CFStringRef certSummary = SecCertificateCopySubjectSummary(cert);
        NSString* summaryString = [[NSString alloc] initWithString:(__bridge NSString*)certSummary];
        NSLog(@"CERT SUMMARY: %@", summaryString);
        CFRelease(certSummary);
    } else {
        NSLog(@" *** ERROR *** trying to create the SSL certificate from data located at %@, but failed", pespublicKey);
    }
}
Run Code Online (Sandbox Code Playgroud)

hru*_*ing 2

您不会首先对关键数据进行 Base64 解码。您将 Base64 编码的数据传递给SecCertificateCreateWithData(),并且该函数需要原始的解码数据。尝试这样的事情:

NSData *certData = [[NSData alloc] initWithBase64EncodedString:pespublicKey options:0];
cert = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certData);
Run Code Online (Sandbox Code Playgroud)

更新:

您发送到 iOS 代码的是 base64 DER 编码的密钥,而不是 DER 或 PEM 编码的证书。因此,您看到的结果是预期的——您给它一个不包含证书的 DER 编码数据 blob,它会返回一个表示不存在的证书数据的空证书引用。

您有两个选择:

  1. 使用您已经找到的代码将密钥添加到钥匙串中,然后将其取出。这似乎是导入 iOS 上使用的密钥的“iOS 方式”。

  2. 使用公钥及其关联的私钥对证书进行签名并将其导入到您的应用程序中,与该证书创建临时信任关系,然后从证书信息中提取公钥(例如:来自 NSString 的 iOS SecKeyRef

要使第二个选项起作用,您的 Java 代码不仅必须拥有公钥,还需要关联的私钥来生成签名证书。

根据您计划使用 执行的操作SecKeyRef,您可能会遇到问题。SecKeyRef值可以直接转换为SecKeychainItemRef用于钥匙串服务功能的值。如果该SecKeyRef值不是来自钥匙串,您的代码将会出错。阅读文档以获取更多信息