Search code examples
iosobjective-ccommoncrypto

SecKeyEncrypt returns errSecParam


I am trying to encrypt some NSData using SecKeyEncrypt function. The problem is, it returns an error -50, which according to documentation is

errSecParam
One or more parameters passed to the function are not valid.

The problem is, I can't find anything wrong with my function. Code is as follows

- (NSData *)encryptWithPrivateKey:(NSData *)plainData
{
    if (!privateKeyRef) {
        RBLog(@"No private key");
        return nil;
    }
    if (!plainData.length) {
        RBLog(@"Plain data empty");
        return nil;
    }

    size_t blockSize = SecKeyGetBlockSize(privateKeyRef); // 128
    NSMutableData *encryptedData = [[NSMutableData alloc] initWithCapacity:blockSize]; // using capacity of 1024 changes nothing
    size_t encryptedDataLen = blockSize;

    OSStatus status = SecKeyEncrypt(privateKeyRef,
                                    kSecPaddingPKCS1,
                                    (const uint8_t *)plainData.bytes,
                                    plainData.length,
                                    (uint8_t *)encryptedData.bytes,
                                    &encryptedDataLen);

    if (status != errSecSuccess) {
        RBLog(@"Could not encrypt, OS status %@", @(status));
    }
    return [NSData dataWithData:encryptedData];
}

The key is created using SecKeyGeneratePair which returns errSecSuccess. As you can see, I'm trying to encrypt the data with private key, not public one, so I have added

[privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrCanEncrypt];

to private key parameters upon generation, but that unfortunatelly didn't help.

What is the issue here?


Solution

  • I managed to find the solution.

    What I actually wanted to do was to have the data signed (that's why I was using private key to encrypt instead of public one), but it turns out CommonCrypto has a specific function just for that, so using

    OSStatus status = SecKeyRawSign(privateKeyRef,
                                    kPadding,
                                    (const uint8_t *)plainText.bytes,
                                    plainText.length,
                                    (uint8_t *)encryptedData.bytes,
                                    &encryptedDataLen);
    

    solved the issue.