การถอดรหัสคีย์สาธารณะ RSA บน OS X โดยใช้ SecTransform API (หรือ API ระบบอื่น)

ฉันกำลังพยายามแทนที่การใช้ OpenSSL ซึ่งเลิกใช้มานานแล้วและถูกลบออกจาก 10.11 SDK ด้วย Security Transform API การใช้ OpenSSL ของฉันมีไว้เพื่อการตรวจสอบคีย์ใบอนุญาตเท่านั้น ปัญหาที่ฉันพบคือรหัสลิขสิทธิ์ถูกสร้างขึ้น (ฝั่งเซิร์ฟเวอร์) โดยใช้ฟังก์ชัน rsa_private_encrypt() ของ OpenSSL แทนที่จะเป็น (อาจเหมาะสมกว่า) 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() ของ OpenSSL ใน Security.framework อาจสามารถใช้ SecVerifyTransform ได้ (ฉันไม่สามารถใช้งานสิ่งนี้ได้ แต่ก็เป็นเช่นนั้นกับ RSA_sign() ของ OpenSSL เช่นกัน) ฉันยินดีอย่างยิ่งที่จะใช้ 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