ideawu / Objective-C-RSA

Doing RSA encryption and decryption with Objective-C on iOS
http://www.ideawu.com/blog/post/132.html
Other
1.15k stars 280 forks source link

Mac OSX Support #20

Open dtokos opened 8 years ago

dtokos commented 8 years ago

Hello,

i found this useful obc-c class and tested it. It works on iOS but not on OSX. I was searching all over the internet an i didn't find any class for OSX. Can be this somehow modified or are u planning OSX support?

Thanks for info, have a nice day

ideawu commented 8 years ago

I have no plan for Mac OS X, but I suggest you using openssl library for OS X.

dreampiggy commented 3 years ago

Can been supported by using this code below to create SecKeyRef and some compatible implementations using old APIs.

For SecKeyRawSign/SecKeyEncrypt/SecKeyDecrypt:

#if TARGET_OS_OSX
#pragma clang diagnostic push
#pragma clang diagnostic ignored"-Wnonnull"
static OSStatus OSXSecKeyRawSign(SecKeyRef key, SecPadding padding, const uint8_t *plainText, size_t plainTextLen, uint8_t *cipherText, size_t *cipherTextLen)
{
    CFErrorRef error = NULL;
    SecTransformRef encrypt = SecEncryptTransformCreate(key, &error);

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

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

    CFDataRef encryptedData = SecTransformExecute(encrypt, &error);
    if (error) {
        NSLog(@"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;
}

static OSStatus OSXSecKeyEncrypt(SecKeyRef key, SecPadding padding, const uint8_t *plainText, size_t plainTextLen, uint8_t *cipherText, size_t *cipherTextLen)
{
    CFErrorRef error = NULL;
    SecTransformRef encrypt = SecEncryptTransformCreate(key, &error);

    if (error) {
        NSLog(@"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) {
        NSLog(@"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;
}

static OSStatus OSXSecKeyDecrypt(SecKeyRef key, SecPadding padding, const uint8_t *cipherText, size_t cipherTextLen, uint8_t *plainText, size_t *plainTextLen)
{
    CFErrorRef error = NULL;
    SecTransformRef decrypt = SecDecryptTransformCreate(key, &error);

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

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

    CFDataRef sourceData = CFDataCreate(kCFAllocatorDefault, cipherText, cipherTextLen);
    SecTransformSetAttribute(decrypt, kSecTransformInputAttributeName,
                             sourceData, &error);

    CFDataRef decryptedData = SecTransformExecute(decrypt, &error);
    if (error) {
        NSLog(@"Decryption failed: %@\n", (__bridge NSError *)error);
        return (OSStatus)[(__bridge NSError *)error code];
    }

    if ((unsigned long)CFDataGetLength(decryptedData) > *plainTextLen) {
        return errSecBufferTooSmall;
    }
    *plainTextLen = CFDataGetLength(decryptedData);
    CFDataGetBytes(decryptedData, CFRangeMake(0, *plainTextLen), plainText);

    return noErr;
}
#pragma clang diagnostic pop

For SecKeyRef generation (don't use Keychain):

#if TARGET_OS_OSX
    NSDictionary *publicKey = @{(__bridge NSString *)kSecAttrKeyType : (__bridge NSString *)kSecAttrKeyTypeRSA, (__bridge NSString *)kSecAttrKeyClass : (__bridge NSString *)kSecAttrKeyClassPublic};
    SecKeyRef keyRef = SecKeyCreateFromData((__bridge CFDictionaryRef)publicKey, (__bridge CFDataRef)data, nil);
//    SecKeyRef keyRef = SecKeyCreateWithData((__bridge CFDataRef)data, (__bridge CFDictionaryRef)publicKey, nil);
    return keyRef;
#endif