0

Update

Misleading question:

From the discussion below as well as this question formulated thereafter ...

... it became clear that the assumption leading to this question ...

'iOS: Creating PublicKey in PKCS-Format instead of ASN.1-Format'

... was fundamentally wrong.

Fixing the assumptions

Hence the assumptions should have been:

  • Swift (iOS) produces PKCS#1-formatted keys
  • Java 17 produces keys which look alike but are slightly different using SubjectPublicKeyInfo (or SPKI)

For the sake of documentation, the question remains untouched (below)


Objective

Creating a PublicKey in PKCS-format:

  • Generated on an iOS-device (Swift)

General approach

iOS generates PublicKeys which are represented in ASN.1-Format

Sample: Generating a KeyPair (ASN.1-Format)

SampleCode to extract the PublicKey in ASN.1-Format from the KeyPair (Swift):

// Keypair attributes
let tag = "my_personal_keystore_keypair_alias".data(using: .utf8)!
let attributes: [String: Any] =
    [kSecAttrKeyType as String:            kSecAttrKeyTypeRSA,
     kSecAttrKeySizeInBits as String:      "4096",
     kSecPrivateKeyAttrs as String:
        [kSecAttrIsPermanent as String:    true,
         kSecAttrApplicationTag as String: tag]
]
var error: Unmanaged<CFError>?

// Generate PrivateKey / Keypair
guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
    throw error!.takeRetainedValue() as Error
}

// Extract PublicKey
guard let publicKey = SecKeyCopyPublicKey(privateKey),
      let publicKeyOptional = SecKeyCopyExternalRepresentation(publicKey, nil) else {
    return "PublicKey could not be accessed."
}
let publicKeyData = publicKeyOptional as Data
let base64PublicKey = publicKeyData.base64EncodedString()
print("PublicKey, base64:   ", base64PublicKey)

Problem

I am missing an option to retrieve the PublicKey in PKCS-Format.

Apple Developer Documentation

There seems to be some kind of a SecItemExport, but it lacks explanation to me.

Stackoverflow

The question is not new in its intent, still the best answer is linked to a dead resource and hence of no use.

Additional condition

External libraries for key generation are not allowed.

  • The intent is that it is not possible to trust sources to handle PrivateKeys properly. Therefore only sources from Apple are trusted.
  • Nevertheless, using a library to convert the PublicKey (only) from ASN.1 into PKCS-format would be feasible.

Anyways

Thanks for reading & sharing - any help is appreciated :)

Appendix for experimentation

Adding public keys which are produced by the given code. I serve multiple to prevent 'lucky shots' .. ;-)

First:

MIICCgKCAgEAl0HYn9IdRmexAR9dSh3SxmFazWF0RV2TKmtRxGySvCA+aHZ/Dp+8tC0YDWpQzP+tZdlDWNOBj/D7i1z4b+UZk8F9ZEoi+w61kYQz+KjMkRuYrPBFi4A/gsS2qGeFJ4OvLQzGObZ0C+5/E+wunUWyQCVjgjTHKH8yqfVXeWYFKmaSSZblSZJAObE8Ao5J38DMINF1oWG+GdZt8RTLf35ULLEa8zKvFXrfBkDjiQH90WKPwDxWwvFInqZhjpsFxLytiKW+iBLqa4+0P7uwXVodFXa38RW9dk9mEsLvj6764BKtPAaWym9XZfEZNBu0jwlfO07k0augynGps6bsSIyYglDImlTRagdA/e+1AMBlSxEFVO4NpCjEpMT7rNX/LYPeEaJ8fTC3axOM1yEntcwUfSSCDulVPGlWlFbPxt29y1RrGtMmwfbTlbOQf2okMf0mGx9Ytd9HWadIdWh4FqDVWA8MF82PP1YsOW5TA0hkprK1qJwfkaLRKnmpfL5a7gWn4HWzpdDqrezhbc/zTCeHbX5c61mgWsAIWnB3fyXsJHpR62+QtBEznwhDxafVCQyUmsDqbncBxilEnFIn08G+6ox2PQC8GhNdpFVGsSoqpDfctsm51/tUYLpyeIBdzw/3nMLL1J5jL3yWr7ZKgnzNwjpC8l6c6gpsF3NRodeVhp8CAwEAAQ==

