SecKeyCopyExternalRepresentation Fails for Symmetric Key

My little Swift program on macOS 12.3.1 creates a cryptographic key for a symmetric cipher as follows:

	let parameters = NSMutableDictionary()
	var raw = 256
	let num = CFNumberCreate(kCFAllocatorDefault, .sInt32Type, &raw)!
	var optError: Unmanaged<CFError>?

	parameters.setValue("Pix Cipher", forKey: kSecAttrLabel as String)
	parameters.setValue(kSecAttrKeyTypeAES, forKey: kSecAttrKeyType as String)
	parameters.setValue(num, forKey: kSecAttrKeySizeInBits as String)
	parameters.setValue(kCFBooleanTrue, forKey: kSecAttrIsPermanent as String)
	parameters.setValue(kCFBooleanTrue, forKey: kSecAttrCanEncrypt as String)
	parameters.setValue(kCFBooleanTrue, forKey: kSecAttrCanDecrypt as String)

	key = SecKeyGenerateSymmetric(parameters, &optError)

This key can be stored in the Key Chain and works fine for encryption and decryption. But when I want to export it using

	var error: Unmanaged<CFError>?
	
	let cfData = SecKeyCopyExternalRepresentation(key!, &error)

, this fails, with error set to something like Error Domain=NSOSStatusErrorDomain Code=-4 "MacOS error: -4"

What does "MacOS error: -4" mean? (kCFMessagePortTransportError/kCSIdentityDeletedErr /unimpErr?) Why does SecKeyCopyExternalRepresentation not work? What is wrong with the key?

Kind regards, Jakob

Replies

What does "MacOS error: -4" mean?

Pro tip!

% security error -4
Error: 0xFFFFFFFC -4 Function or operation not implemented.

In this case it’s errSecUnimplemented, grandfathered in from the traditional Mac OS unimpErr error.

To start, please read On Mac Keychains because I’m going to assume terms from there.

With regards your main issue, this is not going to work. The primary focus of SecKeyCopyExternalRepresentation is the data protection keychain and that keychain doesn’t support symmetric keys in this way. Rather, in the data protection keychain you store keys using kSecClassGenericPassword.

You might be able to export your key using SecItemExport but, honestly, you’re heading down the wrong path here. As I explain in On Mac Keychains, the data protection keychain is The Future™. Unless there’s some overriding reason you need to use the file-based keychain, you’d be better off:

  • Generating a random key by calling SecRandomCopyBytes.

  • Saving that as a generic password.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

  • Thanks, Quinn, for the enlightenment! Creating these random bytes and storing them as a password in the keychain works fine. But for encryption/decryption I need a SecKey. Now when I try to create a SecKey from my byte array (rawKey of type CFData in the following code snippet, size 256 bits):

    let parameters = NSMutableDictionary() var error: Unmanaged<CFError>? parameters.setValue(kSecAttrKeyClassSymmetric, forKey: kSecAttrKeyClass as String) parameters.setValue(kSecAttrKeyTypeAES, forKey: kSecAttrKeyType as String) key = SecKeyCreateWithData(rawKey, parameters, &error)

    , I get the error "Unsupported symmetric key type: 2147483649". And with 192 bits and kSecAttrKeyType3DES in place of kSecAttrKeyTypeAES I get "Unsupported symmetric key type: 17". What symmetric key type is then supported by SecKeyCreateWithData?

    Kind regards, Jakob

Add a Comment

But for encryption/decryption I need a SecKey.

What API are you using for these cryptographic operations?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

  • For the encryption/decryption itself I am using the functions from SecTransform.h — and I am just realizing that they have been deprecated. I wrote my code about 5 years ago. Is CryptoKit the recommended replacement? Then I will try this… Thanks, Jakob

Add a Comment

For the encryption/decryption itself I am using the functions from SecTransform.h

Oh, yeah, that’s a blast from the past.

I am just realizing that they have been deprecated.

Right. SecTransform is one of the few subsystems that’s able to use a SecKey object containing a symmetric key.

Is CryptoKit the recommended replacement?

Yes and no. CryptoKit only supports a limited set of cryptographic operations, the ones that Apple encourages folks to use, so it may not suit your needs.

What specific transforms where you using?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I was using the SecTransforms created by SecEncryptTransformCreate and SecDecryptTransformCreate, just for encryption and decryption of certain binary data with a symmetric cipher. Judging from the documentation I found CryptoKit should be powerful enough to do the same.

Thanks, Jakob