# Using OpenSSL to Sign Data (Simple Guide)

OpenSSL, a tool which accompanies us all the time but often being ignored by everyone. OpenSSL is currently the most powerful tool in the cryptographic industry.

With that said, OpenSSL itself is not easy to use and rather complicated and confusing.

This guide focus on signing & encrypting data in a simple way, utilizing a pair of **Elliptic Curve** keys.

My OpenSSL version:

```
OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)
```

## Getting Started

### Generate keys

First we need to choose the algorithm. Unlike `RSA`

, which only differs in key size, `ECC`

has a lot of curves, like NIST curve, Brainpool curve.

Yeah I know, Curve 25519 folks. Unfortunately Curve 25519 is not a standard curve and therefore not supported by

`ecparam`

in OpenSSL. Alternatively you can use`openssl genpkey -algorithm ed25519/x25519`

to generate Curve 25519 keys, but due to the specialty of Curve 25519, itCANNOTbe used for encryption, only signing. Also, you areoughtto generate X.509 certificates in order to sign stuff, which is beyond what we are going to talk about.

Run `openssl ecparam -list_curves`

to see all the curves available.

```
$ openssl ecparam -list_curves 1 ↵
secp112r1 : SECG/WTLS curve over a 112 bit prime field
secp112r2 : SECG curve over a 112 bit prime field
secp128r1 : SECG curve over a 128 bit prime field
secp128r2 : SECG curve over a 128 bit prime field
secp160k1 : SECG curve over a 160 bit prime field
secp160r1 : SECG curve over a 160 bit prime field
secp160r2 : SECG/WTLS curve over a 160 bit prime field
secp192k1 : SECG curve over a 192 bit prime field
secp224k1 : SECG curve over a 224 bit prime field
secp224r1 : NIST/SECG curve over a 224 bit prime field
secp256k1 : SECG curve over a 256 bit prime field
secp384r1 : NIST/SECG curve over a 384 bit prime field
secp521r1 : NIST/SECG curve over a 521 bit prime field
prime192v1: NIST/X9.62/SECG curve over a 192 bit prime field
prime192v2: X9.62 curve over a 192 bit prime field
prime192v3: X9.62 curve over a 192 bit prime field
prime239v1: X9.62 curve over a 239 bit prime field
prime239v2: X9.62 curve over a 239 bit prime field
prime239v3: X9.62 curve over a 239 bit prime field
prime256v1: X9.62/SECG curve over a 256 bit prime field
sect113r1 : SECG curve over a 113 bit binary field
sect113r2 : SECG curve over a 113 bit binary field
sect131r1 : SECG/WTLS curve over a 131 bit binary field
sect131r2 : SECG curve over a 131 bit binary field
sect163k1 : NIST/SECG/WTLS curve over a 163 bit binary field
sect163r1 : SECG curve over a 163 bit binary field
sect163r2 : NIST/SECG curve over a 163 bit binary field
sect193r1 : SECG curve over a 193 bit binary field
sect193r2 : SECG curve over a 193 bit binary field
sect233k1 : NIST/SECG/WTLS curve over a 233 bit binary field
sect233r1 : NIST/SECG/WTLS curve over a 233 bit binary field
sect239k1 : SECG curve over a 239 bit binary field
sect283k1 : NIST/SECG curve over a 283 bit binary field
sect283r1 : NIST/SECG curve over a 283 bit binary field
sect409k1 : NIST/SECG curve over a 409 bit binary field
sect409r1 : NIST/SECG curve over a 409 bit binary field
sect571k1 : NIST/SECG curve over a 571 bit binary field
sect571r1 : NIST/SECG curve over a 571 bit binary field
c2pnb163v1: X9.62 curve over a 163 bit binary field
c2pnb163v2: X9.62 curve over a 163 bit binary field
c2pnb163v3: X9.62 curve over a 163 bit binary field
c2pnb176v1: X9.62 curve over a 176 bit binary field
c2tnb191v1: X9.62 curve over a 191 bit binary field
c2tnb191v2: X9.62 curve over a 191 bit binary field
c2tnb191v3: X9.62 curve over a 191 bit binary field
c2pnb208w1: X9.62 curve over a 208 bit binary field
c2tnb239v1: X9.62 curve over a 239 bit binary field
c2tnb239v2: X9.62 curve over a 239 bit binary field
c2tnb239v3: X9.62 curve over a 239 bit binary field
c2pnb272w1: X9.62 curve over a 272 bit binary field
c2pnb304w1: X9.62 curve over a 304 bit binary field
c2tnb359v1: X9.62 curve over a 359 bit binary field
c2pnb368w1: X9.62 curve over a 368 bit binary field
c2tnb431r1: X9.62 curve over a 431 bit binary field
wap-wsg-idm-ecid-wtls1: WTLS curve over a 113 bit binary field
wap-wsg-idm-ecid-wtls3: NIST/SECG/WTLS curve over a 163 bit binary field
wap-wsg-idm-ecid-wtls4: SECG curve over a 113 bit binary field
wap-wsg-idm-ecid-wtls5: X9.62 curve over a 163 bit binary field
wap-wsg-idm-ecid-wtls6: SECG/WTLS curve over a 112 bit prime field
wap-wsg-idm-ecid-wtls7: SECG/WTLS curve over a 160 bit prime field
wap-wsg-idm-ecid-wtls8: WTLS curve over a 112 bit prime field
wap-wsg-idm-ecid-wtls9: WTLS curve over a 160 bit prime field
wap-wsg-idm-ecid-wtls10: NIST/SECG/WTLS curve over a 233 bit binary field
wap-wsg-idm-ecid-wtls11: NIST/SECG/WTLS curve over a 233 bit binary field
wap-wsg-idm-ecid-wtls12: WTLS curve over a 224 bit prime field
Oakley-EC2N-3:
IPSec/IKE/Oakley curve #3 over a 155 bit binary field.
Not suitable for ECDSA.
Questionable extension field!
Oakley-EC2N-4:
IPSec/IKE/Oakley curve #4 over a 185 bit binary field.
Not suitable for ECDSA.
Questionable extension field!
brainpoolP160r1: RFC 5639 curve over a 160 bit prime field
brainpoolP160t1: RFC 5639 curve over a 160 bit prime field
brainpoolP192r1: RFC 5639 curve over a 192 bit prime field
brainpoolP192t1: RFC 5639 curve over a 192 bit prime field
brainpoolP224r1: RFC 5639 curve over a 224 bit prime field
brainpoolP224t1: RFC 5639 curve over a 224 bit prime field
brainpoolP256r1: RFC 5639 curve over a 256 bit prime field
brainpoolP256t1: RFC 5639 curve over a 256 bit prime field
brainpoolP320r1: RFC 5639 curve over a 320 bit prime field
brainpoolP320t1: RFC 5639 curve over a 320 bit prime field
brainpoolP384r1: RFC 5639 curve over a 384 bit prime field
brainpoolP384t1: RFC 5639 curve over a 384 bit prime field
brainpoolP512r1: RFC 5639 curve over a 512 bit prime field
brainpoolP512t1: RFC 5639 curve over a 512 bit prime field
SM2 : SM2 curve over a 256 bit prime field
```

