使用 SecTransform API(或其他系统 API)在 OS X 上进行 RSA public 密钥解密
RSA public key decryption on OS X using SecTransform API (or other system API)
我正在尝试替换我对 OpenSSL 的使用,OpenSSL 早已被弃用,并且已使用安全转换从 10.11 SDK 中删除 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 APIs 复制它。我有以下内容:
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
错误。
我是不是遗漏了什么,或者 Security.framework 中没有与 OpenSSL 的 RSA_public_decrypt()
等效的东西?也许可以使用 SecVerifyTransform
(我也无法让它工作,但 OpenSSL 的 RSA_sign()
也是如此)。我当然愿意使用另一个系统 API(例如 CDSA/CSSM),如果它能让我做到这一点。
不幸的是,由于此代码需要验证现有的许可证代码,我不能简单地更改我的许可证生成代码以使用 RSA_sign()
或类似代码。
我想出了如何使用 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
请注意,here, while CDSA is deprecated, Apple recommends its use "if none of the other cryptographic service APIs support what you are trying to do". I have filed radar #23063471 要求将此功能添加到 Security.framework。
我正在尝试替换我对 OpenSSL 的使用,OpenSSL 早已被弃用,并且已使用安全转换从 10.11 SDK 中删除 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 APIs 复制它。我有以下内容:
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
错误。
我是不是遗漏了什么,或者 Security.framework 中没有与 OpenSSL 的 RSA_public_decrypt()
等效的东西?也许可以使用 SecVerifyTransform
(我也无法让它工作,但 OpenSSL 的 RSA_sign()
也是如此)。我当然愿意使用另一个系统 API(例如 CDSA/CSSM),如果它能让我做到这一点。
不幸的是,由于此代码需要验证现有的许可证代码,我不能简单地更改我的许可证生成代码以使用 RSA_sign()
或类似代码。
我想出了如何使用 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
请注意,here, while CDSA is deprecated, Apple recommends its use "if none of the other cryptographic service APIs support what you are trying to do". I have filed radar #23063471 要求将此功能添加到 Security.framework。