Как сделать асимметричное шифрование/дешифрование с OSX 10.7+ без openssl?

Поскольку openssl устарел в OSX 10.7+, я хотел бы переключиться с openssl на внутреннюю цепочку ключей OSX и функцию шифрования.

Но теперь я застрял на асимметричном шифровании/дешифровании.

Как я могу выполнить шифрование/дешифрование случайно сгенерированного симметричного ключа с помощью асимметричного (RSA) ключа. С openssl это довольно просто.

В документах разработчиков Apple они говорят, что CommonCrypto поддерживает асимметричное шифрование, но при проверке заголовков я вижу только поддержку симметричного материала.

Любые подсказки?


person Jonas Schnelli    schedule 29.07.2012    source источник
comment
Связанный вопрос: stackoverflow.com/questions/4140664/   -  person JWWalker    schedule 18.08.2012
comment
SecEncryptTransform будет выполнять как асинхронное, так и синхронное шифрование.   -  person l --marc l    schedule 17.08.2015


Ответы (1)


Взгляните на службы синтаксиса криптографических сообщений и посмотрите, может ли это сделать то, что вам нужно.

Кроме того, вы немного неправильно понимаете OpenSSL. Библиотеки OpenSSL, поставляемые с ОС, устарели. Это не означает, что вы не можете продолжать использовать OpenSSL. OpenSSL — это Open Source, и ничто не мешает вам загрузить его и свободно использовать в своем приложении.

Прекращение поддержки Apple просто означает, что если вы используете OpenSSL, вам необходимо включить свою собственную копию библиотек OpenSSL, чтобы вы отвечали за поддержание вашей библиотеки OpenSSL в актуальном состоянии. и для исправления любой поломки, которая возникает всякий раз, когда вы это делаете. :-)

А если нет, то функции асимметричного шифрования и дешифрования iOS (SecKeyEncrypt и SecKeyDecrypt) существуют в OS X, и заголовок iOS даже показывает, что они доступны в OS X. Я не уверен, почему их нет в OS X. SDK. Я зарегистрировал ошибку, и она была отмечена как дубликат.

Apple, вероятно, не сможет удалить эти функции в будущем, не нарушая Симулятор, но если вы отправляете заявку в магазин приложений, и они вас огорчают из-за их использования, вот примерно совместимая замена для SecKeyEncrypt, созданная с использованием Security Преобразования API:

// Workaround for SecKeyEncrypt not really being public API in OS X
OSStatus OSXSecKeyEncrypt ( SecKeyRef key, SecPadding padding, const uint8_t *plainText, size_t plainTextLen, uint8_t *cipherText, size_t *cipherTextLen )
{
    CFMutableDictionaryRef parameters = CFDictionaryCreateMutable(
                                                                  kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks,
                                                                  &kCFTypeDictionaryValueCallBacks);
    CFDictionarySetValue(parameters, kSecAttrKeyType, kSecAttrKeyTypeAES);
    CFErrorRef error = NULL;
    SecTransformRef encrypt = SecEncryptTransformCreate(key, &error);

    if (error) {
        AFNSLog(@"Encryption failed: %@\n", (__bridge NSError *)error);
        return (OSStatus)[(__bridge NSError *)error code];
    }

    SecTransformSetAttribute(
                             encrypt,
                             kSecPaddingKey,
                             NULL, // kSecPaddingPKCS1Key (rdar://13661366 : NULL means kSecPaddingPKCS1Key and
                                                                          // kSecPaddingPKCS1Key fails horribly)
                             &error);

    CFDataRef sourceData = CFDataCreate(kCFAllocatorDefault, plainText, plainTextLen);
    SecTransformSetAttribute(encrypt, kSecTransformInputAttributeName,
                             sourceData, &error);

    CFDataRef encryptedData = SecTransformExecute(encrypt, &error);
    if (error) {
        AFNSLog(@"Encryption failed: %@\n", (__bridge NSError *)error);
        return (OSStatus)[(__bridge NSError *)error code];
    }

    if ((unsigned long)CFDataGetLength(encryptedData) > *cipherTextLen) {
        return errSecBufferTooSmall;
    }
    *cipherTextLen = CFDataGetLength(encryptedData);
    CFDataGetBytes(encryptedData, CFRangeMake(0, *cipherTextLen), cipherText);

    return noErr;
}

Вы должны быть в состоянии довольно легко адаптировать код для расшифровки; Мне это было не нужно для моих целей, поэтому я не писал эту функцию.

person dgatwood    schedule 17.08.2012
comment
Увы, этот пример показывает только крайний случай — случай, когда весь открытый текст доступен за один раз. Все методы OpenSSL EVP_*Update работают с неограниченными/потоковыми данными, в то время как ваш пример этого не делает и, следовательно, не полностью отвечает на вопрос. - person Graham Leggett; 30.06.2018
comment
Мой ответ должен был быть простым ответом для наиболее распространенного случая. Для потоковой передачи используйте SecTransformCreateReadTransformWithReadStream, чтобы создать преобразование чтения, а затем используйте secTransformCreateGroupTransform и secTransformConnectTransforms, чтобы связать их. Дополнительную информацию см. в Руководстве по программированию Apple Security Transforms, в частности, Security Transforms Basics › Выполнение цепочек преобразований. - person dgatwood; 02.07.2018