Can't get SecKeyCreateWithData to work with private key from my App Store Connect account.

I've tried all kinds of ways to get a SecKeyRef from the .p8 file I downloaded from my App Store Connect account. The key itself looks OK, as openssl gives this result:

openssl asn1parse -in 359UpAdminKey.p8

0:d=0  hl=3 l= 147 cons: SEQUENCE          
3:d=1  hl=2 l=   1 prim: INTEGER           :00
6:d=1  hl=2 l=  19 cons: SEQUENCE          
8:d=2  hl=2 l=   7 prim: OBJECT            :id-ecPublicKey

17:d=2 hl=2 l= 8 prim: OBJECT :prime256v1 27:d=1 hl=2 l= 121 prim: OCTET STRING [HEX DUMP]:30...

My method for creating the key is:

'- (SecKeyRef)privateKeyFromP8:(NSURL *)p8FileURL error:(NSError **)error {

// Read the .p8 file
NSData *p8Data = [NSData dataWithContentsOfURL:p8FileURL options:0 error:error];
if (!p8Data) {
	return NULL;
}

// Convert P8 to base64 string, removing header/footer
NSString *p8String = [[NSString alloc] initWithData:p8Data encoding:NSUTF8StringEncoding];
	
NSArray *lines = [p8String componentsSeparatedByString:@"\n"];
NSMutableString *base64String = [NSMutableString string];

for (NSString *line in lines) {
	if (![line containsString:@"PRIVATE KEY"]) {
		[base64String appendString:line];
	}
}
	
// Decode base64 to raw key data
NSData *keyData = [[NSData alloc] initWithBase64EncodedString:base64String options:0];
if (!keyData) {
	if (error) {
		*error = [NSError errorWithDomain:@"P8ImportError"
											  code:1
										 userInfo:@{NSLocalizedDescriptionKey: @"Failed to decode base64 data"}];
	}
	return NULL;
}
	
// Set up key parameters
NSDictionary *attributes = @{
	(__bridge NSString *)kSecAttrKeyType: (__bridge NSString *)kSecAttrKeyTypeECSECPrimeRandom,
	(__bridge NSString *)kSecAttrKeyClass: (__bridge NSString *)kSecAttrKeyClassPrivate,
	(__bridge NSString *)kSecAttrKeySizeInBits: @256
};

// Create SecKeyRef from the raw key data
CFErrorRef keyError = NULL;
SecKeyRef privateKey = SecKeyCreateWithData((__bridge CFDataRef)p8Data,
														  (__bridge CFDictionaryRef)attributes,
														  &keyError);

if (!privateKey && keyError) {
	*error = (__bridge_transfer NSError *)keyError;
	NSError *bridgeError = (__bridge NSError *)keyError;
	if (error) {
		*error = bridgeError; // Pass the bridged error back to the caller
	}
	NSLog(@"Key Error: %@", bridgeError.localizedDescription);
}

return privateKey;

} `

I get this error from SecKeyCreateWithData

The operation couldn’t be completed. (OSStatus error -50 - EC private key creation from data failed)

Filed a DTS incident, but they won't be back until after the New Year.

I've tried all kinds of things. Various AI chatbots, etc. Nothing seems to be working. I'm sure the problem is something elementary, but have spent hours on this with no luck.

Help, please.

Answered by 359Steve in 820187022

Never mind. Turns out you can't actually do this directly with SecKeyCreateWithData, you have to switch to Swift CryptoKit. See:

https://developer.apple.com/forums/thread/680572

func createSecKeyWithPEMSecp256r1Private(_ pem: String) throws -> SecKey {
    let privateKeyCK = try P256.Signing.PrivateKey(pemRepresentation: pem)
    let x963Data = privateKeyCK.x963Representation
    var errorQ: Unmanaged<CFError>? = nil
    guard let privateKeySF = SecKeyCreateWithData(x963Data as NSData, [
        kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom,
        kSecAttrKeyClass: kSecAttrKeyClassPrivate,
    ] as NSDictionary, &errorQ) else {
        throw errorQ!.takeRetainedValue()
    }
    return privateKeySF
}

Never mind. Turns out you can't actually do this directly with SecKeyCreateWithData, you have to switch to Swift CryptoKit. See:

https://developer.apple.com/forums/thread/680572

func createSecKeyWithPEMSecp256r1Private(_ pem: String) throws -> SecKey {
    let privateKeyCK = try P256.Signing.PrivateKey(pemRepresentation: pem)
    let x963Data = privateKeyCK.x963Representation
    var errorQ: Unmanaged<CFError>? = nil
    guard let privateKeySF = SecKeyCreateWithData(x963Data as NSData, [
        kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom,
        kSecAttrKeyClass: kSecAttrKeyClassPrivate,
    ] as NSDictionary, &errorQ) else {
        throw errorQ!.takeRetainedValue()
    }
    return privateKeySF
}
Can't get SecKeyCreateWithData to work with private key from my App Store Connect account.
 
 
Q