Apple CryptoKit

RSS for tag

Perform cryptographic operations securely and efficiently using Apple CryptoKit.

Apple CryptoKit Documentation

Posts under Apple CryptoKit tag

35 results found
Sort by:
Post not yet marked as solved
34 Views

AES-GCM 256 Encrypt & Decrypt in iOS Swift Sync with .Net output

I want to use AES-GCM encryption of a plaintext with 'key' only. The 'key' will be received from backend (.net), in webservice response. The same key will be used later in backend as well to decrypt the encrypted value. I have used extension as follwoing To generate string to Symetric key extension SymmetricKey { init(string keyString: String, size: SymmetricKeySize = .bits256) throws { guard var keyData = keyString.data(using: .utf8) else { print("Could not create base64 encoded Data from String.") throw CryptoKitError.incorrectParameterSize } let keySizeBytes = size.bitCount / 8 keyData = keyData.subdata(in: 0..<keySizeBytes) guard keyData.count >= keySizeBytes else { throw CryptoKitError.incorrectKeySize } self.init(data: keyData) } } Encryption & Decryption code snipet: func aesgcmEncryptDecrypt() { let str : String = "FwhXRYJ$xLf?^Kh6_&YfTJ%RuG+EqcTY" var key : SymmetricKey = SymmetricKey(size: .bits256) do{ key = try SymmetricKey(string: str) }catch{ } let plain = "HOW ARE YOU?" let nonce = try! AES.GCM.Nonce(data: Data(base64Encoded: "fv1nixTVoYpSvpdA")!) let tag = Data(base64Encoded: "e1eIgoB4+lA/j3KDHhY4BQ==")! // Encrypt let sealedBox = try! AES.GCM.seal(plain.data(using: .utf8)!, using: key, nonce: nonce, authenticating: tag) // Decrypt let sealedBoxRestored = try! AES.GCM.SealedBox(combined: sealedBox.combined!) let decrypted = try! AES.GCM.open(sealedBoxRestored, using: key, authenticating: tag) Swift.print("Combined:\n(sealedBox.combined!.base64EncodedString())\n") Swift.print("Cipher:\n(sealedBox.ciphertext.base64EncodedString())\n") Swift.print("Nonce:\n(nonce.withUnsafeBytes { Data(Array($0)).base64EncodedString() })\n") Swift.print("Tag:\n(tag.base64EncodedString())\n") Swift.print("Decrypted:\n(String(data: decrypted, encoding: .utf8)!)\n") } Our(generated from this code & .Net code) encrypted text is not matching. Anyone can help me, what I am doing wrong, detailing will be more helpful. Basically I was looking for saloution in Objective-C but I did not get any supported library for Objective-C. Using the AesGcm class
Asked
by Rahul9663.
Last updated
.
Post not yet marked as solved
48 Views

AES-GCM 256 Encrypt & Decrypt in iOS Swift Sync with .Net output

Hi I want to use AES-GCM encryption of a plaintext with 'key' only. The 'key' will be received from backend (.net), in webservice response. The same key will be used later in backend as well to decrypt the encrypted value. I have used extension as follwoing To generate string to Symetric key extension SymmetricKey { init(string keyString: String, size: SymmetricKeySize = .bits256) throws { guard var keyData = keyString.data(using: .utf8) else { print("Could not create base64 encoded Data from String.") throw CryptoKitError.incorrectParameterSize } let keySizeBytes = size.bitCount / 8 keyData = keyData.subdata(in: 0..<keySizeBytes) guard keyData.count >= keySizeBytes else { throw CryptoKitError.incorrectKeySize } self.init(data: keyData) } } Encryption & Decryption code snipet: func aesgcmEncryptDecrypt() { let str : String = "FwhXRYJ$xLf?^Kh6_&YfTJ%RuG+EqcTY" var key : SymmetricKey = SymmetricKey(size: .bits256) do{ key = try SymmetricKey(string: str) }catch{ } let plain = "HOW ARE YOU?" let nonce = try! AES.GCM.Nonce(data: Data(base64Encoded: "fv1nixTVoYpSvpdA")!) let tag = Data(base64Encoded: "e1eIgoB4+lA/j3KDHhY4BQ==")! // Encrypt let sealedBox = try! AES.GCM.seal(plain.data(using: .utf8)!, using: key, nonce: nonce, authenticating: tag) // Decrypt let sealedBoxRestored = try! AES.GCM.SealedBox(combined: sealedBox.combined!) let decrypted = try! AES.GCM.open(sealedBoxRestored, using: key, authenticating: tag) Swift.print("Combined:\n(sealedBox.combined!.base64EncodedString())\n") Swift.print("Cipher:\n(sealedBox.ciphertext.base64EncodedString())\n") Swift.print("Nonce:\n(nonce.withUnsafeBytes { Data(Array($0)).base64EncodedString() })\n") Swift.print("Tag:\n(tag.base64EncodedString())\n") Swift.print("Decrypted:\n(String(data: decrypted, encoding: .utf8)!)\n") } Our(generated from this code & .Net code) encrypted text is not matching. Anyone can help me, what I am doing wrong, detailing will be more helpful. Basically I was looking for saloution in Objective-C but I did not get any supported library for Objective-C.
Asked
by Biswa.
Last updated
.
Post not yet marked as solved
57 Views

Mac OS 11.4 Token Sign not working

I'm having a problem accessing a site where I need to use a certificate for identification, where I used some examples to type the pin but none works, I checked an instruction to register a module in firefox as a security device but it doesn't work, it worked on macos 10.15 , but now when adding the security device , the slot does not appear in Firefox. Tank's
Asked Last updated
.
Post not yet marked as solved
80 Views

SecKeyCreateWithData Returns ‘Nil’ with Error

We are trying to create a ’SecKey’ from a ‘.der’ file. But ‘SecKeyCreateWithData’ always throw ‘Nil ’ with Error. Steps Followed:: First we created a ECDSA Private & Public key pair with the below Commands , then converted the .pem file holding the private key to ‘.der’file. Finally used the ‘.der’ file to generate a ‘SecKey’ via code. Commands Used to Generate Private & Public Keys:: openssl ecparam -genkey -name prime256v1 -noout -out ec-key-pair.pem openssl ec -in ec-key-pair.pem -pubout -out ec-key-pair.pub Command Used to Generate .Der file:: openssl pkey -outform der -in ec-key-pair.pem -out ec-key-pair.der Content Inside .pem file:: -----BEGIN EC PRIVATE KEY----- MHcCAQEEIKJTc3zI8D07Myh7ZIR+wGyQgsjEeKdH0+hSiErK5AjzoAoGCCqGSM49 AwEHoUQDQgAEvbOBrM/D2fX05zKQYuJiTRP6YiUBabImrHb9s+OHimxUxX+E9jVe oQ6nxSOkfgm0H1OjLfp2xGLqkDTuF38UGQ== -----END EC PRIVATE KEY----- Error Received:: Unmanaged - _value : Error Domain=NSOSStatusErrorDomain Code=-50 "EC private key creation from data failed" UserInfo={NSDescription=EC private key creation from data failed} Minimum Deployment Target Used:: iOS 14.0 Code Used:: if let certificateData = NSData(contentsOf:Bundle.main.url(forResource: "ec-key-pair", withExtension: "der")! ) {       var error: Unmanaged<CFError>? = nil       let privateSecKey = SecKeyCreateWithData(certificateData , [           kSecAttrKeyType: kSecAttrKeyTypeEC,           kSecAttrKeyClass: kSecAttrKeyClassPrivate] as NSDictionary, &error) }
Asked Last updated
.
Post not yet marked as solved
67 Views

How to convert base64 encoded private key and public key with EC with secp256r1 (curve) to SecKey using swift4 code?

I am searching for a way using swift4 code (not terminal commands) to convert base64 encoded private key and public key with EC with secp256r1 (curve) to SecKey. After I get private and public SecKey, I will be signing some data and verifying the same with SHA256withECDSA algorithm.
Asked
by nbhal.
Last updated
.
Post not yet marked as solved
2.6k Views

macOS 11 Big Sur breaks ssh-add -s /usr/lib/ssh-keychain.dylib

I am trying to add my smart card PIV cert to ssh-agent. In macOS 10.15 Catalina, it was as simple as: ssh-add -s /usr/lib/ssh-keychain.dylib But in macOS 11.1 Big Sur, the ssh-agent debug output says: failed PKCS#11 add of "/usr/lib/ssh-keychain.dylib": realpath: No such file or directory I am aware that macOS 11 caches system libraries ... but I believe that /usr/lib/ssh-keychain.dylib is in the cache. Any help would be greatly appreciated!
Asked
by jrnphd.
Last updated
.
Post not yet marked as solved
92 Views

RSA Key Generating use Security, SecKeyCreateRandomKey

i want make RSA pair key to 512bit i find SecKeyCreateRandomKey, CrytoKit, another open lib.. I decided to use Security I have to give the server developer the string value of the rsa file I created I sent you an rsa string but server developer answered that the format was wrong I wonder what is wrong with my code. Or I want to be helped to generate an rsa key and chage type into a string this is my code first - make private key using SecKeyCreateRandomKey func createPrivateKey()-> SecKey?{           let privateKeyParams: [String: Any] = [       kSecAttrIsPermanent as String: true,       kSecAttrApplicationTag as String: tagName     ]           let parameters: [String: Any] = [       kSecAttrKeyType as String: kSecAttrKeyTypeRSA,       kSecAttrKeySizeInBits as String: 512,       kSecPrivateKeyAttrs as String: privateKeyParams     ]           var error: Unmanaged<CFError>?           guard let privateKey = SecKeyCreateRandomKey(parameters as CFDictionary, &error) else     {       NSLog("\tError generating keypair. %@", "\(error!.takeRetainedValue().localizedDescription)")       return nil     }     return privateKey   } second - get public key using private key of Seckey func getPublicKey(key: SecKey) -> SecKey?{     return SecKeyCopyPublicKey(key)   } third - get public key Data using public key seckey func getPublicData(key: SecKey) -> CFData?{     return SecKeyCopyExternalRepresentation(key, nil)   } fouth - string of public key using public key of Data  public func exportPublicKey(_ rawPublicKeyBytes: Data, base64EncodingOptions: Data.Base64EncodingOptions = []) -> String?   {    Log.debug("exportPublicKey", rawPublicKeyBytes.base64EncodedString(options: base64EncodingOptions))     return rawPublicKeyBytes.base64EncodedString(options: base64EncodingOptions)   } last i send result of exportPublicKey() rsa string like this MEgCQQDCmgOuSGbG/Mtq2NnHlBQU5rsGnNf17h4NZy+2lyrjKGgaVpD66QHmx2Na+/QQaamEhUgkFAkj0UlkMTRWGKO5AgMBBBE= or -----BEGIN PUBLIC KEY----- MEgCQQDCmgOuSGbG/Mtq2NnHlBQU5rsGnNf17h4NZy+2lyrjKGgaVpD66QHmx2Na+/QQaamEhUgkFAkj0UlkMTRWGKO5AgMBBBE= -----END PUBLIC KEY-----
Asked
by tedev.
Last updated
.
Post not yet marked as solved
253 Views

On Cryptographic Key Formats

I regularly see folks having problems importing cryptographic keys, so I thought I’d write down some hints and tips on how to recognise and import the various key formats. This post describes how to recognise the format of the data you have. A companion post, Importing Cryptographic Keys - https://developer.apple.com/forums/thread/680572, discusses how to import each type of key. If you have questions about any of this stuff, please put them in a new thread, tagging it with Security or Apple CryptoKit. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" On Cryptographic Key Formats To import a key you must first work out its format and then align that format with one of the import routines in Security framework or Apple CryptoKit. This post covers the first step, figuring out the format of the key you’re working with. This is surprisingly tricky because: There are a number of different key types with a number of different encodings. In many cases the source of your key does not clearly document its type and encoding. In some cases the documentation you do get is out-and-out wrong. Public and private keys come in a variety of types but the ones supported by Apple are: RSA SECG secp256r1, aka NIST P-256 SECG secp384r1, aka NIST P-384 SECG secp521r1, aka NIST P-521 Curve 25519 Such keys can be encoded in a number of different ways: PEM - https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail DER encoded ASN.1 - https://en.wikipedia.org/wiki/X.690#DER_encoding Raw key bytes These encodings can be nested, and the same key can be nested in multiple different ways. For example, an RSA key may be DER encoded and then PEM encoded, or it may be directly PEM encoded. Once you understand the format of the key you’re trying to import, read Importing Cryptographic Keys - https://developer.apple.com/forums/thread/680572 for information on how to import that key. PEM PEM - https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail (short for Privacy-Enhanced Mail) is a text file format that’s easy to spot. For example: % cat public-key-p256.pem----BEGIN PUBLIC KEY MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELCHzcEnURkr78BgTxRpOHveoEB0q oStqiJY1vHw36QEb/dVABv3r2u8NhqbWYlYTR5gslSdgE9HBzS14Za/wIw==----END PUBLIC KEY PEM is a very flexible format. It’s not uncommon for PEM files to contain metadata outside of the BEGIN and END encapsulation boundaries, or multiple credentials within the same file, each with its own encapsulation boundaries. However, the critical things to note are the: Label Encapsulated Data The label identifies the type of credential represented by the PEM. The example above is a public key (PUBLIC KEY) but you might see a private key (PRIVATE KEY), a certificate (CERTIFICATE), a specific type of key (for example, RSA PUBLIC KEY), and so on. IMPORTANT Generic keys (PUBLIC KEY and PRIVATE KEY) use a different format from typed keys (for example, RSA PUBLIC KEY and RSA PRIVATE KEY). However, it’s not uncommon for PEMs to be mislabelled, for example, be labelled PRIVATE KEY but contain an EC PRIVATE KEY. Ain’t crypto fun!?! The encapsulated data, the Base64 encoded data between the encapsulation boundaries, represents the credential itself. You interpret this data based on the label. For example, a public key’s data is an DER-encode ASN.1 SubjectPublicKeyInfo structure (more on this below) and to interpret that you first decode the Base64 and then dump the ASN.1: % base64 -D > public-key-p256.der MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELCHzcEnURkr78BgTxRpOHveoEB0q oStqiJY1vHw36QEb/dVABv3r2u8NhqbWYlYTR5gslSdgE9HBzS14Za/wIw== ^D % dumpasn1 -p -a public-key-p256.der SEQUENCE { &#9;SEQUENCE { &#9;&#9;OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) &#9;&#9;OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) &#9;&#9;} &#9;BIT STRING &#9;&#9;04 2C 21 F3 70 49 D4 46 4A FB F0 18 13 C5 1A 4E &#9;&#9;1E F7 A8 10 1D 2A A1 2B 6A 88 96 35 BC 7C 37 E9 &#9;&#9;01 1B FD D5 40 06 FD EB DA EF 0D 86 A6 D6 62 56 &#9;&#9;13 47 98 2C 95 27 60 13 D1 C1 CD 2D 78 65 AF F0 &#9;&#9;23 &#9;} I’m using the dumpasn1 tool, available here - https://www.cs.auckland.ac.nz/~pgut001/dumpasn1.c. Note There are easier ways to decode PEM files, most notably the openssl tool. I’m deliberately using primitive methods to illustrate how the parts fit together. DER Encoded ASN.1 ASN.1 - https://en.wikipedia.org/wiki/ASN.1 is a very flexible format for describing data structures. ASN.1 can be encoded in various ways but, in a cryptographic context you most commonly see DER-encoded ASN.1 - https://en.wikipedia.org/wiki/ASN.1#Example_encoded_in_DER. Recognising DER data isn’t always easy, although there are some tricks. Consider this hex dump of the public-key.asn1 file from the previous section: % xxd -p public-key-p256.der 3059301306072a8648ce3d020106082a8648ce3d030107034200042c21f3 7049d4464afbf01813c51a4e1ef7a8101d2aa12b6a889635bc7c37e9011b fdd54006fdebdaef0d86a6d662561347982c95276013d1c1cd2d7865aff0 23 The presence of the leading 0x30 is a common indicator that you’re looking at DER-encoded ASN.1 (that’s because 0x30 is the most common encoding for the ASN.1 SEQUENCE element). If you suspect that the data is DER, run dumpasn1 to confirm that: % dumpasn1 -p -a public-key-p256.der SEQUENCE { &#9;SEQUENCE { &#9;&#9;OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) &#9;&#9;OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) &#9;&#9;} &#9;BIT STRING &#9;&#9;04 2C 21 F3 70 49 D4 46 4A FB F0 18 13 C5 1A 4E &#9;&#9;1E F7 A8 10 1D 2A A1 2B 6A 88 96 35 BC 7C 37 E9 &#9;&#9;01 1B FD D5 40 06 FD EB DA EF 0D 86 A6 D6 62 56 &#9;&#9;13 47 98 2C 95 27 60 13 D1 C1 CD 2D 78 65 AF F0 &#9;&#9;23 &#9;} A ‘clean’ dump confirms that you’re looking at DER-encoded ASN.1. The question then becomes “What type of data is this?” If the ASN.1 came from a PEM, the PEM’s label indicates the type. If not, it’s helpful if you can match the ASN.1 against the well-known structures discussed below. Public Key A public key (PEM label PUBLIC KEY) is held in an ASN.1 SubjectPublicKeyInfo structure, as defined in RFC 5280 - https://tools.ietf.org/html/rfc5280. For example: % xxd -p public-key-p256.der 3059301306072a8648ce3d020106082a8648ce3d030107034200042c21f3 7049d4464afbf01813c51a4e1ef7a8101d2aa12b6a889635bc7c37e9011b fdd54006fdebdaef0d86a6d662561347982c95276013d1c1cd2d7865aff0 23 % % dumpasn1 -p -a public-key-p256.der SEQUENCE { &#9;SEQUENCE { &#9;&#9;OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) &#9;&#9;OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) &#9;&#9;} &#9;BIT STRING &#9;&#9;04 2C 21 F3 70 49 D4 46 4A FB F0 18 13 C5 1A 4E &#9;&#9;1E F7 A8 10 1D 2A A1 2B 6A 88 96 35 BC 7C 37 E9 &#9;&#9;01 1B FD D5 40 06 FD EB DA EF 0D 86 A6 D6 62 56 &#9;&#9;13 47 98 2C 95 27 60 13 D1 C1 CD 2D 78 65 AF F0 &#9;&#9;23 &#9;} The SEQUENCE starting on line 9 identifies the key algorithm. dumpasn1 helps you out here by decoding the OBJECT IDENTIFIER (OID) into a human readable form. In this case ecPublicKey indicates that we’re looking at an elliptic curve key - https://en.wikipedia.org/wiki/Elliptic-curve_cryptography. The remainder of this sequence holds algorithm parameters, discussed below. Finally, the BIT STRING starting on line 13 contains the public key, the format of which depends on the algorithm; see the Typed Public Key section for details. The algorithm parameters vary by algorithm: RSA keys have no parameters. Common EC keys have a single parameter indicating a named elliptic curve. In the above example, prime256v1 indicates a specific curve defined by SECG - https://en.wikipedia.org/wiki/SECG. You may also see an EC key with a complex set of parameters that defines the specific curve to use. Note Security framework and Apple CryptoKit support specific named curves (more on those below). If you have a key with complex parameters, you will not be able to use it with those APIs. Take care when reading curve names because they can contain subtle differences. For example, secp256r1 is different from secp256k1, and the latter is not supported by Apple platforms. Also, some curves have multiple common names. For example, dumpasn1 display a secp256r1 curve using the old prime256v1 name whereas in other situations you might see the newer secp256r1 name. When in doubt, check the OID against the documentation. Specifically: RFC 3279 - https://tools.ietf.org/html/rfc3279 lists the OIDs for RSA keys. RFC 5480 - https://tools.ietf.org/html/rfc5480 lists the OIDs for SECG keys. RFC 8410 - https://tools.ietf.org/html/rfc8410 lists the OIDs for Curve 25519 keys. For the keys supported by Apple platforms, here’s what you’ll see reported by dumpasn1: RSA: rsaEncryption (1 2 840 113549 1 1 1) SECG secp256r1: prime256v1 (1 2 840 10045 3 1 7) SECG secp384r1: secp384r1 (1 3 132 0 34) SECG secp521r1: secp521r1 (1 3 132 0 35) Curve 25519: curveEd25519 (1 3 101 112) Private Key A private key (PEM label PRIVATE KEY) is held in a PKCS#8 structure, as defined by RFC 5208 - https://tools.ietf.org/html/rfc5208. There are two possibilities here: A plaintext private key, defined by the PrivateKeyInfo structure. An encrypted private key, defined by the EncryptedPrivateKeyInfo. I’m going to focus on the first one. Note RFC 5208 has been obsoleted by RFC 5958 - https://tools.ietf.org/html/rfc5958 but I’m referencing the old RFC because I find it easier to read. When you dump a PrivateKeyInfo structure you’ll see something like this: % xxd -p private-key-p256.der 308187020100301306072a8648ce3d020106082a8648ce3d030107046d30 6b0201010420986a7a91cbb5f4f81636e81aaff0835a771dc66865c407a8 e84469cf6ab8a477a144034200049747e981aab8ea71a255cd9a1562858c 406006f1e418260d31e1a77f6c2b35a9a3132f232db00351d9d8003487d4 ee52847990313daa7c721f88d4bb56da91c7 % % dumpasn1 -p -a -e private-key-p256.der SEQUENCE { &#9;INTEGER 0 &#9;SEQUENCE { &#9;&#9;OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) &#9;&#9;OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) &#9;&#9;} &#9;OCTET STRING &#9;&#9;30 6B 02 01 01 04 20 98 6A 7A 91 CB B5 F4 F8 16 &#9;&#9;36 E8 1A AF F0 83 5A 77 1D C6 68 65 C4 07 A8 E8 &#9;&#9;44 69 CF 6A B8 A4 77 A1 44 03 42 00 04 97 47 E9 &#9;&#9;81 AA B8 EA 71 A2 55 CD 9A 15 62 85 8C 40 60 06 &#9;&#9;F1 E4 18 26 0D 31 E1 A7 7F 6C 2B 35 A9 A3 13 2F &#9;&#9;23 2D B0 03 51 D9 D8 00 34 87 D4 EE 52 84 79 90 &#9;&#9;31 3D AA 7C 72 1F 88 D4 BB 56 DA 91 C7 &#9;} The INTEGER on line 10 is a version number. The SEQUENCE starting on line 11 is the key algorithm; see the discussion in the Public Key section, above. The OCTET STRING starting on line 15 is the private key, the format of which depends on the algorithm; see the Typed Private Key section for details. IMPORTANT If you receive a PEM labelled PRIVATE KEY that doesn’t match up with this PrivateKeyInfo structure, there are two possibilities: The private key may be encrypted. In that case decrypt it using the openssl tool. The private key may be mislabelled. It’s depressingly common to find a typed private key labelled as PRIVATE KEY. Typed Public Key A typed public key has a label AAA PUBLIC KEY, where AAA denotes an algorithm. Typed public keys are relatively rare, but it’s important to understand the format because it’s this format that’s encapsulated within the SubjectPublicKeyInfo struct in the PUBLIC KEY format. The format for the typed public key data varies by algorithm. For the algorithms supported by Apple platforms, the data in the typed public key matches the public key’s raw key bytes; see Raw Key Bytes for the details. Typed Private Keys A typed private key has a label AAA PRIVATE KEY, where AAA denotes an algorithm. Typed private keys are relatively rare, but it’s important to understand the format because it’s this format that’s encapsulated within the PrivateKeyInfo structure in the PRIVATE KEY format. The format for the typed private key data varies by algorithm. For an RSA key it matches the raw key bytes of the private key; see Raw Key Bytes for the details. For other key types that’s not the case. Curve 25519 is an easy one: % xxd -p curve25519-private-key.der 04209fd90805255bae86a6c3035b2de837e929ea792ea11fd466e67ed0b2 65c0a999 % % dumpasn1 -p -a curve25519-private-key.der OCTET STRING &#9;9F D9 08 05 25 5B AE 86 A6 C3 03 5B 2D E8 37 E9 &#9;29 EA 79 2E A1 1F D4 66 E6 7E D0 B2 65 C0 A9 99 The raw key bytes is simply wrapped in an OCTET STRING. In contrast, the story for SECG keys is more complex. Consider this: % xxd -p p256-private-key.der 308187020100301306072a8648ce3d020106082a8648ce3d030107046d30 6b0201010420986a7a91cbb5f4f81636e81aaff0835a771dc66865c407a8 e84469cf6ab8a477a144034200049747e981aab8ea71a255cd9a1562858c 406006f1e418260d31e1a77f6c2b35a9a3132f232db00351d9d8003487d4 ee52847990313daa7c721f88d4bb56da91c7 % % dumpasn1 -p -a p256-private-key.der SEQUENCE { &#9;INTEGER 0 &#9;SEQUENCE { &#9;&#9;OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) &#9;&#9;OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) &#9;&#9;} &#9;OCTET STRING, encapsulates { &#9;&#9;SEQUENCE { &#9;&#9;&#9;INTEGER 1 &#9;&#9;&#9;OCTET STRING &#9;&#9;&#9;&#9;98 6A 7A 91 CB B5 F4 F8 16 36 E8 1A AF F0 83 5A &#9;&#9;&#9;&#9;77 1D C6 68 65 C4 07 A8 E8 44 69 CF 6A B8 A4 77 &#9;&#9;&#9;[1] { &#9;&#9;&#9;&#9;BIT STRING &#9;&#9;&#9;&#9;&#9;04 97 47 E9 81 AA B8 EA 71 A2 55 CD 9A 15 62 85 &#9;&#9;&#9;&#9;&#9;8C 40 60 06 F1 E4 18 26 0D 31 E1 A7 7F 6C 2B 35 &#9;&#9;&#9;&#9;&#9;A9 A3 13 2F 23 2D B0 03 51 D9 D8 00 34 87 D4 EE &#9;&#9;&#9;&#9;&#9;52 84 79 90 31 3D AA 7C 72 1F 88 D4 BB 56 DA 91 &#9;&#9;&#9;&#9;&#9;C7 &#9;&#9;&#9;&#9;} &#9;&#9;&#9;} &#9;&#9;} &#9;} This is an ASN.1 ECPrivateKey structure, as defined by RFC 5915 - https://tools.ietf.org/html/rfc5915. The raw key bytes are split between two fields: The BIT STRING starting on line 22 contains the marker (04) and the X and Y values. The OCTET STRING starting on line 18 contains the K value. See Raw Key Bytes for more information on these values. Raw Key Bytes It should come as no surprise that the raw key bytes are different for each algorithm. RSA An RSA public key is stored in an RSAPublicKey structure, as defined by RFC 8017 - https://tools.ietf.org/html/rfc8017. For example: % xxd -p rsa-public-key.der 3082010a0282010100cf243c324b262470131648614b62ee9c52af43319c 2498a7c16ba9790bb3a881f960f7b0303f8f49e86fedd6813be5fa888393 55d04426df0050dbb771eb683773b7dd929949695093f910c8dcdb633674 de986ada8d643e0e819b7cd5ab3bde4372103797472dc843a2711699e21a 4afddeed9f62810316903457342c345a35ebb2f06da019fed2afa56e7856 6e75a0d712849ae255155d9304348318930611b3b4f1153d77ee5970f076 299c548c8afff53157205048ade26d40930af2ecc96d4f77e8591523b767 fa3cdbc45a8a210339c4a556cea2e0dfa3ee819b62e463f75d87a53c2fbd 1bbcb8ec8fe2e8000ce37235fa903113c7b37d9c2a8b39c54b0203010001 % % dumpasn1 -p -a rsa-public-key.der SEQUENCE { &#9;INTEGER &#9;&#9;00 CF 24 3C 32 4B 26 24 70 13 16 48 61 4B 62 EE &#9;&#9;9C 52 AF 43 31 9C 24 98 A7 C1 6B A9 79 0B B3 A8 &#9;&#9;81 F9 60 F7 B0 30 3F 8F 49 E8 6F ED D6 81 3B E5 &#9;&#9;FA 88 83 93 55 D0 44 26 DF 00 50 DB B7 71 EB 68 &#9;&#9;37 73 B7 DD 92 99 49 69 50 93 F9 10 C8 DC DB 63 &#9;&#9;36 74 DE 98 6A DA 8D 64 3E 0E 81 9B 7C D5 AB 3B &#9;&#9;DE 43 72 10 37 97 47 2D C8 43 A2 71 16 99 E2 1A &#9;&#9;4A FD DE ED 9F 62 81 03 16 90 34 57 34 2C 34 5A &#9;&#9;35 EB B2 F0 6D A0 19 FE D2 AF A5 6E 78 56 6E 75 &#9;&#9;A0 D7 12 84 9A E2 55 15 5D 93 04 34 83 18 93 06 &#9;&#9;11 B3 B4 F1 15 3D 77 EE 59 70 F0 76 29 9C 54 8C &#9;&#9;8A FF F5 31 57 20 50 48 AD E2 6D 40 93 0A F2 EC &#9;&#9;C9 6D 4F 77 E8 59 15 23 B7 67 FA 3C DB C4 5A 8A &#9;&#9;21 03 39 C4 A5 56 CE A2 E0 DF A3 EE 81 9B 62 E4 &#9;&#9;63 F7 5D 87 A5 3C 2F BD 1B BC B8 EC 8F E2 E8 00 &#9;&#9;0C E3 72 35 FA 90 31 13 C7 B3 7D 9C 2A 8B 39 C5 &#9;&#9;4B &#9;INTEGER 65537 &#9;} An RSA private key is stored in an RSAPrivateKey structure, defined by that same RFC - https://tools.ietf.org/html/rfc8017. For example: % xxd -p rsa-private-key.der 308204a30201000282010100cf243c324b262470131648614b62ee9c52af 43319c2498a7c16ba9790bb3a881f960f7b0303f8f49e86fedd6813be5fa 88839355d04426df0050dbb771eb683773b7dd929949695093f910c8dcdb 633674de986ada8d643e0e819b7cd5ab3bde4372103797472dc843a27116 99e21a4afddeed9f62810316903457342c345a35ebb2f06da019fed2afa5 6e78566e75a0d712849ae255155d9304348318930611b3b4f1153d77ee59 70f076299c548c8afff53157205048ade26d40930af2ecc96d4f77e85915 23b767fa3cdbc45a8a210339c4a556cea2e0dfa3ee819b62e463f75d87a5 3c2fbd1bbcb8ec8fe2e8000ce37235fa903113c7b37d9c2a8b39c54b0203 0100010282010044b694716a946089fd0aeb3fbb2e3a5108ecb2b186466d 8d58904a4ba92213c7e9ddcccc5974fc275c3fa4f9ff2ccb816c3f996462 0df9870827ca7af4034f32f5e40c505121151a71bbb161b041e68b6e0159 363901a63b1fbcc6c3866da3127bf51e84125ebe452c8a7a513102dc0dfc 61331a2826fbcb4452d88aaa0f43ccfe436e1554f95bdd883c41e7e8529f acd7556ba539af3e083e7143ddf8637f67b59eea494b02396ff5089a1964 48dc8f7eb236d2f92a3358d0d6f5af1443205400bbd2758d3ec7cb208c11 7d78d68409f987fd6e43a93a26961c10c05f85458821594d242f8106856c 393f3b971cae1bfc20319e37147b22d2d2179ed5844e8102818100f27c96 e84d6ff814c56996a0e143fa85106d74e2eaa848347d8681bbcc396d85fc b51d318f543ad25090fe087e0e1ee0202f2ee8674e58609c22cc56e305c5 c55b016d0ca45c847ac88b59dd8a597388b09d7d5f86e2cdf60cb7660d94 a5e4e6f539506a6aacdf67fb9458b016a63d72392129eff5faa210a1739d 948ef0453b02818100daaf65e651382baed753222ab53dfb2f79ef96c6bd ec1c2822e5b8405900cf9203b2a0e015d12042cc9e686bbf3e5d2d732ed7 45e2a1cc1787637b8f14727dd5da11261d3a7cbe3521296f269cdf2a16ea 2974a710b14f3e61484d2580fef9c5bf4965a7a9ee6055a8c27867609408 7ef1643e81ab17307ca40b79166b693f310281803ed463719ba6f87bc14f 039579e8d83fa42b084f478804f57cd4de469fbafd92eb10ae98c9cf8452 3c47e55aa3f6daaf2e07abbad211adba929a3da201bedc28afd4e5c191d0 db0ec969ba063a33c548d4a269fad7836ae467151a1f48b5d762b4857e3d a4985866a3fc2322b52babde2dc95709730dd6f2423327d0775cf0430281 8100c4f14336c99c6992bb2e8e4da20de0c21ff14a7b4f9d6cba24bb7754 d412ebdc96e1ef09fffbe72ee172239e2d8c2f83f8008e34cce663942904 c9c8d0644fb920fb62b4ddf06ba813666a487eec67ce5d31da717e920048 b079d9a855e4caf270d3dbedc416fec1060ba53d8c77a4b31617ee46fedb 127a9d8e0b8dca4bed710281800c2fe643bfc8c81b39f1a574c751d2c5ee 0ce836a772197350f2f0a6a4d5248790a0cdf0c25a69a8834d645ea3c96e e740d95adeea689259ac4ce36a7310c86c9c35441fdd96ff8cec89a65f8c 8666bbc2a42cd2a58e70b1e8b2269ed6307c5a2143cbd41de4682dea4a38 8a7c8d2f4088e9a2008fa986f9b0e92fa517ecc77b % % dumpasn1 -p -a rsa-private-key.der&#9;&#9;&#9; SEQUENCE { &#9;INTEGER 0 &#9;INTEGER &#9;&#9;00 CF 24 3C 32 4B 26 24 70 13 16 48 61 4B 62 EE &#9;&#9;9C 52 AF 43 31 9C 24 98 A7 C1 6B A9 79 0B B3 A8 &#9;&#9;81 F9 60 F7 B0 30 3F 8F 49 E8 6F ED D6 81 3B E5 &#9;&#9;FA 88 83 93 55 D0 44 26 DF 00 50 DB B7 71 EB 68 &#9;&#9;37 73 B7 DD 92 99 49 69 50 93 F9 10 C8 DC DB 63 &#9;&#9;36 74 DE 98 6A DA 8D 64 3E 0E 81 9B 7C D5 AB 3B &#9;&#9;DE 43 72 10 37 97 47 2D C8 43 A2 71 16 99 E2 1A &#9;&#9;4A FD DE ED 9F 62 81 03 16 90 34 57 34 2C 34 5A &#9;&#9;35 EB B2 F0 6D A0 19 FE D2 AF A5 6E 78 56 6E 75 &#9;&#9;A0 D7 12 84 9A E2 55 15 5D 93 04 34 83 18 93 06 &#9;&#9;11 B3 B4 F1 15 3D 77 EE 59 70 F0 76 29 9C 54 8C &#9;&#9;8A FF F5 31 57 20 50 48 AD E2 6D 40 93 0A F2 EC &#9;&#9;C9 6D 4F 77 E8 59 15 23 B7 67 FA 3C DB C4 5A 8A &#9;&#9;21 03 39 C4 A5 56 CE A2 E0 DF A3 EE 81 9B 62 E4 &#9;&#9;63 F7 5D 87 A5 3C 2F BD 1B BC B8 EC 8F E2 E8 00 &#9;&#9;0C E3 72 35 FA 90 31 13 C7 B3 7D 9C 2A 8B 39 C5 &#9;&#9;4B &#9;INTEGER 65537 &#9;INTEGER &#9;&#9;44 B6 94 71 6A 94 60 89 FD 0A EB 3F BB 2E 3A 51 &#9;&#9;08 EC B2 B1 86 46 6D 8D 58 90 4A 4B A9 22 13 C7 &#9;&#9;E9 DD CC CC 59 74 FC 27 5C 3F A4 F9 FF 2C CB 81 &#9;&#9;6C 3F 99 64 62 0D F9 87 08 27 CA 7A F4 03 4F 32 &#9;&#9;F5 E4 0C 50 51 21 15 1A 71 BB B1 61 B0 41 E6 8B &#9;&#9;6E 01 59 36 39 01 A6 3B 1F BC C6 C3 86 6D A3 12 &#9;&#9;7B F5 1E 84 12 5E BE 45 2C 8A 7A 51 31 02 DC 0D &#9;&#9;FC 61 33 1A 28 26 FB CB 44 52 D8 8A AA 0F 43 CC &#9;&#9;FE 43 6E 15 54 F9 5B DD 88 3C 41 E7 E8 52 9F AC &#9;&#9;D7 55 6B A5 39 AF 3E 08 3E 71 43 DD F8 63 7F 67 &#9;&#9;B5 9E EA 49 4B 02 39 6F F5 08 9A 19 64 48 DC 8F &#9;&#9;7E B2 36 D2 F9 2A 33 58 D0 D6 F5 AF 14 43 20 54 &#9;&#9;00 BB D2 75 8D 3E C7 CB 20 8C 11 7D 78 D6 84 09 &#9;&#9;F9 87 FD 6E 43 A9 3A 26 96 1C 10 C0 5F 85 45 88 &#9;&#9;21 59 4D 24 2F 81 06 85 6C 39 3F 3B 97 1C AE 1B &#9;&#9;FC 20 31 9E 37 14 7B 22 D2 D2 17 9E D5 84 4E 81 &#9;INTEGER &#9;&#9;00 F2 7C 96 E8 4D 6F F8 14 C5 69 96 A0 E1 43 FA &#9;&#9;85 10 6D 74 E2 EA A8 48 34 7D 86 81 BB CC 39 6D &#9;&#9;85 FC B5 1D 31 8F 54 3A D2 50 90 FE 08 7E 0E 1E &#9;&#9;E0 20 2F 2E E8 67 4E 58 60 9C 22 CC 56 E3 05 C5 &#9;&#9;C5 5B 01 6D 0C A4 5C 84 7A C8 8B 59 DD 8A 59 73 &#9;&#9;88 B0 9D 7D 5F 86 E2 CD F6 0C B7 66 0D 94 A5 E4 &#9;&#9;E6 F5 39 50 6A 6A AC DF 67 FB 94 58 B0 16 A6 3D &#9;&#9;72 39 21 29 EF F5 FA A2 10 A1 73 9D 94 8E F0 45 &#9;&#9;3B &#9;INTEGER &#9;&#9;00 DA AF 65 E6 51 38 2B AE D7 53 22 2A B5 3D FB &#9;&#9;2F 79 EF 96 C6 BD EC 1C 28 22 E5 B8 40 59 00 CF &#9;&#9;92 03 B2 A0 E0 15 D1 20 42 CC 9E 68 6B BF 3E 5D &#9;&#9;2D 73 2E D7 45 E2 A1 CC 17 87 63 7B 8F 14 72 7D &#9;&#9;D5 DA 11 26 1D 3A 7C BE 35 21 29 6F 26 9C DF 2A &#9;&#9;16 EA 29 74 A7 10 B1 4F 3E 61 48 4D 25 80 FE F9 &#9;&#9;C5 BF 49 65 A7 A9 EE 60 55 A8 C2 78 67 60 94 08 &#9;&#9;7E F1 64 3E 81 AB 17 30 7C A4 0B 79 16 6B 69 3F &#9;&#9;31 &#9;INTEGER &#9;&#9;3E D4 63 71 9B A6 F8 7B C1 4F 03 95 79 E8 D8 3F &#9;&#9;A4 2B 08 4F 47 88 04 F5 7C D4 DE 46 9F BA FD 92 &#9;&#9;EB 10 AE 98 C9 CF 84 52 3C 47 E5 5A A3 F6 DA AF &#9;&#9;2E 07 AB BA D2 11 AD BA 92 9A 3D A2 01 BE DC 28 &#9;&#9;AF D4 E5 C1 91 D0 DB 0E C9 69 BA 06 3A 33 C5 48 &#9;&#9;D4 A2 69 FA D7 83 6A E4 67 15 1A 1F 48 B5 D7 62 &#9;&#9;B4 85 7E 3D A4 98 58 66 A3 FC 23 22 B5 2B AB DE &#9;&#9;2D C9 57 09 73 0D D6 F2 42 33 27 D0 77 5C F0 43 &#9;INTEGER &#9;&#9;00 C4 F1 43 36 C9 9C 69 92 BB 2E 8E 4D A2 0D E0 &#9;&#9;C2 1F F1 4A 7B 4F 9D 6C BA 24 BB 77 54 D4 12 EB &#9;&#9;DC 96 E1 EF 09 FF FB E7 2E E1 72 23 9E 2D 8C 2F &#9;&#9;83 F8 00 8E 34 CC E6 63 94 29 04 C9 C8 D0 64 4F &#9;&#9;B9 20 FB 62 B4 DD F0 6B A8 13 66 6A 48 7E EC 67 &#9;&#9;CE 5D 31 DA 71 7E 92 00 48 B0 79 D9 A8 55 E4 CA &#9;&#9;F2 70 D3 DB ED C4 16 FE C1 06 0B A5 3D 8C 77 A4 &#9;&#9;B3 16 17 EE 46 FE DB 12 7A 9D 8E 0B 8D CA 4B ED &#9;&#9;71 &#9;INTEGER &#9;&#9;0C 2F E6 43 BF C8 C8 1B 39 F1 A5 74 C7 51 D2 C5 &#9;&#9;EE 0C E8 36 A7 72 19 73 50 F2 F0 A6 A4 D5 24 87 &#9;&#9;90 A0 CD F0 C2 5A 69 A8 83 4D 64 5E A3 C9 6E E7 &#9;&#9;40 D9 5A DE EA 68 92 59 AC 4C E3 6A 73 10 C8 6C &#9;&#9;9C 35 44 1F DD 96 FF 8C EC 89 A6 5F 8C 86 66 BB &#9;&#9;C2 A4 2C D2 A5 8E 70 B1 E8 B2 26 9E D6 30 7C 5A &#9;&#9;21 43 CB D4 1D E4 68 2D EA 4A 38 8A 7C 8D 2F 40 &#9;&#9;88 E9 A2 00 8F A9 86 F9 B0 E9 2F A5 17 EC C7 7B &#9;} Due to the way that these keys are encoded, the number of raw key bytes will vary from key to key. You should expect that, for a key whose size in bits is S: The public key will be a little over S / 8. The private key will be roughly S &#92;&#42; 0.6. These key formats are also known as PKCS#1. SECG Elliptic Curve Apple platforms support three SECG - https://en.wikipedia.org/wiki/SECG keys: secp256r1, aka NIST P-256, aka P256 - https://developer.apple.com/documentation/cryptokit/p256 secp384r1, aka NIST P-384, aka P384 - https://developer.apple.com/documentation/cryptokit/p384 secp521r1, aka NIST P-521, aka P521 - https://developer.apple.com/documentation/cryptokit/p521 Note that the latter is 521 not 512! These keys have of 4 components: A marker, which is always 0x04 X and Y values for the public key An additional K value for the private key These values are usually formatted according to ANSI X9.63. Specifically: The public key consists of 04 | X | Y. The private key consists of 04 | X | Y | K. Note In both case | indicates concatenation. X, Y and K are all the same size, being the key size in bits divided by 8 (rounded up in the case of secp521r1). So a secp256r1 public key is 65 bytes (1 for the marker plus 32 each for X and Y) and the matching private key is 97 bytes (an extra 32 bytes for K). For example: % xxd -p p256-public-key.dat 049747e981aab8ea71a255cd9a1562858c406006f1e418260d31e1a77f6c 2b35a9a3132f232db00351d9d8003487d4ee52847990313daa7c721f88d4 bb56da91c7 % % xxd -p p256-private-key.dat 049747e981aab8ea71a255cd9a1562858c406006f1e418260d31e1a77f6c 2b35a9a3132f232db00351d9d8003487d4ee52847990313daa7c721f88d4 bb56da91c7986a7a91cbb5f4f81636e81aaff0835a771dc66865c407a8e8 4469cf6ab8a477 Curve 25519 Curve 25519, defined RFC 7748 - https://tools.ietf.org/html/rfc7748, has the simplest raw key bytes format: Both the public and private key consist of 32 bytes of unstructured data. For example: % xxd -p curve25519-public-key.dat 910bf46f0c0dc836878fa70860fdde219d5f62650a83a7c5923d2ab74b81 76c5 % % xxd -p curve25519-private-key.dat 9fd90805255bae86a6c3035b2de837e929ea792ea11fd466e67ed0b265c0 a999
Asked
by eskimo.
Last updated
.
Post not yet marked as solved
246 Views

Importing Cryptographic Keys

I regularly see folks having problems importing cryptographic keys, so I thought I’d write down some hints and tips on how to recognise and import the various key formats. This post describes how to import each type of key. A companion post, On Cryptographic Keys Formats - https://developer.apple.com/forums/thread/680554, discusses how to recognise the format of the data you have. If you have questions about any of this stuff, please put them in a new thread, tagging it with Security or Apple CryptoKit. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Importing Cryptographic Keys Apple platforms support 5 different key types: RSA (Security framework only) SECG secp256r1, aka NIST P-256 (Security framework and Apple CryptoKit) SECG secp384r1, aka NIST P-384 (Security framework and Apple CryptoKit) SECG secp521r1, aka NIST P-521 (Security framework and Apple CryptoKit) Curve 25519 (Apple CryptoKit only) This post explains how to import each type of key. If you’re not sure what type of key you have, or how its encoded, or you run into weird problems and suspect that you might be using the wrong key type or encoding, read On Cryptographic Keys Formats - https://developer.apple.com/forums/thread/680554. Note This post focuses on APIs available on all Apple platforms. Some Mac-specific APIs can import other formats. The Security framework uses the SecKey - https://developer.apple.com/documentation/security/seckey type for all key types that it supports. Apple CryptoKit has a different approach: It uses different types for different key types, which helps catch common programming mistakes at compile time. There are 4 top-level enums: P256 - https://developer.apple.com/documentation/cryptokit/p256, for SECG secp256r1 P384 - https://developer.apple.com/documentation/cryptokit/p384, for SECG secp384r1 P521 - https://developer.apple.com/documentation/cryptokit/p521, for SECG secp521r1 Curve25519 - https://developer.apple.com/documentation/cryptokit/curve25519, for Curve 25519 Each of those enums contains a KeyAgreement enum and a Signing enum, where you express the intended purpose for your key. In this post I always use Signing but the code will work the same if you choose KeyAgreement. Finally, in each of those enums you’ll find both Public and Private types; these are structs that represent a specific public or private key. Undo PEM Encoding Writing a full-featured PEM parser is tricky. It is, however, relatively straightforward to undo the PEM encoding of a known simple PEM file. For example, if you have this file: % cat p256-private-key.pem ----BEGIN PRIVATE KEY MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgmGp6kcu19PgWNuga r/CDWncdxmhlxAeo6ERpz2q4pHehRANCAASXR+mBqrjqcaJVzZoVYoWMQGAG8eQY Jg0x4ad/bCs1qaMTLyMtsANR2dgANIfU7lKEeZAxPap8ch+I1LtW2pHH----END PRIVATE KEY Decode it like so: let u = URL(fileURLWithPath: "p256-private-key.pem") guard let pem = try? String(contentsOf: u) else { &#9;&#9;… handle error … } let pemBase64 = pem &#9;&#9;.split(separator: "\n") &#9;&#9;.dropFirst() &#9;&#9;.dropLast() &#9;&#9;.joined() guard let pemData = Data(base64Encoded: String(pemBase64)) else { &#9;&#9;… handle error … } debugPrint(pemData as NSData) // prints: // <30818702 01003013 06072a86 48ce3d02 0106082a 8648ce3d … d4bb56da 91c7> Import RSA Keys Use SecKeyCreateWithData to import an RSA key. If you have an RSAPublicKey structure like this: % xxd -p rsa-public-key.der 3082010a0282010100cf243c324b262470131648614b62ee9c52af43319c 2498a7c16ba9790bb3a881f960f7b0303f8f49e86fedd6813be5fa888393 55d04426df0050dbb771eb683773b7dd929949695093f910c8dcdb633674 de986ada8d643e0e819b7cd5ab3bde4372103797472dc843a2711699e21a 4afddeed9f62810316903457342c345a35ebb2f06da019fed2afa56e7856 6e75a0d712849ae255155d9304348318930611b3b4f1153d77ee5970f076 299c548c8afff53157205048ade26d40930af2ecc96d4f77e8591523b767 fa3cdbc45a8a210339c4a556cea2e0dfa3ee819b62e463f75d87a53c2fbd 1bbcb8ec8fe2e8000ce37235fa903113c7b37d9c2a8b39c54b0203010001 % % dumpasn1 -p -a rsa-public-key.der SEQUENCE { &#9;INTEGER &#9;&#9;00 CF 24 3C 32 4B 26 24 70 13 16 48 61 4B 62 EE &#9;&#9;9C 52 AF 43 31 9C 24 98 A7 C1 6B A9 79 0B B3 A8 &#9;&#9;81 F9 60 F7 B0 30 3F 8F 49 E8 6F ED D6 81 3B E5 &#9;&#9;FA 88 83 93 55 D0 44 26 DF 00 50 DB B7 71 EB 68 &#9;&#9;37 73 B7 DD 92 99 49 69 50 93 F9 10 C8 DC DB 63 &#9;&#9;36 74 DE 98 6A DA 8D 64 3E 0E 81 9B 7C D5 AB 3B &#9;&#9;DE 43 72 10 37 97 47 2D C8 43 A2 71 16 99 E2 1A &#9;&#9;4A FD DE ED 9F 62 81 03 16 90 34 57 34 2C 34 5A &#9;&#9;35 EB B2 F0 6D A0 19 FE D2 AF A5 6E 78 56 6E 75 &#9;&#9;A0 D7 12 84 9A E2 55 15 5D 93 04 34 83 18 93 06 &#9;&#9;11 B3 B4 F1 15 3D 77 EE 59 70 F0 76 29 9C 54 8C &#9;&#9;8A FF F5 31 57 20 50 48 AD E2 6D 40 93 0A F2 EC &#9;&#9;C9 6D 4F 77 E8 59 15 23 B7 67 FA 3C DB C4 5A 8A &#9;&#9;21 03 39 C4 A5 56 CE A2 E0 DF A3 EE 81 9B 62 E4 &#9;&#9;63 F7 5D 87 A5 3C 2F BD 1B BC B8 EC 8F E2 E8 00 &#9;&#9;0C E3 72 35 FA 90 31 13 C7 B3 7D 9C 2A 8B 39 C5 &#9;&#9;4B &#9;INTEGER 65537 &#9;} Import it with this code: let u = URL(fileURLWithPath: "rsa-public-key.der") guard let keyBytes = try? Data(contentsOf: u) else { &#9;&#9;… handle error … } guard let privateKey = SecKeyCreateWithData(keyBytes as NSData, [ &#9;&#9;kSecAttrKeyType: kSecAttrKeyTypeRSA, &#9;&#9;kSecAttrKeyClass: kSecAttrKeyClassPublic, ] as NSDictionary, nil) else { &#9;&#9;… handle error … } print(privateKey) // prints: // <SecKeyRef algorithm id: 1, key type: RSAPublicKey, version: 4, block size: 2048 bits, exponent: {hex: 10001, decimal: 65537}, modulus: …, addr: …> Note You don’t need to include any other attributes in the dictionary you pass to SecKeyCreateWithData. Specifically, many folks think that they need to pass in the kSecAttrKeySizeInBits attribute. This isn’t the case; SecKeyCreateWithData will work out the key size from the key data. If you have an RSAPrivateKey structure like this: % xxd -p rsa-private-key.der 308204a30201000282010100cf243c324b262470131648614b62ee9c52af 43319c2498a7c16ba9790bb3a881f960f7b0303f8f49e86fedd6813be5fa 88839355d04426df0050dbb771eb683773b7dd929949695093f910c8dcdb 633674de986ada8d643e0e819b7cd5ab3bde4372103797472dc843a27116 99e21a4afddeed9f62810316903457342c345a35ebb2f06da019fed2afa5 6e78566e75a0d712849ae255155d9304348318930611b3b4f1153d77ee59 70f076299c548c8afff53157205048ade26d40930af2ecc96d4f77e85915 23b767fa3cdbc45a8a210339c4a556cea2e0dfa3ee819b62e463f75d87a5 3c2fbd1bbcb8ec8fe2e8000ce37235fa903113c7b37d9c2a8b39c54b0203 0100010282010044b694716a946089fd0aeb3fbb2e3a5108ecb2b186466d 8d58904a4ba92213c7e9ddcccc5974fc275c3fa4f9ff2ccb816c3f996462 0df9870827ca7af4034f32f5e40c505121151a71bbb161b041e68b6e0159 363901a63b1fbcc6c3866da3127bf51e84125ebe452c8a7a513102dc0dfc 61331a2826fbcb4452d88aaa0f43ccfe436e1554f95bdd883c41e7e8529f acd7556ba539af3e083e7143ddf8637f67b59eea494b02396ff5089a1964 48dc8f7eb236d2f92a3358d0d6f5af1443205400bbd2758d3ec7cb208c11 7d78d68409f987fd6e43a93a26961c10c05f85458821594d242f8106856c 393f3b971cae1bfc20319e37147b22d2d2179ed5844e8102818100f27c96 e84d6ff814c56996a0e143fa85106d74e2eaa848347d8681bbcc396d85fc b51d318f543ad25090fe087e0e1ee0202f2ee8674e58609c22cc56e305c5 c55b016d0ca45c847ac88b59dd8a597388b09d7d5f86e2cdf60cb7660d94 a5e4e6f539506a6aacdf67fb9458b016a63d72392129eff5faa210a1739d 948ef0453b02818100daaf65e651382baed753222ab53dfb2f79ef96c6bd ec1c2822e5b8405900cf9203b2a0e015d12042cc9e686bbf3e5d2d732ed7 45e2a1cc1787637b8f14727dd5da11261d3a7cbe3521296f269cdf2a16ea 2974a710b14f3e61484d2580fef9c5bf4965a7a9ee6055a8c27867609408 7ef1643e81ab17307ca40b79166b693f310281803ed463719ba6f87bc14f 039579e8d83fa42b084f478804f57cd4de469fbafd92eb10ae98c9cf8452 3c47e55aa3f6daaf2e07abbad211adba929a3da201bedc28afd4e5c191d0 db0ec969ba063a33c548d4a269fad7836ae467151a1f48b5d762b4857e3d a4985866a3fc2322b52babde2dc95709730dd6f2423327d0775cf0430281 8100c4f14336c99c6992bb2e8e4da20de0c21ff14a7b4f9d6cba24bb7754 d412ebdc96e1ef09fffbe72ee172239e2d8c2f83f8008e34cce663942904 c9c8d0644fb920fb62b4ddf06ba813666a487eec67ce5d31da717e920048 b079d9a855e4caf270d3dbedc416fec1060ba53d8c77a4b31617ee46fedb 127a9d8e0b8dca4bed710281800c2fe643bfc8c81b39f1a574c751d2c5ee 0ce836a772197350f2f0a6a4d5248790a0cdf0c25a69a8834d645ea3c96e e740d95adeea689259ac4ce36a7310c86c9c35441fdd96ff8cec89a65f8c 8666bbc2a42cd2a58e70b1e8b2269ed6307c5a2143cbd41de4682dea4a38 8a7c8d2f4088e9a2008fa986f9b0e92fa517ecc77b % % dumpasn1 -p -a rsa-private-key.der SEQUENCE { &#9;INTEGER 0 &#9;INTEGER &#9;&#9;00 CF 24 3C 32 4B 26 24 70 13 16 48 61 4B 62 EE &#9;&#9;9C 52 AF 43 31 9C 24 98 A7 C1 6B A9 79 0B B3 A8 &#9;&#9;81 F9 60 F7 B0 30 3F 8F 49 E8 6F ED D6 81 3B E5 &#9;&#9;FA 88 83 93 55 D0 44 26 DF 00 50 DB B7 71 EB 68 &#9;&#9;37 73 B7 DD 92 99 49 69 50 93 F9 10 C8 DC DB 63 &#9;&#9;36 74 DE 98 6A DA 8D 64 3E 0E 81 9B 7C D5 AB 3B &#9;&#9;DE 43 72 10 37 97 47 2D C8 43 A2 71 16 99 E2 1A &#9;&#9;4A FD DE ED 9F 62 81 03 16 90 34 57 34 2C 34 5A &#9;&#9;35 EB B2 F0 6D A0 19 FE D2 AF A5 6E 78 56 6E 75 &#9;&#9;A0 D7 12 84 9A E2 55 15 5D 93 04 34 83 18 93 06 &#9;&#9;11 B3 B4 F1 15 3D 77 EE 59 70 F0 76 29 9C 54 8C &#9;&#9;8A FF F5 31 57 20 50 48 AD E2 6D 40 93 0A F2 EC &#9;&#9;C9 6D 4F 77 E8 59 15 23 B7 67 FA 3C DB C4 5A 8A &#9;&#9;21 03 39 C4 A5 56 CE A2 E0 DF A3 EE 81 9B 62 E4 &#9;&#9;63 F7 5D 87 A5 3C 2F BD 1B BC B8 EC 8F E2 E8 00 &#9;&#9;0C E3 72 35 FA 90 31 13 C7 B3 7D 9C 2A 8B 39 C5 &#9;&#9;4B &#9;INTEGER 65537 &#9;INTEGER &#9;&#9;44 B6 94 71 6A 94 60 89 FD 0A EB 3F BB 2E 3A 51 &#9;&#9;08 EC B2 B1 86 46 6D 8D 58 90 4A 4B A9 22 13 C7 &#9;&#9;E9 DD CC CC 59 74 FC 27 5C 3F A4 F9 FF 2C CB 81 &#9;&#9;6C 3F 99 64 62 0D F9 87 08 27 CA 7A F4 03 4F 32 &#9;&#9;F5 E4 0C 50 51 21 15 1A 71 BB B1 61 B0 41 E6 8B &#9;&#9;6E 01 59 36 39 01 A6 3B 1F BC C6 C3 86 6D A3 12 &#9;&#9;7B F5 1E 84 12 5E BE 45 2C 8A 7A 51 31 02 DC 0D &#9;&#9;FC 61 33 1A 28 26 FB CB 44 52 D8 8A AA 0F 43 CC &#9;&#9;FE 43 6E 15 54 F9 5B DD 88 3C 41 E7 E8 52 9F AC &#9;&#9;D7 55 6B A5 39 AF 3E 08 3E 71 43 DD F8 63 7F 67 &#9;&#9;B5 9E EA 49 4B 02 39 6F F5 08 9A 19 64 48 DC 8F &#9;&#9;7E B2 36 D2 F9 2A 33 58 D0 D6 F5 AF 14 43 20 54 &#9;&#9;00 BB D2 75 8D 3E C7 CB 20 8C 11 7D 78 D6 84 09 &#9;&#9;F9 87 FD 6E 43 A9 3A 26 96 1C 10 C0 5F 85 45 88 &#9;&#9;21 59 4D 24 2F 81 06 85 6C 39 3F 3B 97 1C AE 1B &#9;&#9;FC 20 31 9E 37 14 7B 22 D2 D2 17 9E D5 84 4E 81 &#9;INTEGER &#9;&#9;00 F2 7C 96 E8 4D 6F F8 14 C5 69 96 A0 E1 43 FA &#9;&#9;85 10 6D 74 E2 EA A8 48 34 7D 86 81 BB CC 39 6D &#9;&#9;85 FC B5 1D 31 8F 54 3A D2 50 90 FE 08 7E 0E 1E &#9;&#9;E0 20 2F 2E E8 67 4E 58 60 9C 22 CC 56 E3 05 C5 &#9;&#9;C5 5B 01 6D 0C A4 5C 84 7A C8 8B 59 DD 8A 59 73 &#9;&#9;88 B0 9D 7D 5F 86 E2 CD F6 0C B7 66 0D 94 A5 E4 &#9;&#9;E6 F5 39 50 6A 6A AC DF 67 FB 94 58 B0 16 A6 3D &#9;&#9;72 39 21 29 EF F5 FA A2 10 A1 73 9D 94 8E F0 45 &#9;&#9;3B &#9;INTEGER &#9;&#9;00 DA AF 65 E6 51 38 2B AE D7 53 22 2A B5 3D FB &#9;&#9;2F 79 EF 96 C6 BD EC 1C 28 22 E5 B8 40 59 00 CF &#9;&#9;92 03 B2 A0 E0 15 D1 20 42 CC 9E 68 6B BF 3E 5D &#9;&#9;2D 73 2E D7 45 E2 A1 CC 17 87 63 7B 8F 14 72 7D &#9;&#9;D5 DA 11 26 1D 3A 7C BE 35 21 29 6F 26 9C DF 2A &#9;&#9;16 EA 29 74 A7 10 B1 4F 3E 61 48 4D 25 80 FE F9 &#9;&#9;C5 BF 49 65 A7 A9 EE 60 55 A8 C2 78 67 60 94 08 &#9;&#9;7E F1 64 3E 81 AB 17 30 7C A4 0B 79 16 6B 69 3F &#9;&#9;31 &#9;INTEGER &#9;&#9;3E D4 63 71 9B A6 F8 7B C1 4F 03 95 79 E8 D8 3F &#9;&#9;A4 2B 08 4F 47 88 04 F5 7C D4 DE 46 9F BA FD 92 &#9;&#9;EB 10 AE 98 C9 CF 84 52 3C 47 E5 5A A3 F6 DA AF &#9;&#9;2E 07 AB BA D2 11 AD BA 92 9A 3D A2 01 BE DC 28 &#9;&#9;AF D4 E5 C1 91 D0 DB 0E C9 69 BA 06 3A 33 C5 48 &#9;&#9;D4 A2 69 FA D7 83 6A E4 67 15 1A 1F 48 B5 D7 62 &#9;&#9;B4 85 7E 3D A4 98 58 66 A3 FC 23 22 B5 2B AB DE &#9;&#9;2D C9 57 09 73 0D D6 F2 42 33 27 D0 77 5C F0 43 &#9;INTEGER &#9;&#9;00 C4 F1 43 36 C9 9C 69 92 BB 2E 8E 4D A2 0D E0 &#9;&#9;C2 1F F1 4A 7B 4F 9D 6C BA 24 BB 77 54 D4 12 EB &#9;&#9;DC 96 E1 EF 09 FF FB E7 2E E1 72 23 9E 2D 8C 2F &#9;&#9;83 F8 00 8E 34 CC E6 63 94 29 04 C9 C8 D0 64 4F &#9;&#9;B9 20 FB 62 B4 DD F0 6B A8 13 66 6A 48 7E EC 67 &#9;&#9;CE 5D 31 DA 71 7E 92 00 48 B0 79 D9 A8 55 E4 CA &#9;&#9;F2 70 D3 DB ED C4 16 FE C1 06 0B A5 3D 8C 77 A4 &#9;&#9;B3 16 17 EE 46 FE DB 12 7A 9D 8E 0B 8D CA 4B ED &#9;&#9;71 &#9;INTEGER &#9;&#9;0C 2F E6 43 BF C8 C8 1B 39 F1 A5 74 C7 51 D2 C5 &#9;&#9;EE 0C E8 36 A7 72 19 73 50 F2 F0 A6 A4 D5 24 87 &#9;&#9;90 A0 CD F0 C2 5A 69 A8 83 4D 64 5E A3 C9 6E E7 &#9;&#9;40 D9 5A DE EA 68 92 59 AC 4C E3 6A 73 10 C8 6C &#9;&#9;9C 35 44 1F DD 96 FF 8C EC 89 A6 5F 8C 86 66 BB &#9;&#9;C2 A4 2C D2 A5 8E 70 B1 E8 B2 26 9E D6 30 7C 5A &#9;&#9;21 43 CB D4 1D E4 68 2D EA 4A 38 8A 7C 8D 2F 40 &#9;&#9;88 E9 A2 00 8F A9 86 F9 B0 E9 2F A5 17 EC C7 7B &#9;} Import it with this code: let u = URL(fileURLWithPath: "rsa-private-key.der") guard let keyBytes = try? Data(contentsOf: u) else { &#9;&#9;… handle error … } guard let privateKey = SecKeyCreateWithData(keyBytes as NSData, [ &#9;&#9;kSecAttrKeyType: kSecAttrKeyTypeRSA, &#9;&#9;kSecAttrKeyClass: kSecAttrKeyClassPrivate, ] as NSDictionary, nil) else { &#9;&#9;… handle error … } print(privateKey) // prints: // <SecKeyRef algorithm id: 1, key type: RSAPrivateKey, version: 4, block size: 2048 bits, addr: …> Finally, an oft-forgotten feature of SecKeyCreateWithData is that it can undo a SubjectPublicKeyInfo wrapper. So, if you have an RSA public key wrapped in a SubjectPublicKeyInfo like this: % xxd -p public-key-rsa.der 30820122300d06092a864886f70d01010105000382010f003082010a0282 010100bce736006d9b0a2a49508f32e8d66f2b26236263a476f5a2eaf6af 34f0055b12b3bea5f5a62f3aab82274c3e3b21d15cc741100c670dd7687d 9c7e5c012d95bf5177993087df441c9944d10dff0767abfd6e412df279e4 e518b905e5582f967b6b2a64eeaeef712c594268fbff9cc2e63833ebffb7 f00c61fd7224ae2328047e13bbb904899e9ad5c9f44cfff5cd9a2df5a5b6 29bec605d6ecdce5dacba40cb119695f7c3dbd19e6fcd86a13700dfe6818 d1894aca9172a1e857540641971f7d7c9533aee2047c16c1c4f125e830b2 7d5e80d445c2fe09fa5586ee0bb105800fd1e8489e44b2f123eeef1cceeb eb1ba2d094923944181c513208c1f37fca31e50203010001 % % dumpasn1 -p -a public-key-rsa.der SEQUENCE { &#9;SEQUENCE { &#9;&#9;OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1) &#9;&#9;NULL &#9;&#9;} &#9;BIT STRING, encapsulates { &#9;&#9;SEQUENCE { &#9;&#9;&#9;INTEGER &#9;&#9;&#9;&#9;00 BC E7 36 00 6D 9B 0A 2A 49 50 8F 32 E8 D6 6F &#9;&#9;&#9;&#9;2B 26 23 62 63 A4 76 F5 A2 EA F6 AF 34 F0 05 5B &#9;&#9;&#9;&#9;12 B3 BE A5 F5 A6 2F 3A AB 82 27 4C 3E 3B 21 D1 &#9;&#9;&#9;&#9;5C C7 41 10 0C 67 0D D7 68 7D 9C 7E 5C 01 2D 95 &#9;&#9;&#9;&#9;BF 51 77 99 30 87 DF 44 1C 99 44 D1 0D FF 07 67 &#9;&#9;&#9;&#9;AB FD 6E 41 2D F2 79 E4 E5 18 B9 05 E5 58 2F 96 &#9;&#9;&#9;&#9;7B 6B 2A 64 EE AE EF 71 2C 59 42 68 FB FF 9C C2 &#9;&#9;&#9;&#9;E6 38 33 EB FF B7 F0 0C 61 FD 72 24 AE 23 28 04 &#9;&#9;&#9;&#9;7E 13 BB B9 04 89 9E 9A D5 C9 F4 4C FF F5 CD 9A &#9;&#9;&#9;&#9;2D F5 A5 B6 29 BE C6 05 D6 EC DC E5 DA CB A4 0C &#9;&#9;&#9;&#9;B1 19 69 5F 7C 3D BD 19 E6 FC D8 6A 13 70 0D FE &#9;&#9;&#9;&#9;68 18 D1 89 4A CA 91 72 A1 E8 57 54 06 41 97 1F &#9;&#9;&#9;&#9;7D 7C 95 33 AE E2 04 7C 16 C1 C4 F1 25 E8 30 B2 &#9;&#9;&#9;&#9;7D 5E 80 D4 45 C2 FE 09 FA 55 86 EE 0B B1 05 80 &#9;&#9;&#9;&#9;0F D1 E8 48 9E 44 B2 F1 23 EE EF 1C CE EB EB 1B &#9;&#9;&#9;&#9;A2 D0 94 92 39 44 18 1C 51 32 08 C1 F3 7F CA 31 &#9;&#9;&#9;&#9;E5 &#9;&#9;&#9;INTEGER 65537 &#9;&#9;&#9;} &#9;&#9;} &#9;} Import it with this code: let u = URL(fileURLWithPath: "public-key-rsa.der") guard let keyBytes = try? Data(contentsOf: u) else { &#9;&#9;… handle error … } guard let privateKey = SecKeyCreateWithData(keyBytes as NSData, [ &#9;&#9;kSecAttrKeyType: kSecAttrKeyTypeRSA, &#9;&#9;kSecAttrKeyClass: kSecAttrKeyClassPublic, ] as NSDictionary, nil) else { &#9;&#9;… handle error … } print(privateKey) // prints: // <SecKeyRef algorithm id: 1, key type: RSAPublicKey, version: 4, block size: 2048 bits, exponent: {hex: 10001, decimal: 65537}, modulus: …, addr: …> Import SECG Keys with Security Framework If you’re working with Security framework, use SecKeyCreateWithData to import an SECG key. If you have a secp256r1 public key in X9.63 format: % xxd p256-public-key.dat 00000000: 0497 47e9 81aa b8ea 71a2 55cd 9a15 6285&#9;..G.....q.U...b. 00000010: 8c40 6006 f1e4 1826 0d31 e1a7 7f6c 2b35&#9;.@`....&.1...l+5 00000020: a9a3 132f 232d b003 51d9 d800 3487 d4ee&#9;.../#-..Q...4... 00000030: 5284 7990 313d aa7c 721f 88d4 bb56 da91&#9;R.y.1=.|r....V.. 00000040: c7&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; . Import it with this code: let u = URL(fileURLWithPath: "p256-public-key.dat") guard let keyBytes = try? Data(contentsOf: u) else { &#9;&#9;… handle error … } guard let privateKey = SecKeyCreateWithData(keyBytes as NSData, [ &#9;&#9;kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom, &#9;&#9;kSecAttrKeyClass: kSecAttrKeyClassPublic, ] as NSDictionary, nil) else { &#9;&#9;… handle error … } print(privateKey) // prints: // <SecKeyRef curve type: kSecECCurveSecp256r1, algorithm id: 3, key type: ECPublicKey, version: 4, block size: 256 bits, y: …, x: …, addr: …> Note I’m using secp256r1 as an example. The code in this section will work for the other SECG key types, secp384r1 and secp521r1. And if you have a secp256r1 private key in X9.63 format: % xxd p256-private-key.dat 00000000: 0497 47e9 81aa b8ea 71a2 55cd 9a15 6285&#9;..G.....q.U...b. 00000010: 8c40 6006 f1e4 1826 0d31 e1a7 7f6c 2b35&#9;.@`....&.1...l+5 00000020: a9a3 132f 232d b003 51d9 d800 3487 d4ee&#9;.../#-..Q...4... 00000030: 5284 7990 313d aa7c 721f 88d4 bb56 da91&#9;R.y.1=.|r....V.. 00000040: c798 6a7a 91cb b5f4 f816 36e8 1aaf f083&#9;..jz......6..... 00000050: 5a77 1dc6 6865 c407 a8e8 4469 cf6a b8a4&#9;Zw..he....Di.j.. 00000060: 77&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; w Import it with this code: let u = URL(fileURLWithPath: "p256-private-key.dat") guard let keyBytes = try? Data(contentsOf: u) else { &#9;&#9;… handle error … } guard let privateKey = SecKeyCreateWithData(keyBytes as NSData, [ &#9;&#9;kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom, &#9;&#9;kSecAttrKeyClass: kSecAttrKeyClassPrivate, ] as NSDictionary, nil) else { &#9;&#9;… handle error … } print(privateKey) // prints: // <SecKeyRef curve type: kSecECCurveSecp256r1, algorithm id: 3, key type: ECPrivateKey, version: 4, block size: 256 bits, addr: …> Import SECG Keys with Apple CryptoKit Apple CryptoKit can import SECG keys in three different ways: X9.63 raw key bytes DER encoding PEM encoding If you have a secp256r1 public key in X9.63 format, import it with this code: let u = URL(fileURLWithPath: "p256-public-key.dat") guard let keyBytes = try? Data(contentsOf: u) else { &#9;&#9;… handle error … } guard let publicKey = try? P256.Signing.PublicKey(x963Representation: keyBytes) else { &#9;&#9;… handle error … } print(publicKey) // prints: // PublicKey(impl: CryptoKit.CoreCryptoNISTCurvePublicKeyImpl<CryptoKit.P256.CurveDetails>(keyBytes: […]])) Note I’m using secp256r1 as an example. The code in this section will work for the other SECG key types, secp384r1 and secp521r1. If you have a secp256r1 private key in X9.63 format import it with this code: let u = URL(fileURLWithPath: "p256-private-key.dat") guard let keyBytes = try? Data(contentsOf: u) else { &#9;&#9;… handle error … } guard let privateKey = try? P256.Signing.PrivateKey(x963Representation: keyBytes) else { &#9;&#9;… handle error … } print(privateKey) // prints: // PrivateKey(impl: CryptoKit.CoreCryptoNISTCurvePrivateKeyImpl<CryptoKit.P256.CurveDetails>(key: CryptoKit.SecureBytes(backing: CryptoKit.SecureBytes.Backing))) CryptoKit can also import a DER-encoded SECG key. For example, it can import the following using the init(derRepresentation:) initialiser: % xxd -p public-key-p256.der 3059301306072a8648ce3d020106082a8648ce3d030107034200042c21f3 7049d4464afbf01813c51a4e1ef7a8101d2aa12b6a889635bc7c37e9011b fdd54006fdebdaef0d86a6d662561347982c95276013d1c1cd2d7865aff0 23 % % dumpasn1 -p -a public-key-p256.der SEQUENCE { &#9;SEQUENCE { &#9;&#9;OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) &#9;&#9;OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) &#9;&#9;} &#9;BIT STRING &#9;&#9;04 2C 21 F3 70 49 D4 46 4A FB F0 18 13 C5 1A 4E &#9;&#9;1E F7 A8 10 1D 2A A1 2B 6A 88 96 35 BC 7C 37 E9 &#9;&#9;01 1B FD D5 40 06 FD EB DA EF 0D 86 A6 D6 62 56 &#9;&#9;13 47 98 2C 95 27 60 13 D1 C1 CD 2D 78 65 AF F0 &#9;&#9;23 &#9;} % % xxd -p private-key-p256.der 308187020100301306072a8648ce3d020106082a8648ce3d030107046d30 6b0201010420986a7a91cbb5f4f81636e81aaff0835a771dc66865c407a8 e84469cf6ab8a477a144034200049747e981aab8ea71a255cd9a1562858c 406006f1e418260d31e1a77f6c2b35a9a3132f232db00351d9d8003487d4 ee52847990313daa7c721f88d4bb56da91c7 % % dumpasn1 -p -a private-key-p256.der SEQUENCE { &#9;INTEGER 0 &#9;SEQUENCE { &#9;&#9;OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) &#9;&#9;OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) &#9;&#9;} &#9;OCTET STRING, encapsulates { &#9;&#9;SEQUENCE { &#9;&#9;&#9;INTEGER 1 &#9;&#9;&#9;OCTET STRING &#9;&#9;&#9;&#9;98 6A 7A 91 CB B5 F4 F8 16 36 E8 1A AF F0 83 5A &#9;&#9;&#9;&#9;77 1D C6 68 65 C4 07 A8 E8 44 69 CF 6A B8 A4 77 &#9;&#9;&#9;[1] { &#9;&#9;&#9;&#9;BIT STRING &#9;&#9;&#9;&#9;&#9;04 97 47 E9 81 AA B8 EA 71 A2 55 CD 9A 15 62 85 &#9;&#9;&#9;&#9;&#9;8C 40 60 06 F1 E4 18 26 0D 31 E1 A7 7F 6C 2B 35 &#9;&#9;&#9;&#9;&#9;A9 A3 13 2F 23 2D B0 03 51 D9 D8 00 34 87 D4 EE &#9;&#9;&#9;&#9;&#9;52 84 79 90 31 3D AA 7C 72 1F 88 D4 BB 56 DA 91 &#9;&#9;&#9;&#9;&#9;C7 &#9;&#9;&#9;&#9;} &#9;&#9;&#9;} &#9;&#9;} &#9;} Finally, CryptoKit can import a PEM-encoded SECG. For example, it can import the following using the init(pemRepresentation:) initialiser: % cat public-key-p256.pem----BEGIN PUBLIC KEY MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELCHzcEnURkr78BgTxRpOHveoEB0q oStqiJY1vHw36QEb/dVABv3r2u8NhqbWYlYTR5gslSdgE9HBzS14Za/wIw==----END PUBLIC KEY % cat private-key-p256.pem----BEGIN PRIVATE KEY MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgmGp6kcu19PgWNuga r/CDWncdxmhlxAeo6ERpz2q4pHehRANCAASXR+mBqrjqcaJVzZoVYoWMQGAG8eQY Jg0x4ad/bCs1qaMTLyMtsANR2dgANIfU7lKEeZAxPap8ch+I1LtW2pHH----END PRIVATE KEY Mapping SECG Keys between Apple CryptoKit and Security Framework If you need to map an SECG key from Apple CryptoKit to Security framework, or vice versa, use the X9.63 format. Imagine that you’re working in Security framework but you need to import a PEM key. SecKeyCreateWithData will not accept an SECG key in PEM format; it requires that the key be in X9.63 format. CryptoKit can import a PEM key but you want to continue using your existing Security framework code. Fortunately there’s a way out of this bind: Import the PEM key using Apple CryptoKit. Get the X9.63 representation. Create the Security framework key from that. For example, the following routine imports a PEM secp256r1 private key and returns a SecKey object: func createSecKeyWithPEMSecp256r1Private(_ pem: String) throws -> SecKey { &#9;&#9;let privateKeyCK = try P256.Signing.PrivateKey(pemRepresentation: pem) &#9;&#9;let x963Data = privateKeyCK.x963Representation &#9;&#9;var errorQ: Unmanaged<CFError>? = nil &#9;&#9;guard let privateKeySF = SecKeyCreateWithData(x963Data as NSData, [ &#9;&#9;&#9;&#9;kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom, &#9;&#9;&#9;&#9;kSecAttrKeyClass: kSecAttrKeyClassPrivate, &#9;&#9;] as NSDictionary, &errorQ) else { &#9;&#9;&#9;&#9;throw errorQ!.takeRetainedValue() &#9;&#9;} &#9;&#9;return privateKeySF } To go the other way, from Security framework to CryptoKit, call SecKeyCopyExternalRepresentation to get the X9.63 representation of the key and then create a CryptoKit value using the init(x963Representation:) initialiser. Importing Curve 25519 Keys Apple CryptoKit supports Curve 25519 keys. If you have the raw bytes of a Curve 25519 public key: % xxd curve25519-public-key.dat 00000000: 910b f46f 0c0d c836 878f a708 60fd de21&#9;...o...6....`..! 00000010: 9d5f 6265 0a83 a7c5 923d 2ab7 4b81 76c5&#9;._be.....=*.K.v. Import it with this code: let u = URL(fileURLWithPath: "curve25519-public-key.dat") guard let keyBytes = try? Data(contentsOf: u) else { &#9;&#9;… handle error … } guard let publicKey = try? Curve25519.Signing.PublicKey(rawRepresentation: keyBytes) else { &#9;&#9;… handle error … } print(publicKey) // prints: // PublicKey(baseKey: CryptoKit.Curve25519.Signing.CoreCryptoCurve25519PublicKeyImpl(keyBytes: […])) If you have the raw bytes of a Curve 25519 private key: % xxd curve25519-private-key.dat 00000000: 9fd9 0805 255b ae86 a6c3 035b 2de8 37e9&#9;....%[.....[-.7. 00000010: 29ea 792e a11f d466 e67e d0b2 65c0 a999&#9;).y....f.~..e... Import it with this code: let u = URL(fileURLWithPath: "curve25519-private-key.dat") guard let keyBytes = try? Data(contentsOf: u) else { &#9;&#9;… handle error … } guard let privateKey = try? Curve25519.Signing.PrivateKey(rawRepresentation: keyBytes) else { &#9;&#9;… handle error … } print(privateKey) // prints: // PrivateKey(baseKey: CryptoKit.Curve25519.Signing.CoreCryptoCurve25519PrivateKeyImpl(key: CryptoKit.SecureBytes(backing: CryptoKit.SecureBytes.Backing)))
Asked
by eskimo.
Last updated
.
Post marked as solved
165 Views

Error -50 when attempting to store a SymmetricKey in Keychain

Hi all, I've been working on implementing CryptoKit in my app, and I seem to have run into a wall where I can't get the generated SymmetricKey to be stored in the keychain. Here is the code I've written: swift static func makeAndStoreKey(name: String) throws - SymmetricKey? { let nameData = name.data(using: .utf8) let symmetricKey = SymmetricKey(size: .bits256) let query = [kSecClass: kSecClassGenericPassword, kSecAttrApplicationTag: nameData!, kSecValueRef: symmetricKey.rawRepresentation] as [String: Any] let status = SecItemAdd(query as CFDictionary, nil) guard status == errSecSuccess else { throw KeyStoreError("Unable to store item: \(status.message)") } return symmetricKey } static func loadKey(name: String) throws - SymmetricKey? { let nameData = name.data(using: .utf8) let query = [kSecClass: kSecClassGenericPassword, kSecAttrApplicationTag: nameData!, kSecReturnRef: true] as [String: Any] var item: CFTypeRef? switch SecItemCopyMatching(query as CFDictionary, &amp;amp;amp;item) { case errSecSuccess: guard let data = item as? Data else { return nil } return SymmetricKey(data: data) case errSecItemNotFound: return nil case let status: throw KeyStoreError("Keychain read failed: \(status.message)") } } I was also attempting to add the following attributes to the keychain query (but commented them out because I was attempting to troubleshoot this issue) swift kSecAttrIsPermanent: true, kSecAttrCanEncrypt: true, kSecAttrCanDecrypt: true, kSecAttrAccessible: kSecAttrAccessibleWhenUnlocked, kSecUseDataProtectionKeychain: true, kSecAttrIsInvisible: true, I've tried storing the key as both a a kSecClassGenericPassword and a kSecClassKey, and it returns the same -50 ("One or more parameters passed to a function were not valid.") error. I've tried storing the key as both Data and the SymmetricKey iteself, and I have tried storing the ApplicationTag as both a String and as Data. Neither of these resolve the issue. I'm hoping someone has some ideas on what I'm missing here. I've been following the instructions listed here: https://developer.apple.com/documentation/cryptokit/storing_cryptokit_keys_in_the_keychain Here is my code to convert to a rawRepresentation (the code supplied in the CryptoKit Keys in the Keychain article didn't compile unfortunately). swift import Foundation import CryptoKit extension SymmetricKey: GenericPasswordConvertible { public var description: String { return "" } initD(rawRepresentation data: D) throws where D: ContiguousBytes { self.init(data: data) } var rawRepresentation: Data { var intArr = [UInt8]() self.withUnsafeBytes { ptr in intArr.append(contentsOf: ptr) } return Data(intArr) } } Thanks in advance for the help.
Asked Last updated
.
Post marked as solved
233 Views

Cryptokit - How to get PEM representation of Curve25519 Public Key

Hi, How do I generate the pem representation of a curve25519 public key? I can generate the key using :      let privateKey = Curve25519.KeyAgreement.PrivateKey() let publicKey = privateKey.publicKey print(publicKey.rawRepresentation.base64EncodedString()) This prints a string like this : GyQfzi3bLfpDpzi8e9j6lovX15EZY1t1fQQcnJlURxI= But the expected strings are more like : ----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEApxUNh3jHlNSAWE7fadipsh9AjXv6439VY3EWEC5kbgY=\n-----END PUBLIC KEY Even if I add the " -----BEGIN PUBLIC KEY-----" and "-----END PUBLIC KEY-----" tags, it still doesn't process the key. So what format is exactly the base64 encoded string of the raw format of curve25519 public key? And how do I generate the public key pem format? The requirement is for Swift iOS.
Asked Last updated
.
Post marked as solved
114 Views

Can CryptoKit encrypt or decrypt streams?

I have a continuous data stream encrypted by aesgcm, I did not find a way to decrypt it using CryptoKit unless I have the full data. My question is Can CryptoKit decrypt or encrypt a stream without a complete read? Like EVP_***_Update in OpenSSL. Thank you.
Asked
by HenryL.
Last updated
.
Post marked as solved
363 Views

CryptoKit - generate Curve25519 public key from a long base 64 string given from server

Hi, I'm using Curve25519 to generate the public-private key pair that's to be used for creating the shared Secret. The public key received from the server is but a very long message(base64 encoded string), which is about 309 bytes when converted to Data. When I try to create the shared secret key using this data, CryptoKit throws the error "CryptoKit.CryptoKitError.incorrectKeySize" at this line: swift      let serverPublicKey = try! Curve25519.KeyAgreement.PublicKey(rawRepresentation: serverPublicKeyData) I need the output of this line(serverPublicKey) for generating the shared secret. Here's the rest of the code: swift      let clientPrivateKey = Curve25519.KeyAgreement.PrivateKey()      let clientSharedSecret = try! clientPrivateKey.sharedSecretFromKeyAgreement(with: serverPublicKey)      let clientSharedSecretyKey = clientSharedSecret.x963DerivedSymmetricKey(using: SHA256.self, sharedInfo: Data(), outputByteCount: 32) and I'm encrypting using AES.GCM swift      let clientSealedBoxData = try! AES.GCM.seal(messageData, using: clientSharedSecretyKey).combined!      let clientSealedBox = try! AES.GCM.SealedBox(combined: clientSealedBoxData) where messageData is the data to be encrypted Is there any way to compress the received public key to 32 bytes to pass it to the KeyAgreement line? (Also, is this the right method to generate the public key for encrypting?) I've referred a lot of sites but couldn't arrive at a solution. Please help.
Asked Last updated
.
Post not yet marked as solved
268 Views

Curve25519 String representation

Hi. I've been trying to make an ed25519 key pair from already existing keys, which has been giving me significant issues. I made an ed25519 key pair through OpenSSH (the keygen command), and attempted to input the private and public keys into the Curve25519 object. They keep giving me back CryptoKit Error 1, which has no further description. So I also tried to generate keys with Curve25519, but I cannot make a string representation of them. I always get 'nil' back trying to utf8 encode them into Strings from Data, but I can base64 encode them successfully. I need the original String representation. So how do I add already existing ed25519 keys, and how do I get String representations of ones I generate with Curve25519?
Asked Last updated
.