EC public key creation from data failed

When I try to create SecRef using the public key , I get "

Error Domain=NSOSStatusErrorDomain Code=-50 "EC public key creation from data failed" (paramErr: error in user parameter list) UserInfo={NSDescription=EC public key creation from data failed"


NSData *data = [[NSData alloc] initWithBase64EncodedString:key options:NSDataBase64DecodingIgnoreUnknownCharacters];

NSInteger sizeInBits = data.length;

NSDictionary* attributes =

@{ (id)kSecAttrKeyType: (id)kSecAttrKeyTypeECSECPrimeRandom,

(id)kSecAttrKeySizeInBits: @(sizeInBits),

(id)kSecPublicKeyAttrs:

@{ (id)kSecAttrIsPermanent: @YES,

(id)kSecAttrApplicationTag: tag

},

(id)kSecAttrCanSign:@YES,

(id)kSecAttrKeyClass: (id)kSecAttrKeyClassPublic

};



CFErrorRef error = NULL;

SecKeyRef secRef = SecKeyCreateWithData((__bridge CFDataRef)data,

(__bridge CFDictionaryRef)attributes,

&error);

Replies

As far as I can tell your key data is wonky. Consider this:

$ cat tmp.b64 
L2I9fahDGX373HLMxN1xy5rHaq9gIiMJGOodpLwAiijQP0j0rzZLOMHks6YnLixRWoltfEYggHLuF5zDj2v2onfQ04pdR4NtvtX1va/v+cbiyfoM4Nf5babVeYrFhYEqoE79jPrarPqgRmJWD2xnc1gB5JShhVyFn/IkyYndNqSy2w0pRiNh9NOdP3JYbsuNFJAtQujhVC2oI7KdNvAYqfDfwH2hGRgoMO2rlQvly3nVPN+SejPbGjQrehWc6Tq1f+/hGa6TEU5XD2DRNRBqaLSZTiNke4SViiU/76dhUjgg4GEKPAFlJkh8otxhengevWSgEtC8E+/vvifHIJ3vnw==
$ base64 -D < tmp.b64 > tmp.dat
$ ls -l tmp.dat 
-rw-r--r--@ 1 quinn  staff  256 10 May 11:29 tmp.dat

Your code takes the file length of 256 and uses it as the key size in bits. However, a 256 bit EC key is not 256 bytes long. Consider the following code:

@import Foundation;

int main(int argc, char **argv) {
    #pragma unused(argc)
    #pragma unused(argv)
    int                 retVal;

    @autoreleasepool {
        CFErrorRef error;
        SecKeyRef privateKey = SecKeyCreateRandomKey((__bridge CFDictionaryRef) @{
            (__bridge id) kSecAttrKeyType: (__bridge id) kSecAttrKeyTypeECSECPrimeRandom,
            (__bridge id) kSecAttrKeySizeInBits: @256
        }, &error);
        assert(privateKey != NULL);
        SecKeyRef publicKey = SecKeyCopyPublicKey(privateKey);
        assert(publicKey != NULL);
        NSData * publicKeyData = CFBridgingRelease( SecKeyCopyExternalRepresentation(publicKey, &error) );
        NSLog(@"%@", publicKeyData);
        NSLog(@"%zu", (size_t) publicKeyData.length);

        CFRelease(publicKey);
        CFRelease(privateKey);

        retVal = EXIT_SUCCESS;
    }

    return retVal;
}

It prints:

… <04e1573d 3e8828b5 d0792606 35346edd e71c1479 82cf3a32 7a26d647 94dfab54 c2b3a91b 60a8da18 46875fda d095895c 0349abdd 1c755b27 fe0c33e0 4856e358 fd>
… 65

So, a 256 bit EC public key is 65 bytes long and starts with an 04. Your key looks nothing like that:

$ hexdump -Cv tmp.dat
00000000  2f 62 3d 7d a8 43 19 7d  fb dc 72 cc c4 dd 71 cb  |/b=}.C.}..r...q.|
00000010  9a c7 6a af 60 22 23 09  18 ea 1d a4 bc 00 8a 28  |..j.`"#........(|
…

Normally folks run into this problem because their key is inside some ASN.1 wrapper. However that’s not the case here:

$ dumpasn1 -p tmp.dat 
Unknown (Reserved) {
  Unknown (Reserved) {
    [8] {
      GraphicString
        '..r...q...j.`"#........(.?H..6K8....'.,QZ.m|F .r'
        '.....k..w...]G.m...............m..y....*.N......'
        '.FbV.lgsX.....\...$...6....)F'