Second:

MIICCgKCAgEAlSbN7rlX6EMCDGuxQm9G6qqXIWshDvI5VaN4QPNCFcFzPjI/FyaHqi43+mxTyKGycT6TNqvanSu67yoIA80tSlFH2LndWv6sPQeHKxNwwFKU98Y/uL3M6hKIVXDwa6kZGM58dfY9qMWEOPXB4AwZtVaxJ4ePHFAR0kEOAHLCPpQxFkNlkg9FlCwlBzZbhHkI5uhCmlGEiLpLaJNJzjn7yo33m65189J6tIh3vopZ2ahFHb/vo6SVSbtS7Y0YlinJwH3MCGLm5+pKBpE64t5lgEhDPYSF7pKpLhEVqC5ETaya3mYTkXPSCiY/9Mo5zddniUGrxAJaY940jY3QNYeFmWPEEdhhIW2tUbuiM3IlHAqk4Du5p/2o1QcSVZdBsHStSGdcWqs00Z+ooxXwrOpMOUnZeb8Jt5dGDyHwjOmPf0N8dDQwz+5pgOoTkxd/z5cTK9tMv/nC+Mbbt8LRsct16M3LYrRAYnA8unX1ZD3eXTJPOSB/fM9Hmf1ObxQro9tatC5RaJjS0Xg5aepUsey62BW9lj4kHCkRPD4w1OmjDWGUCOSEhwy0KwqFyRBppYUMndEbJb3GKEjpekcQYwjERPtH/vEVxaN5gGYaCORancUaNH+d03zAmi0G830QXQvyohyKUkGw5qljEBH5R5Wqu7YLTlUes0rQEx8DpLVclaMCAwEAAQ==

Third:

MIICCgKCAgEA1ZqMyEHgyW/uFK0+BRbByiu2ZMG/HsasoC27h4FEjvSxQQTtMgAZpoFNAjLstDWcN6PtT4137LVW3L0nsYvth+MG91mkpiByqoCNc6RigQDODNkmPlOk0ICIBII06CYx/FhzyVnm+idbi+TCZ4k9SFYkqN4iuve3QSDp8AJjIoKQEdJGcwiSE85eMXoNLmqCJ0ACxEYLHUI8n/rm2Zo3pJNRYL/WIsJvjzZAFHJ0I8ZwGzB7pNbTr6IGiXFxy8mZ51/yaQCe2/sPQLIVlYwD+lBCpDNoX3S86JLCEWOHmvntcPoPyvKnyaaE4i8yU1XUtCC1oSK4yodJPSrCzixIjG72P/puoUkTHWsLzPQ3yVVJYztvp+ETVwUj+wm8VD5GzbnPrwkO5MctmRhIEPZ1s63Tv4we1PtjlsFvsFPTYm1nuoSgsscfdjcb1/YFF/JcnVreuQcuHNrxecSxa47XzuETb5CfvoB+pVj7hZjOkEABWWcpaMTciIDk9CYUNByM33YFCt8tIPB/uuC3Kt8EpdfkypHh7CcNgHv6O6YXeUuNrb7XjE5DdtcbRMVHHWo8bNzLOHYgd7HMY346Ie6Ko8SFGMNV4Npk+c2CGzZgpBvo3+PfjGfXQjBVcdt9asQvF1fc922Zx2Oyy7Uc+xmTHkpKZqZB2LU++N+aHOa/370CAwEAAQ==

