How to get/use asymmetric keys for ~20K of data?

I'd like to use a public key to encrypt data in my app, then use a private key to decrypt it on my private machine. RSA won't work as the data needs to be smaller than the key (more or less). I read I can use Ellyptical Encryption to do this, and it appears to to work. But it seems the key is limited to 384 bytes:


private let keyType = kSecAttrKeyTypeECSECPrimeRandom // kSecAttrKeyTypeEC
private let algorithm = SecKeyAlgorithm.eciesEncryptionStandardX963SHA384AESGCM // eciesEncryptionStandardX963SHA512AESGCM
private let keySize = 256 // works: 256, 384 NoGood: 512

        let keyPairAttr:[CFString: Any] = [
            kSecAttrKeyType         : keyType,
            kSecAttrKeySizeInBits   : keySize,
            kSecPrivateKeyAttrs     : privateKeyAttr,
            kSecPublicKeyAttrs      : publicKeyAttr
        ]

        var publicKey: SecKey? = nil
        var privateKey: SecKey? = nil
        sanityCheck = SecKeyGeneratePair(keyPairAttr as CFDictionary, &publicKey, &privateKey)

        guard SecKeyIsAlgorithmSupported(key, .encrypt, algorithm) else {
            fatalError("Can't use this algorithm with this key!")
        }
        if let encryptedCFData = SecKeyCreateEncryptedData(key, algorithm, cfData, &error) {
            return encryptedCFData as NSData as Data
        }

I am a total Crypto noobie. I read that often you create a symmetric key, then send it to the remote using RSA asymmetric - its just cumbersome and somewhat difficult in my situation.


I only would be sending data occasionally, and it would be around 20K in size. I cannot find any description on relative merits of different "algorithms" - is there a suggested set of settings that provide reasonable security and performance?

Replies

I am a total Crypto noobie.

Do not use asymmetric encryption for encrypting large quantities of data. That is a classic newbie mistake [1] )-:

Another newbie mistake is to implement your own custom crypto data format or protocol. Design of such things should be left to crypto experts. And even those folks get things wrong (hence the TLS 1.0 through 1.2 saga [2]).

My advice is that you implement (or use a library implementation of) some standard data format or protocol. Which one you choose depends on your specific requirements.

On that subject you wrote:

I'd like to use a public key to encrypt data in my app, then use a private key to decrypt it on my private machine.

Can you explain more about this? If your goal is to transport data from one machine to another, you should use TLS; you don’t need an extra layer of crypto on top of that. If, however, you also want to protect the data at rest then you need a crypto data format that supports that goal. If you’re working on macOS there’s an obvious choice for that, namely CMS. iOS has no CMS support, so if you’re targeting iOS then there’s no built-in solution and you need to look at non-built-in alternatives.

Share and Enjoy

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

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

[1] And by that I mean “I’ve done it myself but now know better.” (-;

[2] TLS 1.3 is a different kettle of fish, it’s primary goal not being to close known security vulnerabilities but to simplify the protocol to try to prevent future ones.

The situation I'm dealing with is that I have some data that would be extremely helpful to me, that would end up getting tossed in a file on a computer that while requires a login is not what I consider very secure. The data would get tossed in a file along with other bits of data related to corporate business. I'd be extracting that info occasionally, and want to provide a reasonabe level of protection to it. Perhaps this is not achieveable.


I found an article online by Apple itself that touches on what I am trying to accomplish: "Using Keys for Encryption - Perform asymmetric and symmetric encryption and decryption using cryptographic keys." It speaks of the need to encrypt arbitrary data using a private key, that is then unencrypted by the holder of a private key.


For that reason, you’ll usually want to use another method, such as asymmetric encryption, to exchange a symmetric key at the time you begin communicating. In fact, the certificate, key, and trust services API provides a simple way to accomplish this. You follow all of the steps outlined in Use Asymmetric Encryption, with only the following adjustments:

- Change the algorithm. When you choose an algorithm of kSecKeyAlgorithmRSAEncryptionOAEPSHA512AESGCM or one of the other symmetric encryption algorithms, the encryption and decryption function calls change their behavior.


So it suggests in addition to the algorithm above, there are others that also would let me accomplish my goal. What is returned as keys are RSA keys, but under the hood what happens is that Apple also creates a symmetric key, encodes that in the encrypted data, and this process is unwound on the other side. However, there is not explanation I can find on the other algorithms including kSecKeyAlgorithmECIESEncryptionCofactorX963SHA256AESGCM whichalso appears viable.

The situation I'm dealing with is that I have some data that would be extremely helpful to me, that would end up getting tossed in a file on a computer that while requires a login is not what I consider very secure. The data would get tossed in a file along with other bits of data related to corporate business. I'd be extracting that info occasionally, and want to provide a reasonabe level of protection to it. Perhaps this is not achieveable.

That’s certainly achievable. Two things:

  • You’re dealing with data at rest, which an import criteria informing your crypto choices.

  • You need asymmetric encryption, because you can’t give the insecure client any private material. If you used symmetric encryption then you’d have to give the client the key, and that could be compromised.

So the general idea would be as follows:

  1. On a secure machine generate a asymmetric key pair.

  2. Keep the private key private on the secure machine.

  3. Distribute the public key to the insecure machine.

  4. On the insecure machine use that public key to encrypt your data.

  5. Once the data has made its way to secure machine it can decrypt it using the public key.

Now the devil here is in the details. And to help there I need more info from you. Specifically, the fact that you mentioned “login” and “computer” implies that you’re working on macOS. Is that right?

Share and Enjoy

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

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