Score:0

Hybrid encryption parameters when using elliptic curve keys

do flag

I wrote a command line application for encrypting/decrypting files to your local machine. The idea is you have an asymmetric key pair where the private key is stored encrypted and the public key is stored in plain text. This way you can encrypt data without having to "unlock" the application (decrypt your private key), but you must run the unlock command and provide your password to decrypt anything.

The encryption process is roughly as follows:

  1. You provide some plain text
  2. A (secure) random AES key is generated
  3. Your plain text is encrypted with the AES key
  4. The AES key is encrypted with your public key
  5. The encrypted AES key and ciphertext are written to a file

The decryption process then is roughly as follows:

  1. You provide a password
  2. That password is put into a key derivation algorithm to establish an AES key
  3. That AES is used to decrypt your private key
  4. The private key is used to decrypt the AES key for the file you are trying to decrypt
  5. The files AES is used to decrypt the file

My hope was that I could allow the user to specify which asymmetric cipher they want to use. For example you could choose to use RSA with 4096 bit keys or ECIES with Ed448 keys. I imagined this would be possible as the app is written in Java/Kotlin using Bouncy Castle and the JCA provides a generic interface for retrieving and initialising asymmetric key pair generators and ciphers. For example:

    val keyGen = KeyPairGenerator.getInstance("ED448")
    keyGen.initialize(448)
    val keyPair = keyGen.genKeyPair()

    val asymmetricCipher = Cipher.getInstance("XIES")
    asymmetricCipher.init( Cipher.ENCRYPT_MODE, keyPair.public)

In this example the user can provide: "ED448" as the key pair generator algorithm, 448 as the key size (redundant in this case but not always), and "XIES" as the cipher name/transform. My hope is this flexibility will future proof the application a little more as you can use any cipher provided by your JCA and can therefore switch if a vulnerability is discovered etc. For example I was previously using the parameters: RSA, RSA/ECB/PKCS1Padding, 2048

In reality however I'm finding that Bouncy Castle's ECIES and XIES cipher implementations throw an exception if you do not provide algorithm specific parameters when you initialise the cipher i.e.

/**
 * Set the IES engine parameters.
 *
 * @param derivation    the optional derivation vector for the KDF.
 * @param encoding      the optional encoding vector for the KDF.
 * @param macKeySize    the key size (in bits) for the MAC.
 * @param cipherKeySize the key size (in bits) for the block cipher.
 * @param nonce         an IV to use initialising the block cipher.
 * @param usePointCompression whether to use EC point compression or not (false by default)
 */
public IESParameterSpec(
    byte[] derivation,
    byte[] encoding,
    int macKeySize,
    int cipherKeySize,
    byte[] nonce,
    boolean usePointCompression)
{

What I'm considering doing in order to keep the interface generic for the end user is just to have a hard coded parameter spec object that is used if the user provides ECIES/XIES or any variant there of and simply pass the parameters:

        IESParameterSpec(
            /* derivation = */ null,
            /* encoding = */ null,
            /* macKeySize = */ 256,
            /* cipherKeySize = */ 256,
            /* nonce = */ null,
            /* usePointCompression = */ false
        )

Bearing in mind that the only thing this cipher ever encrypts is randomly generated 256 bit AES keys, is this a safe/reasonable standard parameter spec or is it necessary to always use (and presumably then store) fresh parameters for each encryption operation?

Perhaps I am way off base and it is not reasonable to try to provide a generic interface for all asymmetric cipher/key pair specifications despite what the JCA interface would have you believe. Or perhaps there is a much simpler cipher one can use with an elliptic curve key pair that doesn't require such parameters. I don't possess a lot of experience with elliptic curve cryptography so please let me know.

poncho avatar
my flag
Stupid question: since ECIES is already doing what you want (generating an AES key and encrypting some text with that key), why are you using ECIES just to encrypt your selected AES key?
Samuel Amantea-Collins avatar
do flag
Really just to maintain compatibility/generality. I was hoping to have no domain specific knowledge in the code about which asymmetric cipher is being used. I don't want to have two entirely different versions of the code depending on whether you're using ECIES or RSA. If you're using RSA the code must generate an AES key, encrypt it and prepend it to the top of the encrypted file. I wanted to just have the same pattern everywhere for simplicity.
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.