Basically all the curves above are available to use, specifically begun with `prime, secp, brainpool`

`SM2`

is the algorithm developed by the Chinese government and, currently, little information about it is available online. Unless you work for the CHinese government or you are dealing with entites that related to banking or incorporating in China, you are generally not suggested to use SM2 curves.

We will be using SECP curves today.

To generate your keys,

```
openssl ecparam -name secp384r1 -genkey -noout -out private.pem
```

So here’s the thing, `ecparam`

by default only generates the `parameters`

that are needed to generate the respective curve, which is useful if you need to generate a lot of curves. Obviously this is not the case here, so we give it `-genkey`

to ask it to generate the key, and we specify `-noout`

to ask OpenSSL to not output the parameters. The `-name`

is not the name of your private key, but the name of the curve that you are using, here we are going to use 384-bit SECP curve.

#### Encrypting your key

The key we have just generated is **UNENCRYPTED**, which is not safe. I suggest everyone to encrypt their key(s).

```
openssl ec -in private.pem -aes-256-cbc -out private_enc.pem
```

Put in your passphrase and you are good to go.

To obtain your public key,

```
openssl ec -in private.pem -pubout -out public.pem
```

### Signing

Now we can sign some data.

To generate some random number,

```
dd if=/dev/random of=data bs=1k count=1
--- OR ---
echo $RANDOM | tee data
```

And to sign it,

```
openssl dgst -sha384 -sign private.pem data > data.sig
```

To verify it,

```
openssl dgst -sha384 -verify public.pem -signature data.sig data
```

If everything is OK, you will see

```
$ openssl dgst -sha384 -verify public.pem -signature data.sig data
Verified OK
```

Alternatively, you can use `-sha256`

or `-sha512`

.

### Encrypting

Due to the specialty of ECC, you **CANNOT** encrypt big data blocks directly. Instead, you should generate a long and complex symmetric key and encrypt your big data blocks using that key. After that, you encrypt the key.

We first need to generate the symmetric key, but we don’t need it to be ASCII-armored. A binary should be ok.

```
openssl rand -out symmetric_key.bin 256
```

The `256`

stands for the bit length. Longer is usually better but your encryption speed will be significantly slower.

After that, we can symmetrically encrypt the data.

```
openssl enc -aes-256-cbc -pbkdf2 -in data -out data_enc.bin -pass file:./symmetric_key.bin
```

Okay, let’s deal with the key.

Still, due to the specialty of ECC, we cannot encrypt the data directly. Instead, we need to utilize something called **ECDH** to derive a shared key from our primary key, which is symmetric. Then we encrypt data using that key.

```
# Derive a shared key from our primary key.
openssl pkeyutl -derive -inkey private.pem -peerkey public.pem -out shared_key.bin
# Convert the shared key into an AES key.
openssl dgst -sha256 -binary shared_key.bin > derived_key.bin
# Encrypt the key that was used to encrypt files using the derived key.
openssl enc -aes-256-cbc -pbkdf2 -in symmetric_key.bin -out encrypted_symmetric_key.bin -pass file:./derived_key.bin
```

Similarly, we can decrypt the data in the following steps.

```
# Derive a shared key from our primary key.
openssl pkeyutl -derive -inkey private.pem -peerkey public.pem -out shared_key.bin
# Convert the shared key into an AES key.
openssl dgst -sha256 -binary shared_key.bin > derived_key.bin
# Decrypt the key that was used to decrypt files using the derived key.
openssl enc -d -aes-256-cbc -pbkdf2 -in encrypted_symmetric_key.bin -out decrypted_symmetric_key.bin -pass file:./derived_key.bin
# Decrypt the data
openssl enc -d -aes-256-cbc -pbkdf2 -in data_enc.bin -out data_decrypted -pass file:./decrypted_symmetric_key.bin
```

Your decrypted file should appear in `data_decrypted`

## Outro

This is just a simple guide to signing, encrypting, and decrypting using OpenSSL, with ECC keys. ECC itself is very different, so it’s not as easy as RSA, but I’m sure that you have understood the basic operations by viewing this article.