将PEM公钥读入iOS

时间:2015-04-09 15:38:16

标签: java ios objective-c ssl rsa

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

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);

这会产生一个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);

但是在iOS中没有SecKeyCreateFromData方法。

我可以使用this code在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);
    }
}

1 个答案:

答案 0 :(得分:1)

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

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

<强>更新

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

您有两种选择:

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

  2. 使用公钥及其关联的私钥对证书进行签名并将其导入您的应用程序,与该证书建立临时信任关系,然后从证书的信息中提取公钥(例如:{{ 3}})

  3. 对于第二个工作选项,您的Java代码不仅需要拥有公钥,还需要相关的私钥来生成签名证书。

    根据您计划对SecKeyRef执行的操作,您可能会遇到问题。 SecKeyRef值可以直接转换为SecKeychainItemRef值,以便在Keychain Services函数中使用。如果SecKeyRef值不是来自钥匙串,则代码会出错。 iOS SecKeyRef from NSString