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

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"

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

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

SecKeyCopyExternalRepresentation Fails for Symmetric Key
 
 
Q