Подтвердить что ты не робот

Чтение открытого ключа PEM в 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);

В результате получается строка 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.

Я могу использовать строку Base64 в iOS, используя этот код, который добавляет его в цепочку ключей, а затем возвращает его снова как SecKeyRef, но я бы предпочел не нужно добавлять сертификат в цепочку ключей, чтобы иметь возможность получить его для его использования один раз.

Проведя некоторые исследования, кажется, я должен использовать SecCertificateCreateWithData для создания сертификата для использования в iOS из строки Base64, но я всегда возвращаю 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);
    }
}
4b9b3361

Ответ 1

Вначале вы не используете base64-декодирование ваших ключевых данных. Вы передаете данные с кодировкой base64 в SecCertificateCreateWithData(), и эта функция ожидает необработанные, декодированные данные. Попробуйте что-то вроде этого:

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

Update:

То, что вы отправляете на свой iOS-код, является ключом base64 DER, а не сертификатом DER или PEM. Таким образом, ожидается, что результат, который вы видите, вы дадите ему BLOB с кодировкой DER, который не содержит сертификат, и он возвращает вам нулевую ссылку на сертификат, представляющую несуществующие данные сертификата.

У вас есть два варианта:

  • Используйте код, который вы уже нашли, чтобы добавить ключ в цепочку ключей, а затем извлеките его. Кажется, это "способ iOS" для импорта ключей для использования в iOS.

  • Используйте открытый ключ и связанный с ним закрытый ключ, чтобы подписать сертификат и импортировать его в ваше приложение, создать временные отношения доверия с этим сертификатом, а затем вытащить открытый ключ из информации сертификата (пример: iOS SecKeyRef из NSString)

Для второго варианта работы ваш Java-код не только должен иметь открытый ключ, ему также потребуется связанный закрытый ключ для создания подписанного сертификата.

В зависимости от того, что вы планируете делать с SecKeyRef, вы можете столкнуться с проблемами. Значения SecKeyRef могут быть приведены прямо к значениям SecKeychainItemRef для использования в функциях функций Keychain Services. Если значение SecKeyRef не приходит из цепочки ключей, ваш код будет получать ошибки. Подробнее читайте в документах