OSX Generated key can't encrypt (SecKeyCreateRandomKey & SecKeyCreateEncryptedData)

2.2k Views Asked by At

I am basically follow this guide to generated a private key, copy the public key, and then encrypt a message. However, it gives me the error (OSStatus error -67712 - CSSM Exception: -2147415791 CSSMERR_CSP_INVALID_KEY_REFERENCE).

Initially, I thought I set the attributes incorrectly. However, if I create the public key (with the same attributes) by the SecKeyGeneratePair() function, everything works perfectly. Is it weird?

void TestEncryptDecrpt() {
    OSStatus status;
    NSData* tag = [@"com.example.keys.mykey" dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary* attributes =
    @{ (id)kSecAttrKeyType:               (id)kSecAttrKeyTypeRSA,
       (id)kSecAttrKeySizeInBits:         @1024,
       (id)kSecPrivateKeyAttrs:
           @{ (id)kSecAttrIsPermanent:    @YES,
              (id)kSecAttrApplicationTag: tag,
              },
       };

    CFErrorRef error = NULL;
    SecKeyRef privateKey = SecKeyCreateRandomKey((__bridge CFDictionaryRef)attributes, &error);        
    SecKeyRef publicKey = SecKeyCopyPublicKey(privateKey);


    // *** it will work if I generate the key by SecKeyGeneratePair ***
    // status = SecKeyGeneratePair( (__bridge CFDictionaryRef)attributes, &publicKey, &privateKey );


    // start encrypt and decrypt a message
    static char const kMessage[] = "This is a secret!\n";        
    SecKeyAlgorithm algorithm = kSecKeyAlgorithmRSAEncryptionRaw;        
    BOOL canEncrypt = SecKeyIsAlgorithmSupported(publicKey, kSecKeyOperationTypeEncrypt, algorithm);
    NSData* plainData = [NSData dataWithBytes:kMessage length:sizeof(kMessage)];
    canEncrypt &= ([plainData length] < (SecKeyGetBlockSize(publicKey)-130));

    NSData* cipherText = nil;
    if (canEncrypt) {
        CFErrorRef error = NULL;
        cipherText = (NSData*)CFBridgingRelease( SecKeyCreateEncryptedData(publicKey, algorithm, (__bridge CFDataRef)plainData, &error));
        if (!cipherText) {
            NSError *err = CFBridgingRelease(error);  // ARC takes ownership
            // Handle the error. . .
            NSLog(@"error = %@, %@", [err userInfo], [err localizedDescription]);
        }
    }
}
1

There are 1 best solutions below

0
Yu-Chih Tung On

Problem solved. You need the "kSecAttrIsPermanent" property as well in the public key setting.

Not sure why this is not mentioned in the example.