Расшифровка открытого ключа RSA в OS X с использованием SecTransform API (или другого системного API)

Я пытаюсь заменить использование OpenSSL, который давно устарел и был удален из SDK 10.11, на API преобразования безопасности. Я использую OpenSSL просто для проверки лицензионного ключа. Проблема, с которой я столкнулся, заключается в том, что лицензионные ключи генерируются (на стороне сервера) с использованием функции OpenSSL rsa_private_encrypt(), а не (возможно, более подходящей) rsa_sign(). В текущем коде OpenSSL я проверяю их с помощью rsa_public_decrypt() следующим образом:

int decryptedSize = RSA_public_decrypt([signature length], [signature bytes], checkDigest, rsaKey, RSA_PKCS1_PADDING);
BOOL success = [[NSData dataWithBytes:checkDigest length:decryptedSize] isEqualToData:[digest sha1Hash]]) 

К сожалению, я не могу воспроизвести это с помощью SecTransform API. У меня есть следующее:

SecTransformRef decryptor = CFAutorelease(SecDecryptTransformCreate(pubKey, &error));
if (error) { showSecError(error); return NO; }
SecTransformSetAttribute(decryptor, kSecTransformInputAttributeName, (CFDataRef)signatureData, &error);
if (error) { showSecError(error); return NO; }

CFDataRef result = SecTransformExecute(decryptor, &error);
if (error) { showSecError(error); return NO; }
return CFEqual(result, (CFDataRef)[digest sha1Hash]);

Вызов SecTransformExecute() завершается ошибкой CSSMERR_CSP_INVALID_KEY_CLASS.

Я что-то упустил, или нет эквивалента OpenSSL RSA_public_decrypt() в Security.framework? Возможно, можно использовать SecVerifyTransform (мне тоже не удалось заставить это работать, но то же самое верно и для OpenSSL RSA_sign()). Я, безусловно, готов использовать другой системный API (например, CDSA/CSSM), если это позволит мне это сделать.

К сожалению, поскольку этот код должен проверять существующие коды лицензий, я не могу просто изменить свой код генерации лицензий, чтобы вместо этого использовать RSA_sign() или аналогичный.


person Andrew Madsen    schedule 11.10.2015    source источник


Ответы (1)


Я понял, как это сделать, используя CDSA/CSSM. . Код ниже:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"

NSData *ORSDecryptDataWithPublicKey(NSData *dataToDecrypt, SecKeyRef publicKey)
{
    const CSSM_KEY *cssmPubKey = NULL;
    SecKeyGetCSSMKey(publicKey, &cssmPubKey);
    CSSM_CSP_HANDLE handle;
    SecKeyGetCSPHandle(publicKey, &handle);

    CSSM_DATA inputData = {
        .Data = (uint8_t *)[dataToDecrypt bytes],
        .Length = [dataToDecrypt length],
    };

    CSSM_DATA outputData = {
        .Data = NULL,
        .Length = 0,
    };

    CSSM_ACCESS_CREDENTIALS credentials;
    memset(&credentials, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
    CSSM_CC_HANDLE contextHandle;
    CSSM_RETURN result = CSSM_CSP_CreateAsymmetricContext(handle, cssmPubKey->KeyHeader.AlgorithmId, &credentials, cssmPubKey, CSSM_PADDING_PKCS1, &contextHandle);
    if (result) { NSLog(@"Error creating CSSM context: %i", result); return nil; }

    CSSM_CONTEXT_ATTRIBUTE modeAttribute = {
        .AttributeType = CSSM_ATTRIBUTE_MODE,
        .AttributeLength = sizeof(UInt32),
        .Attribute.Uint32 = CSSM_ALGMODE_PUBLIC_KEY,
    };
    result = CSSM_UpdateContextAttributes(contextHandle, 1, &modeAttribute);
    if (result) { NSLog(@"Error setting CSSM context mode: %i", result); return nil; }

    CSSM_SIZE numBytesDecrypted = 0;
    CSSM_DATA remData = {
        .Data = NULL,
        .Length = 0,
    };
    result = CSSM_DecryptData(contextHandle, &inputData, 1, &outputData, 1, &numBytesDecrypted, &remData);
    if (result) { NSLog(@"Error decrypting data using CSSM: %i", result); return nil; }
    CSSM_DeleteContext(contextHandle);

    outputData.Length = numBytesDecrypted;

    return [NSData dataWithBytesNoCopy:outputData.Data length:outputData.Length freeWhenDone:YES];
}

#pragma clang diagnostic pop

Обратите внимание, что, как описано здесь, CDSA устарел, Apple рекомендует использовать его, «если ни один из других API-интерфейсов криптографических служб не поддерживает то, что вы пытаетесь сделать». Я подал radar #23063471 запрос на добавление этой функции в Security.framework.

person Andrew Madsen    schedule 12.10.2015