3

我正在尝试使用安全转换 API 替换我对 OpenSSL 的使用,它很久以前就被弃用并已从 10.11 SDK 中删除。我使用 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错误。

我是否遗漏了什么,或者RSA_public_decrypt()Security.framework 中没有与 OpenSSL 等效的东西?也许SecVerifyTransform可以使用 a (我也无法让它工作,但 OpenSSL 也是如此RSA_sign())。如果它能让我做到这一点,我当然愿意使用另一个系统 API(例如 CDSA/CSSM)。

不幸的是,由于此代码需要验证现有的许可证代码,我不能简单地将我的许可证生成代码更改为使用RSA_sign()或类似代码。

4

1 回答 1

4

我想出了如何使用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 支持您尝试执行的操作”时使用它。我已经提交了雷达#23063471,要求将此功能添加到 Security.framework 中。

于 2015-10-12T01:00:38.160 回答