I have generated an EC public/private key pair using openssl with the following commands:

openssl ecparam -name brainpoolP512t1 -param_enc explicit -genkey -out mykey.pem
openssl ec -in mykey.pem -pubout -out mykey.pub

How can I encrypt / decrypt a file using the new keys that I've just generated using the (linux) terminal?

migrated from crypto.stackexchange.com Nov 21 '15 at 21:10

This question came from our site for software developers, mathematicians and others interested in cryptography.

  • Do you only want to encrypt or do you also want to sign? – SEJPM Nov 21 '15 at 17:17
  • @SEJPM Just encrypt, though if I have to sign too that's not a problem. – starbeamrainbowlabs Nov 21 '15 at 17:21
  • 2
    I'm voting to close this question as off-topic because it is about usage of cryptography-based software rather than about cryptography itself. – user440784 Nov 21 '15 at 17:51
  • 1
    I'm proposing to migrate this question, as it doesn't ask about cryptography per se but may still be useful to other people. I'm proposing SuperUser as migration target, as their scope is (among other things) to answer questions on how to use modern operating systems and their tools. – SEJPM Nov 21 '15 at 18:06

The high level strategy for this is as follows:

  1. Generate a temporary EC private key using openssl ec
  2. Use the recipient's public key to derive a shared secret using openssl pkeyutl
  3. Encrypt the plaintext using openssl enc using the derived secret key
  4. Generate the EC public key from the private key using openssl ecparam
  5. Generate the HMAC of the cipher text into a third file using openssl dgst
  6. Delete the EC private key and the shared secret

The manual flow for this should roughly look at follows:

openssl ec -genkey -param_enc explicit -out temppriv.pem -name brainpool512r1
openssl pkeyutl -derive -inkey temppriv.pem -peerkey RecipientsPublicKey.pem -out SharedSecret.bin
openssl dgst -sha256 -out HashedSharedSecret SharedSecret.bin
openssl enc -aes-256-ofb -iv "00000000000000000000000000000000" -K "<Enter Hex From HashedSharedSecret here>" -in YourPlaintextFile -out ciphertext.enc
openssl ecparam -in tempprivkey.pem -pubout -out temppubkey.pem
openssl dgst -sha256 -hmac "<Enter Hex From HashedSharedSecret here>" -out MAC.bin ciphertext.enc
#strip the everything non-hex using your editor from MAC.bin
rm SharedSecret.bin
rm tempprivkey.pem

The script doing the encryption should roughly look like the following:

    EphemeralPrivateKey=$(openssl ecparam -genkey -param_enc explicit -name brainpool512r1) #generate the ephmeral private key
PrivateKeyBuffer=$(mktemp) #allocate a file to bufer the private key for the derive operation
echo -n "$EphemeralPrivateKey" > $PrivateKeyBuffer  #buffer the private key
    ProcessedDerivedSharedSecret=$(openssl pkeyutl -derive -inkey $PrivateKeyBuffer -peerkey $PeerPublicKey|openssl dgst -sha256) #derive the symmetric key using SHA-256 from the established secret
        rm $PrivateKeyBuffer #remove the temporary file
        ProcessedDerivedSharedSecret=${ProcessedDerivedSharedSecret#*= } #strip the (stdin)=
        openssl enc -aes-256-ofb -iv "0000000000000000000000000000000" -K "$ProcessedDerivedSharedSecret" -in "$PlainTextFile" -out "$CipherTextFile" #encrypt using 0 IV and SHA-256 as key
        MACValue=$(openssl dgst -sha256 -hmac "$ProcessedDerivedSharedSecret" "$CipherTextFile") #MAC it
        MACValue=${MACValue#*= } #strip the (stdin)=
        echo -n "$MACValue" > $MACFile #write the MAC
        echo -n "$EphemeralPrivateKey" | openssl ec -param_enc explicit -pubout -out "$EphemeralPublicKeyFile" #write the ephemeral public key

The above code should work, but may not be optimal. The final message is composed from temppubkey.pem, ciphertext.enc and MAC.bin, you may combine this in whatever way you prefer. Note that my choice for AES-256-OFB is no accident but intentional as CTR, CCM and GCM mode aren't available via the command line. Note further that I preferred AES-256 over the standard choice of AES-128 here because we can simply plug the output of SHA-256 in there. Note even further that using an all-zero IV is secure here as OFB "only" requires unique IVs per key and each key is fully random.

As for the security considerations: This method will generate a temporary private key for each file, ensuring all encryptions are unique and leakage of one shared secret won't leak all shared secrets for the same pair of communication partners. You could use digital signatures to ensure the message actually came from the same source.

  • Thanks! How do I decrypt a message that I've encrypted with this script? – starbeamrainbowlabs Nov 22 '15 at 10:56
  • @starbeamrainbowlabs, same as encryption basically. You derive the shared secret from the supplied (ephemeral) public key and the recipient's private key. You hash it as above. Then you verify the HMAC using openssl dgst, finally you decrypt using openssl enc (there's a command line switch for decryption) – SEJPM Nov 22 '15 at 11:02
  • You need to quote $RawDerivedSharedSecret otherwise it gets split and globbed, which has a low but nonnegligible probability of changing the 'derived' secret so that decrypt using the same parties' keys won't work. Even quoted, depending on your echo (which in turn depends on your shell) some low-proability values may produce differing results on different platforms; printf '%s' "$var" is the safe way. Plus setting it from =$( -derive ) will trim trailing bytes of 00 or 0A, which is consistent but not as presumably desired. ... – dave_thompson_085 Nov 22 '15 at 21:20
  • ... To avoid both simply, put the derive and the hash-to-hex in one pipeline processed=$(openssl pkeyutl -derive ... | openssl sha256). After deleting (stdin)= from processed it contains only 0-9a-f and can be safely echo'd without quoting. – dave_thompson_085 Nov 22 '15 at 21:32
  • @dave_thompson_085, I hope I've fixed the pipelining as you suggested. Furthermore I think openssl requires the HMAC key and the cipher key to be quoted. But anyways thanks for your advice. – SEJPM Nov 22 '15 at 21:48

First, some OpenSSL docs : https://wiki.openssl.org/index.php/Command_Line_Elliptic_Curve_Operations

and it has been already answered with a good code example : https://stackoverflow.com/questions/1152555/encrypting-decrypting-text-strings-using-openssl-ecc/3449701#3449701

  • The code in that post appears to be in C / C++. I want to use a command line tool. – starbeamrainbowlabs Nov 21 '15 at 17:01
  • what about compiling the code into a command-line tool? Write all the exact ciphers in source and compile your solution =) – Alexey Vesnin Nov 23 '15 at 1:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.