Error: Inconsistent object length, 60 bytes difference.
      }
Error: Inconsistent object length, 4 bytes difference.
    }
Error: Inconsistent object length, 33 bytes difference.
  }
Warning: Further data follows ASN.1 data at position 133.

So I don’t know where this key data comes from but it’s not 256 EC public key. I recommend you have a chat with whoever gave you this key data.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks Eskimo.

Its a RSA public key. When I try to add it I get

Error Domain=NSOSStatusErrorDomain Code=-50 "RSA public key creation from data failed" (paramErr: error in user parameter list) UserInfo={NSDescription=RSA public key creation from data failed}


NSData *data = [[NSData alloc] initWithBase64EncodedString:key options:0];

NSDictionary* attributes =

@{ (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA,

(id)kSecAttrKeySizeInBits: @2048,

(id)kSecPublicKeyAttrs:

@{ (id)kSecAttrIsPermanent: @YES,

(id)kSecAttrApplicationTag: tag1

},

(id)kSecAttrCanEncrypt:@YES,

(id)kSecAttrKeyClass: (id)kSecAttrKeyClassPublic

};


if(data == nil)

{

return nil;

}


CFErrorRef error = NULL;

SecKeyRef key1 = SecKeyCreateWithData((__bridge CFDataRef)data,

(__bridge CFDictionaryRef)attributes,

&error);

Its a RSA public key.

Well, that’s a big difference (-:

For an RSA key

SecKeyCreateWithData
expects the data in “PKCS#1 format”, that is, a DER-encode ASN.1
RSAPublicKey
structure. Per RFC 3447 this is:
RSAPublicKey ::= SEQUENCE {
    modulus           INTEGER,  -- n
    publicExponent    INTEGER   -- e
}

For example, here’s what I get if I modify the code from my previous post to output a 2048-bit RSA key:

$ hexdump -Cv tmp.dat
00000000  30 82 01 0a 02 82 01 01  00 a1 f6 36 c5 bd ce 39  |0..........6...9|
00000010  49 de b7 9d eb 84 e4 c2  da e7 86 8c 91 d1 c8 b0  |I...............|
…

This definitely looks like ASN.1, starting as it does with a 30 8x, which is typically what you see for an ASN.1

SEQUENCE
type. And lo! if you decode it with
dumpasn1
you can see the
RSAPublicKey
structure:
$ dumpasn1 -pa tmp.dat 
SEQUENCE {
  INTEGER
    00 A1 F6 36 C5 BD CE 39 49 DE B7 9D EB 84 E4 C2
    DA E7 86 8C 91 D1 C8 B0 C4 FA D4 C4 21 18 24 95
    CF 7D DE CD 89 F1 ED 5F 13 CA 88 5D 78 2D C1 B5
    21 5E 9E 6B 66 D8 B5 2C C3 FB 89 81 EE 2D BA 1B
    51 8E 54 64 34 47 94 9B 0C E3 F2 AD 18 0C 84 AF
    33 07 36 63 5D 31 F3 EE 34 5A 2F 6C 66 BE 0A 86
    E4 04 EE 64 A1 96 5A A8 FA 6F 5E A8 D8 39 30 A0
    34 86 3C CD B8 64 EE C3 B0 30 7D CE 03 E9 B6 ED
    CF D6 01 F3 F9 01 EC CC 22 9F 02 AF 18 8B 58 F7
    6D A3 22 2A 9E C7 D5 B0 3D E9 ED 7D C0 F5 EC 0A
    2E E7 92 BE EE E0 27 8E D4 19 2D AC 6E 36 75 DC
    74 29 6B F3 BA 00 80 81 E9 F6 61 E7 0F D9 55 04
    DA 6D E7 06 FC A2 BF 01 01 1C DA 0F DE 34 88 F4
    16 D1 31 C4 2C 16 9B 1B 73 67 13 ED 8D DB 5C C8
    F5 6E D9 37 5B 70 9F FC 66 80 CD 58 2A 6A AE CD
    3B 6D 87 06 F7 0B 77 97 59 5C 10 6B 47 66 5A A5
    55
  INTEGER 65537
  }

I suspect that the 256 bytes of data you’ve got is just the

modulus
field, although again it’s hard to say without looking at how this value was generated.

Wrapping a ‘*****’ modulus into an

RSAPublicKey
structure is tricky. A better option is to talk to whoever generated this key and ask them to generate something in the standard format.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"