The fastest way to check the keys is to use a website like this ( https://www.javainuse.com/rsagenerator ). Use the "RSA Encryption"-SubSection, paste one of the Keys including some sample payload to be encrypted. We expect the keys to be formatted as PKCS#1. Therefore for 'Cipher Type' RSA/ECB/PKCS1Padding or RSA/None/PKCS1Padding is chosen. Both lead to ' unknown key type passed to RSA' although the "RSA Generate Keys"-Subsection above produces 'alike'-RSA keys. Hence the iOS-Key has a different Format, which is ASN.1 Still, PKCS#1 is searched for .. :)

d.braun1991
  • 151
  • 1
  • 13
  • Which PKCS format do you require? For public keys, you probably want PKCS#1, and for RSA keys, that's what `SecKeyCopyExternalRepresentation` already produces. Maybe you want PEM output instead? You just output `-----BEGIN RSA PUBLIC KEY-----`, then the Base64 encoded PCKS#1 data, then `-----END RSA PUBLIC KEY-----`. – DarkDust Nov 25 '22 at 15:13
  • 1
    (Note that PKCS#1 is using ASN.1, like most PKCS formats.) – DarkDust Nov 25 '22 at 15:14
  • Hi @DarkDust , I'm pretty new to effectively conducting crypto. Right, the key is exported via `SecKeyCopyExternalRepresentation` and PKCS#1 is the required format. Before an encryption using standard javax.crypto was implemented in a Service first, using Keys with an `RSA/ECB/PKCS1Padding` - works fine. The iOS-PublicKey could be read using an Dependency for ASN. Still those - in the JavaService encrypted - data could not be decrypted in the iOS Device using the PrivateKey. Maybe I should have asked for an iOS KeyPair following `RSA/ECB/PKCS1Padding`. – d.braun1991 Nov 26 '22 at 15:26
  • 1
    I'm not sure I understand. You can export the public key, and import it in some other system. Correct? But you cannot export/import the private key? If so, you might need to export it in PKCS#8 format, with is PKCS#1 with just a few bytes prefixed (but I can't find an answer on SO that shows this fixed byte sequence). – DarkDust Nov 28 '22 at 08:33
  • Hi @DarkDust, sorry for letting you wait. Right, export of the PublicKey is possible - thats all I want in regards of 'sending' except the delivered format. I added some more Information in the appendix to challenge my issue and for playing around. I still think there has to be a single line of **swift** code to change the export format from ASN.1 to PKCS#1 ... .. . but I can not find the solution in the web, yet. Thanks for your time and patience :) – d.braun1991 Dec 17 '22 at 11:08
  • Maybe this will help me solve the issue (next days) .. https://swiftpackageindex.com/nextincrement/rsa-public-key-importer-exporter – d.braun1991 Dec 17 '22 at 11:12
  • Ok, I understand my fault .. I have an ASN.1-Format. .. ASN.1 encapsules (generic) all the other formats (e.g. PKCS#1). Hence I am not searching for a transformation between ASN.1 and PKCS#1 - I'm rather searching for the name of my Sub-Format, which is NOT PKCS#1. Thereafter I want to transform the given format to PKCS#1. – d.braun1991 Dec 17 '22 at 11:21
  • `SecKeyCopyExternalRepresentation` already gives you PKCS#1 output. Do you want to wrap it in PEM, maybe? – DarkDust Dec 17 '22 at 11:43
  • I assume you are right in regards of 'Its a PKCS#1-Format'. Maybe I should have given that possibility a higher credibility. You may wonder why I could not accept this earlier ... .. . ... .. . After sending the PublicKey to a Java-Service, I try to convert it just like a PKCS#1 Key generated by Java17 and it fails. Using a dependency called BouncyCastle lets me parse an ASN.1 Sequence and it works. Thats why I was so obsessed with ASN.1 – d.braun1991 Dec 17 '22 at 12:11
  • Code can be found here: https://stackoverflow.com/questions/74572468/unit-test-in-java-encryption-and-decryption-given-an-ios-keypair-in-asn-1-forma – d.braun1991 Dec 17 '22 at 12:12
  • Wrapping this up: **iOS** sends a PKCS#1 formated key. **Java17** creates PKCS#1 formatted keys as well. **Still** the keys do not apply to the same 'parsing' - alike the website in the *Appendix*-section of the question. – d.braun1991 Dec 17 '22 at 12:14
  • 1
    An RSA private key is just a collection of numbers. There are a bunch of ways to wrap those numbers into structured data. The numbers do not change, just the wrapper. Each wrapper type is documented. Once you know how to read the wrapper and the interior data, you can easily convert one format to another. The `openssl` program has a number of features to help you figure out the format. – John Hanley Dec 20 '22 at 00:18

0 Answers0