Data Protection - Master in Cyber Security (UPC)
Jorge L. Villar, 2026
The
openssl
tool provides specific commands for key generation of some public key encryption schemes.
The command
genpkey
is used to generate a public / secret keypair.
The way this command is used depends on the selected public key algorithm.
$ openssl genpkey -algorithm rsa
outputs a text encoding of a public key and a secret key for the RSA encryption scheme, with the default parameters (e.g., the size of the modulus). For example, the previous call results in the output
-----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDoZCHtGHhaKo8g cM8STl8w7rs7L28VWCfcI3LGC8NkRTuyt/7W9siGUV4EtOd9CtTvuhNTLE7NgxOa PbhlAFZEIAGubeKlPx0Qu+JskQ7S5OTfXeMgmLIuw60OEUjOmrDsZyK0xoWu1SGg kWF+ZhS/4dYdGAt4Lu0ktuFxKTqhKvbbpcfdZOvAurwgmsZhOcj+CDMmudWuYOOE zGdoSGSQZJOulaBBTOMN1YJSQJMrV9QwsPYRgk/8PdSnEmmDORBYYvvXFKj1pNL0 majXTVofnZG/QPQs9gfzMir9Uw5O/4lPnrgg8hy5r53bBlSwAtzN1En7BH22ZD0n nYcZKNR/AgMBAAECggEAIdibnFWJCdDTAa2MayUg9hZ/DHKvIhOx0n0TNUb3UT5I IJJtuk89C1sEb3kNkgem1bdrIxz76TCjBT7iAUvYRJnIxOfaL6kOiaZjpt5Fo2+U 6fdZoiC7KtZy+O6JhRXAmN24j02uoLUH7cPeyDMD6KJytdAPs5RaE5PTJ9ESafB5 54AezAtEF9NG52iY26VlBvhd1bD8xpXlckKToAO4aA1DzMEovSb1mBLitAOxefO7 y6oqDWpZg7XG/3xTeJQr2GDhhLuauledtYZTbgvDltipixjPMm/btGgNrZVAX0wU 0s0MxVN9B8u/k+yuK6GoqYmH+APEhyghg63+73L0uQKBgQDsEap5Z7671Eblkbsb UpwKu4CVlmJt67sv4aUTncfyeBfgXqTnPQGVIy82EHmOlSmNNyeIrbTjXdY82XJ8 WSh4bxSrf9Ckl6wlbrnvNvJnaMgbDpbotfd3KXuh48W/WYG1I23H/54OXkN51Zk7 w1pe2/URPGR/Jq22nC2FcdVwbQKBgQD8Avlk7jtN9b/M8CM4sE8kP29STfBnGe3t kKWglqz0xQgEfzLm7MEGi/zhPxyPxE5ccniC4ltVH2AyynODXFXwe/CiGX7Endki wDUKsbrJcrr0Z0Y9DIsFEuKnGD1btfEnKGmziHIO92N3vHfLzsISGFO+Dcdg/naY QEzUGcw9GwKBgQDOrCizYUB68L2g/pTwtsImI0HPtHk4Ask+gi4jnl8OyFUe+b0l NSPNjaAnlQTW74ARQdg6sNlMtTp6y2SPuP7VcWqHOr9PWfo8S1Q9Ob2/Ct0l0wAL fEPK72ZttRvLCnGkRAA4uHGH4r7wSzB8Qes8YRWMoXLaXuJ2nQS9b4uNgQKBgFLT G2objewiX2YYaksATxJnssuHCAKql/Li/jxYKQHNG8R2laEloI7pRTQ2TMnHR8XE bWz+veutAy3OMcazex8tbLmpzWsLQcjVCNm57dy1U1Jt+rynuazyNwGZytiwZFBt TMgPiQT4M32vuGOIUWonCqbE2ok7OHjzcQyoaeKPAoGBAI0BvipxqWAct95q2AeJ TxKDNncMSQnuPOfWl7yw7t7o2PRy5XmEMavngwyswt/dwwQ0/9oZ5kC8e/8nMGb+ FqSApQ253u2ll0Cmu6Ws953Ck1FkHrJ5Dm6zaBXFhIvmN59xl1QcjZ+wXPtdivDS PnxPQVzC54zud6JkpELf6Zxi -----END PRIVATE KEY-----
The text output is given in PEM (Privacy-Enhanced Mail) format, but you can also produce a human readable text format by adding the option
-text
to the command line:
Private-Key: (2048 bit, 2 primes)
modulus:
00:e8:64:21:ed:18:78:5a:2a:8f:20:70:cf:12:4e:
5f:30:ee:bb:3b:2f:6f:15:58:27:dc:23:72:c6:0b:
c3:64:45:3b:b2:b7:fe:d6:f6:c8:86:51:5e:04:b4:
e7:7d:0a:d4:ef:ba:13:53:2c:4e:cd:83:13:9a:3d:
b8:65:00:56:44:20:01:ae:6d:e2:a5:3f:1d:10:bb:
e2:6c:91:0e:d2:e4:e4:df:5d:e3:20:98:b2:2e:c3:
ad:0e:11:48:ce:9a:b0:ec:67:22:b4:c6:85:ae:d5:
21:a0:91:61:7e:66:14:bf:e1:d6:1d:18:0b:78:2e:
ed:24:b6:e1:71:29:3a:a1:2a:f6:db:a5:c7:dd:64:
eb:c0:ba:bc:20:9a:c6:61:39:c8:fe:08:33:26:b9:
d5:ae:60:e3:84:cc:67:68:48:64:90:64:93:ae:95:
a0:41:4c:e3:0d:d5:82:52:40:93:2b:57:d4:30:b0:
f6:11:82:4f:fc:3d:d4:a7:12:69:83:39:10:58:62:
fb:d7:14:a8:f5:a4:d2:f4:99:a8:d7:4d:5a:1f:9d:
91:bf:40:f4:2c:f6:07:f3:32:2a:fd:53:0e:4e:ff:
89:4f:9e:b8:20:f2:1c:b9:af:9d:db:06:54:b0:02:
dc:cd:d4:49:fb:04:7d:b6:64:3d:27:9d:87:19:28:
d4:7f
publicExponent: 65537 (0x10001)
privateExponent:
21:d8:9b:9c:55:89:09:d0:d3:01:ad:8c:6b:25:20:
f6:16:7f:0c:72:af:22:13:b1:d2:7d:13:35:46:f7:
51:3e:48:20:92:6d:ba:4f:3d:0b:5b:04:6f:79:0d:
92:07:a6:d5:b7:6b:23:1c:fb:e9:30:a3:05:3e:e2:
01:4b:d8:44:99:c8:c4:e7:da:2f:a9:0e:89:a6:63:
a6:de:45:a3:6f:94:e9:f7:59:a2:20:bb:2a:d6:72:
f8:ee:89:85:15:c0:98:dd:b8:8f:4d:ae:a0:b5:07:
ed:c3:de:c8:33:03:e8:a2:72:b5:d0:0f:b3:94:5a:
13:93:d3:27:d1:12:69:f0:79:e7:80:1e:cc:0b:44:
17:d3:46:e7:68:98:db:a5:65:06:f8:5d:d5:b0:fc:
c6:95:e5:72:42:93:a0:03:b8:68:0d:43:cc:c1:28:
bd:26:f5:98:12:e2:b4:03:b1:79:f3:bb:cb:aa:2a:
0d:6a:59:83:b5:c6:ff:7c:53:78:94:2b:d8:60:e1:
84:bb:9a:ba:57:9d:b5:86:53:6e:0b:c3:96:d8:a9:
8b:18:cf:32:6f:db:b4:68:0d:ad:95:40:5f:4c:14:
d2:cd:0c:c5:53:7d:07:cb:bf:93:ec:ae:2b:a1:a8:
a9:89:87:f8:03:c4:87:28:21:83:ad:fe:ef:72:f4:
b9
prime1:
00:ec:11:aa:79:67:be:bb:d4:46:e5:91:bb:1b:52:
9c:0a:bb:80:95:96:62:6d:eb:bb:2f:e1:a5:13:9d:
c7:f2:78:17:e0:5e:a4:e7:3d:01:95:23:2f:36:10:
79:8e:95:29:8d:37:27:88:ad:b4:e3:5d:d6:3c:d9:
72:7c:59:28:78:6f:14:ab:7f:d0:a4:97:ac:25:6e:
b9:ef:36:f2:67:68:c8:1b:0e:96:e8:b5:f7:77:29:
7b:a1:e3:c5:bf:59:81:b5:23:6d:c7:ff:9e:0e:5e:
43:79:d5:99:3b:c3:5a:5e:db:f5:11:3c:64:7f:26:
ad:b6:9c:2d:85:71:d5:70:6d
prime2:
00:fc:02:f9:64:ee:3b:4d:f5:bf:cc:f0:23:38:b0:
4f:24:3f:6f:52:4d:f0:67:19:ed:ed:90:a5:a0:96:
ac:f4:c5:08:04:7f:32:e6:ec:c1:06:8b:fc:e1:3f:
1c:8f:c4:4e:5c:72:78:82:e2:5b:55:1f:60:32:ca:
73:83:5c:55:f0:7b:f0:a2:19:7e:c4:9d:d9:22:c0:
35:0a:b1:ba:c9:72:ba:f4:67:46:3d:0c:8b:05:12:
e2:a7:18:3d:5b:b5:f1:27:28:69:b3:88:72:0e:f7:
63:77:bc:77:cb:ce:c2:12:18:53:be:0d:c7:60:fe:
76:98:40:4c:d4:19:cc:3d:1b
exponent1:
00:ce:ac:28:b3:61:40:7a:f0:bd:a0:fe:94:f0:b6:
c2:26:23:41:cf:b4:79:38:02:c9:3e:82:2e:23:9e:
5f:0e:c8:55:1e:f9:bd:25:35:23:cd:8d:a0:27:95:
04:d6:ef:80:11:41:d8:3a:b0:d9:4c:b5:3a:7a:cb:
64:8f:b8:fe:d5:71:6a:87:3a:bf:4f:59:fa:3c:4b:
54:3d:39:bd:bf:0a:dd:25:d3:00:0b:7c:43:ca:ef:
66:6d:b5:1b:cb:0a:71:a4:44:00:38:b8:71:87:e2:
be:f0:4b:30:7c:41:eb:3c:61:15:8c:a1:72:da:5e:
e2:76:9d:04:bd:6f:8b:8d:81
exponent2:
52:d3:1b:6a:1b:8d:ec:22:5f:66:18:6a:4b:00:4f:
12:67:b2:cb:87:08:02:aa:97:f2:e2:fe:3c:58:29:
01:cd:1b:c4:76:95:a1:25:a0:8e:e9:45:34:36:4c:
c9:c7:47:c5:c4:6d:6c:fe:bd:eb:ad:03:2d:ce:31:
c6:b3:7b:1f:2d:6c:b9:a9:cd:6b:0b:41:c8:d5:08:
d9:b9:ed:dc:b5:53:52:6d:fa:bc:a7:b9:ac:f2:37:
01:99:ca:d8:b0:64:50:6d:4c:c8:0f:89:04:f8:33:
7d:af:b8:63:88:51:6a:27:0a:a6:c4:da:89:3b:38:
78:f3:71:0c:a8:69:e2:8f
coefficient:
00:8d:01:be:2a:71:a9:60:1c:b7:de:6a:d8:07:89:
4f:12:83:36:77:0c:49:09:ee:3c:e7:d6:97:bc:b0:
ee:de:e8:d8:f4:72:e5:79:84:31:ab:e7:83:0c:ac:
c2:df:dd:c3:04:34:ff:da:19:e6:40:bc:7b:ff:27:
30:66:fe:16:a4:80:a5:0d:b9:de:ed:a5:97:40:a6:
bb:a5:ac:f7:9d:c2:93:51:64:1e:b2:79:0e:6e:b3:
68:15:c5:84:8b:e6:37:9f:71:97:54:1c:8d:9f:b0:
5c:fb:5d:8a:f0:d2:3e:7c:4f:41:5c:c2:e7:8c:ee:
77:a2:64:a4:42:df:e9:9c:62
In this version of OpenSSL (3.0.2g), the defaults for RSA are a size of 2048 bits and the public exponent 65537.
Newer or future versions could enlarge the default RSA key size.
The additional fields named
exponent1
,
exponent2
and
coefficient
can be useful to speed up the decryption operation.
You can override the default parameters by providing the desired values via the option
-pkeyopt
.
For instance,
$ openssl genpkey -algorithm rsa -pkeyopt rsa_keygen_bits:1024 -pkeyopt rsa_keygen_pubexp:17
will use the (insecure) specified values for the key generation.
Other public key cryptosystems, like the Diffie-Hellman key exchange, require a previous generation of some public parameters.
The same command
genpkey
can be used for public parameter generation with the option
-genparam
.
For instance, (the order of the options matters!)
$ openssl genpkey -genparam -algorithm dh -text
produces the output
-----BEGIN DH PARAMETERS-----
MIIBCAKCAQEA8ClCIPVTf6epmsEpsrw9UqgbWfgn66w5+C6Gjt+aXghlxBwAwIJM
JGDH96685xhGauTCttWv02hsw5X/ESdUBfSdeU2kWWlOrcC48N2F35XA/qV0fajv
gojBB3lIaf6kVLulLrFxwnFre1tUVrg+3jCllkRgPf2CtaKZK5vcjcQn1PfkvBNe
90TNcyDdzEbrlhgcuFFo9aD/j6Tskhp4UmtSZbwjNqrfjJzRYr0mmM3U61qcWX+H
0b2Tlvb0imefR3WixEyvBFn7C7F4TcVZneWcrI3N/520z3vE20tpfFJB63TxTs7t
5SxF8+AgWBkUFt5fiy5jMKG9ULzQwuKVVwIBAg==
-----END DH PARAMETERS-----
DH Parameters: (2048 bit)
P:
00:f0:29:42:20:f5:53:7f:a7:a9:9a:c1:29:b2:bc:
3d:52:a8:1b:59:f8:27:eb:ac:39:f8:2e:86:8e:df:
9a:5e:08:65:c4:1c:00:c0:82:4c:24:60:c7:f7:ae:
bc:e7:18:46:6a:e4:c2:b6:d5:af:d3:68:6c:c3:95:
ff:11:27:54:05:f4:9d:79:4d:a4:59:69:4e:ad:c0:
b8:f0:dd:85:df:95:c0:fe:a5:74:7d:a8:ef:82:88:
c1:07:79:48:69:fe:a4:54:bb:a5:2e:b1:71:c2:71:
6b:7b:5b:54:56:b8:3e:de:30:a5:96:44:60:3d:fd:
82:b5:a2:99:2b:9b:dc:8d:c4:27:d4:f7:e4:bc:13:
5e:f7:44:cd:73:20:dd:cc:46:eb:96:18:1c:b8:51:
68:f5:a0:ff:8f:a4:ec:92:1a:78:52:6b:52:65:bc:
23:36:aa:df:8c:9c:d1:62:bd:26:98:cd:d4:eb:5a:
9c:59:7f:87:d1:bd:93:96:f6:f4:8a:67:9f:47:75:
a2:c4:4c:af:04:59:fb:0b:b1:78:4d:c5:59:9d:e5:
9c:ac:8d:cd:ff:9d:b4:cf:7b:c4:db:4b:69:7c:52:
41:eb:74:f1:4e:ce:ed:e5:2c:45:f3:e0:20:58:19:
14:16:de:5f:8b:2e:63:30:a1:bd:50:bc:d0:c2:e2:
95:57
G: 2 (0x2)
corresponding to the PEM and the plain text output formats.
Observe that no public / secret keys are generated, but only the description of the Diffie-Hellman group.
The labels
P
and
G
can be different across OpenSSL versions.
In this OpenSSl version, the default size of the prime modulus is 2048. You can specify a different size (e.g., 1024) with the option
-pkeyopt dh_paramgen_prime_len:1024
.
You can save the PEM output to a file (e.g., providing the option
-out
filename) and use it for actual key generation.
This way, you can reuse the same parameters for several keys (e.g., for the two parties in a Diffie-Hellman key exchange).
Given the DH parameter file
mydhgroup.pem
, you can now generate a keypair with
$ openssl genpkey -paramfile mydhgroup.pem -text
You don't need to provide the name of the public key algorithm or the size parameters, because they can be inferred from the public parameters file header. The output produced by the above command is:
-----BEGIN PRIVATE KEY-----
MIICJgIBADCCARcGCSqGSIb3DQEDATCCAQgCggEBAPApQiD1U3+nqZrBKbK8PVKo
G1n4J+usOfguho7fml4IZcQcAMCCTCRgx/euvOcYRmrkwrbVr9NobMOV/xEnVAX0
nXlNpFlpTq3AuPDdhd+VwP6ldH2o74KIwQd5SGn+pFS7pS6xccJxa3tbVFa4Pt4w
pZZEYD39grWimSub3I3EJ9T35LwTXvdEzXMg3cxG65YYHLhRaPWg/4+k7JIaeFJr
UmW8Izaq34yc0WK9JpjN1OtanFl/h9G9k5b29Ipnn0d1osRMrwRZ+wuxeE3FWZ3l
nKyNzf+dtM97xNtLaXxSQet08U7O7eUsRfPgIFgZFBbeX4suYzChvVC80MLilVcC
AQIEggEEAoIBAE1zlNqDYLe6j8tH1X2678l/0zknv8iQXzzge7hHVXKBQftV/mQu
m/zVkf1Uhf9NpoaWA7DG0Rvct1tto/RaW2tUcH/Pr3LK6xgHoTF7Gl5OgM0TAdIX
eRhYDBZTnBY2twiZi2XkrdZ//aaYBaR9xCU0+F8g2c8WCzoXTmZ8sZpDjXl0J01S
Sh8iQjYRvdOPahmHQDXXf/td99Tpm2AzeDRrHn9bm9UELptKhy/T3h6BfaQzPgma
SOqu0VUHD8Q1xSgF7reLvOP3ghVX3hbjkY4CYH3YwutKtDySFL0g3knYDEksQEmf
6rvh5ChTkTX5QLoHy8+yHPH2xpUQNyzTCho=
-----END PRIVATE KEY-----
DH Private-Key: (2048 bit)
private-key:
4d:73:94:da:83:60:b7:ba:8f:cb:47:d5:7d:ba:ef:
c9:7f:d3:39:27:bf:c8:90:5f:3c:e0:7b:b8:47:55:
72:81:41:fb:55:fe:64:2e:9b:fc:d5:91:fd:54:85:
ff:4d:a6:86:96:03:b0:c6:d1:1b:dc:b7:5b:6d:a3:
f4:5a:5b:6b:54:70:7f:cf:af:72:ca:eb:18:07:a1:
31:7b:1a:5e:4e:80:cd:13:01:d2:17:79:18:58:0c:
16:53:9c:16:36:b7:08:99:8b:65:e4:ad:d6:7f:fd:
a6:98:05:a4:7d:c4:25:34:f8:5f:20:d9:cf:16:0b:
3a:17:4e:66:7c:b1:9a:43:8d:79:74:27:4d:52:4a:
1f:22:42:36:11:bd:d3:8f:6a:19:87:40:35:d7:7f:
fb:5d:f7:d4:e9:9b:60:33:78:34:6b:1e:7f:5b:9b:
d5:04:2e:9b:4a:87:2f:d3:de:1e:81:7d:a4:33:3e:
09:9a:48:ea:ae:d1:55:07:0f:c4:35:c5:28:05:ee:
b7:8b:bc:e3:f7:82:15:57:de:16:e3:91:8e:02:60:
7d:d8:c2:eb:4a:b4:3c:92:14:bd:20:de:49:d8:0c:
49:2c:40:49:9f:ea:bb:e1:e4:28:53:91:35:f9:40:
ba:07:cb:cf:b2:1c:f1:f6:c6:95:10:37:2c:d3:0a:
1a
public-key:
7d:d7:89:71:0c:26:21:8e:97:07:e0:a4:af:e5:63:
b4:b6:0a:b4:9e:e1:d5:a0:c1:d7:5e:b4:b5:46:3f:
15:0f:4c:7c:c0:e9:e6:a5:ec:eb:18:ce:9c:26:80:
26:a0:b9:30:b9:24:a0:ce:11:41:08:d3:cc:f3:2a:
01:03:c3:7d:9f:e9:3a:ae:78:62:2d:d2:c7:1a:35:
eb:d5:5a:b6:fe:3a:f9:37:de:6f:2b:0e:5e:07:e8:
c2:bd:82:8f:50:84:56:26:ef:83:71:24:ec:72:f9:
21:a3:1e:b6:86:1a:1b:b3:b9:8f:e3:58:1c:ef:5e:
f6:33:f6:da:61:2d:bb:f9:db:f2:2d:7c:0d:9e:96:
ea:da:8c:69:3e:dd:df:9a:d6:58:2d:28:cb:6d:c4:
09:9a:2f:3f:3d:9d:74:ee:f8:f7:15:14:f5:b8:68:
92:92:a6:d8:d7:16:ff:72:c8:e6:5e:a2:0b:81:e5:
e3:e6:e9:b3:bf:bf:65:35:64:e1:bb:10:2d:dc:c1:
50:d0:43:4e:e7:21:27:1b:f8:c9:37:e3:3d:73:e6:
93:be:79:dd:1f:e5:66:54:28:5d:95:15:73:96:99:
b4:ec:73:c4:9d:81:36:f3:38:ab:65:7c:22:af:91:
73:4f:ea:9a:cc:88:1c:0e:ef:ca:61:90:60:79:c8:
56
P:
00:f0:29:42:20:f5:53:7f:a7:a9:9a:c1:29:b2:bc:
3d:52:a8:1b:59:f8:27:eb:ac:39:f8:2e:86:8e:df:
9a:5e:08:65:c4:1c:00:c0:82:4c:24:60:c7:f7:ae:
bc:e7:18:46:6a:e4:c2:b6:d5:af:d3:68:6c:c3:95:
ff:11:27:54:05:f4:9d:79:4d:a4:59:69:4e:ad:c0:
b8:f0:dd:85:df:95:c0:fe:a5:74:7d:a8:ef:82:88:
c1:07:79:48:69:fe:a4:54:bb:a5:2e:b1:71:c2:71:
6b:7b:5b:54:56:b8:3e:de:30:a5:96:44:60:3d:fd:
82:b5:a2:99:2b:9b:dc:8d:c4:27:d4:f7:e4:bc:13:
5e:f7:44:cd:73:20:dd:cc:46:eb:96:18:1c:b8:51:
68:f5:a0:ff:8f:a4:ec:92:1a:78:52:6b:52:65:bc:
23:36:aa:df:8c:9c:d1:62:bd:26:98:cd:d4:eb:5a:
9c:59:7f:87:d1:bd:93:96:f6:f4:8a:67:9f:47:75:
a2:c4:4c:af:04:59:fb:0b:b1:78:4d:c5:59:9d:e5:
9c:ac:8d:cd:ff:9d:b4:cf:7b:c4:db:4b:69:7c:52:
41:eb:74:f1:4e:ce:ed:e5:2c:45:f3:e0:20:58:19:
14:16:de:5f:8b:2e:63:30:a1:bd:50:bc:d0:c2:e2:
95:57
G: 2 (0x2)
Observe that both the prime and the generator are the same as in the given parameters file.
The prime generated with the previous commands is a safe prime (i.e., is has the form p=2q+1, where q is also prime). This option makes the parameter generation slow and also impacts the performance of the public key operations for these parameters, without a real security improvement
You can use a faster generation following the X9.42 specification (see RFC2631 for more details), in which p=kq+1 and the prime q can be smaller (e.g., 224 bits long).
In this case, the name of the algorithm in the
openssl
call must be
dhx
instead of
dh
.
Then the corresponding is
$ openssl genpkey -genparam -algorithm dhx -text
with an output like
-----BEGIN X9.42 DH PARAMETERS-----
MIICTAKCAQEA95H6n1jzWhkdiR9gmG8M4W1sxoObc/uFT5r7D5lYTS6hz60AkBQ+
JKpHzZ54TRJOHHMH5NmTOmLHM2yOqnTFphw0PlZVUvgPveOQhzf8subnKvuGQOon
0FuVc/RrTUCUbhRKpuhkBKOrhcpluvxsairoojyWwzFFwoOs6EHYI25K6pIWRDbI
/GZuGT5cjrvy2/XGJY2oaLsWZ5oxJQoF1mIDtYOEBZdeaV9U79vAc2f8CW59f0D+
Y6P8M3SmHMn2S5t61/mBodG/C00qhq/EWrvybnYgbG31rTUdtls7MjZB1KNjMutq
mOlvkJa0vcv8ms3vJaVdKhDNzNVVpzx68QKCAQBBUOa0qoS5QAfIvvvqx+4niyuz
g09TdOFZclKUcWm3sPEbrTydI66Sads9mX6pJYD8DVVbUa3+JGQxKMREZpoquo5I
cAn4Vj7CPSuVPDCY78UULrIh6PLX22O25SCCppAKdI0NSYcAso7GRwOmPfPxHCGx
HXBD8xOZE2gUD5FeMzhEEeQ3BInGSRBSfbks7ffilVtYFUf/ARrgujyZoVZNzWE8
5Z6H5i/wIL/xMaIVWZyi0jgfFwWtqutp6Qlkpm4IaW/kwbRdRZ50Eq29ZYv3rkUy
av1t1z5n7/F1uZ6MDJSArcbJ7Cm4bvCYA7QgcthNmzq9QzplvNxKfxvwqL4zAh0A
7wGNSMzf9JPprvmH3jqzItqBuSiQ/u7eHJv6QTAiAx0A2VFUJIRfH/nt0AqCRGTU
YNC8naOJCWKVJ8Y7cQIBNA==
-----END X9.42 DH PARAMETERS-----
DH Parameters: (2048 bit)
P:
00:f7:91:fa:9f:58:f3:5a:19:1d:89:1f:60:98:6f:
0c:e1:6d:6c:c6:83:9b:73:fb:85:4f:9a:fb:0f:99:
58:4d:2e:a1:cf:ad:00:90:14:3e:24:aa:47:cd:9e:
78:4d:12:4e:1c:73:07:e4:d9:93:3a:62:c7:33:6c:
8e:aa:74:c5:a6:1c:34:3e:56:55:52:f8:0f:bd:e3:
90:87:37:fc:b2:e6:e7:2a:fb:86:40:ea:27:d0:5b:
95:73:f4:6b:4d:40:94:6e:14:4a:a6:e8:64:04:a3:
ab:85:ca:65:ba:fc:6c:6a:2a:e8:a2:3c:96:c3:31:
45:c2:83:ac:e8:41:d8:23:6e:4a:ea:92:16:44:36:
c8:fc:66:6e:19:3e:5c:8e:bb:f2:db:f5:c6:25:8d:
a8:68:bb:16:67:9a:31:25:0a:05:d6:62:03:b5:83:
84:05:97:5e:69:5f:54:ef:db:c0:73:67:fc:09:6e:
7d:7f:40:fe:63:a3:fc:33:74:a6:1c:c9:f6:4b:9b:
7a:d7:f9:81:a1:d1:bf:0b:4d:2a:86:af:c4:5a:bb:
f2:6e:76:20:6c:6d:f5:ad:35:1d:b6:5b:3b:32:36:
41:d4:a3:63:32:eb:6a:98:e9:6f:90:96:b4:bd:cb:
fc:9a:cd:ef:25:a5:5d:2a:10:cd:cc:d5:55:a7:3c:
7a:f1
Q:
00:ef:01:8d:48:cc:df:f4:93:e9:ae:f9:87:de:3a:
b3:22:da:81:b9:28:90:fe:ee:de:1c:9b:fa:41
G:
41:50:e6:b4:aa:84:b9:40:07:c8:be:fb:ea:c7:ee:
27:8b:2b:b3:83:4f:53:74:e1:59:72:52:94:71:69:
b7:b0:f1:1b:ad:3c:9d:23:ae:92:69:db:3d:99:7e:
a9:25:80:fc:0d:55:5b:51:ad:fe:24:64:31:28:c4:
44:66:9a:2a:ba:8e:48:70:09:f8:56:3e:c2:3d:2b:
95:3c:30:98:ef:c5:14:2e:b2:21:e8:f2:d7:db:63:
b6:e5:20:82:a6:90:0a:74:8d:0d:49:87:00:b2:8e:
c6:47:03:a6:3d:f3:f1:1c:21:b1:1d:70:43:f3:13:
99:13:68:14:0f:91:5e:33:38:44:11:e4:37:04:89:
c6:49:10:52:7d:b9:2c:ed:f7:e2:95:5b:58:15:47:
ff:01:1a:e0:ba:3c:99:a1:56:4d:cd:61:3c:e5:9e:
87:e6:2f:f0:20:bf:f1:31:a2:15:59:9c:a2:d2:38:
1f:17:05:ad:aa:eb:69:e9:09:64:a6:6e:08:69:6f:
e4:c1:b4:5d:45:9e:74:12:ad:bd:65:8b:f7:ae:45:
32:6a:fd:6d:d7:3e:67:ef:f1:75:b9:9e:8c:0c:94:
80:ad:c6:c9:ec:29:b8:6e:f0:98:03:b4:20:72:d8:
4d:9b:3a:bd:43:3a:65:bc:dc:4a:7f:1b:f0:a8:be:
33
SEED:
d9:51:54:24:84:5f:1f:f9:ed:d0:0a:82:44:64:d4:
60:d0:bc:9d:a3:89:09:62:95:27:c6:3b:71
pcounter: 52
h: 2
You can also custom the prime sizes with the two options
dh_paramgen_prime_len
and
dh_paramgen_subprime_len
, as for example
$ openssl genpkey -genparam -algorithm dhx -pkeyopt dh_paramgen_prime_len:1024 \
$ -pkeyopt dh_paramgen_subprime_len:160 -text
Valid values for
dh_paramgen_subprime_len
are 160, 224 and 256.
You can also use any of the three standarized DH groups (see RFC5114, sections 2.1, 2.2, 2.3) with the option
-pkeyopt dh_rfc5114:
value, where value is one of 1, 2 or 3, as in the example
$ openssl genpkey -genparam -algorithm dhx -pkeyopt dh_rfc5114:3 -text
Observe that the algorithm name for this option must also be
dhx
.
When using one of these groups predefined in RFC5114, there is no need to store the parameters in a file. Thus, we can directly generate a keypair in a single call. For example, using the first group in RFC5114, we can build the following keyfile:
$ openssl genpkey -algorithm dhx -text -pkeyopt dh_rfc5114:1
DH Private-Key: (1024 bit)
private-key:
3d:0f:71:1e:47:44:b2:e1:b7:37:50:01:ea:34:c5:
a5:93:91:71:7f
public-key:
7e:ee:7b:7e:7f:83:c8:5e:68:1c:6b:6e:43:49:11:
4f:c3:1d:9a:8c:6e:3c:62:68:d6:fd:ff:06:bc:39:
21:4f:ec:5a:64:a4:ed:16:6e:1f:07:e4:e6:83:31:
79:e8:07:8b:61:e0:07:ce:33:12:0b:ec:d9:5a:51:
0e:62:1c:68:c7:f4:01:53:f8:5b:b1:0f:2d:aa:31:
1e:39:50:85:83:ff:76:b1:93:f7:67:e5:5c:af:36:
6a:e7:bf:78:b1:6e:1d:d3:dc:95:60:b5:9f:a1:d0:
14:ea:b7:eb:a6:3c:be:31:2d:90:b6:e6:2a:c8:f9:
08:43:4e:c4:fc:59:c4:1e
GROUP: dh_1024_160
Observe that the public parameters are not explicitly included in the file, but only the reference to
dh_1024_160
is given.
The elliptic curve version of Diffie-Hellman key generation is very similar, but it currently supports only known (standarized) elliptic curve groups (that is, you cannot use
openssl
to generate new random elliptic curves with the required security properties).
In order to create the parameters file for one of the preimplemented elliptic curve groups (e.g.,
P-256
, or equivalently,
prime256v1
), you simply use
$ openssl genpkey -genparam -algorithm ec -pkeyopt ec_paramgen_curve:P-256 -pkeyopt \
$ ec_param_enc:named_curve -text
producing the output
-----BEGIN EC PARAMETERS----- BggqhkjOPQMBBw== -----END EC PARAMETERS----- EC-Parameters: (256 bit) ASN1 OID: prime256v1 NIST CURVE: P-256
You can also generate the explicit values of the parameters providing the value
explicit
to the parameter
ec_param_enc
, like in
$ openssl genpkey -genparam -algorithm ec -pkeyopt ec_paramgen_curve:P-256 -pkeyopt \
$ ec_param_enc:explicit -text
and the output is now
-----BEGIN EC PARAMETERS-----
MIH3AgEBMCwGByqGSM49AQECIQD/////AAAAAQAAAAAAAAAAAAAAAP//////////
/////zBbBCD/////AAAAAQAAAAAAAAAAAAAAAP///////////////AQgWsY12Ko6
k+ez671VdpiGvGUdBrDMU7D2O848PifSYEsDFQDEnTYIhucEk2pmeOETnSa3gZ9+
kARBBGsX0fLhLEJH+Lzm5WOkQPJ3A32BLeszoPShOUXYmMKWT+NC4v4af5uO5+tK
fA+eFivOM1drMV7Oy7ZAaDe/UfUCIQD/////AAAAAP//////////vOb6racXnoTz
ucrC/GMlUQIBAQ==
-----END EC PARAMETERS-----
EC-Parameters: (256 bit)
Field Type: prime-field
Prime:
00:ff:ff:ff:ff:00:00:00:01:00:00:00:00:00:00:
00:00:00:00:00:00:ff:ff:ff:ff:ff:ff:ff:ff:ff:
ff:ff:ff
A:
00:ff:ff:ff:ff:00:00:00:01:00:00:00:00:00:00:
00:00:00:00:00:00:ff:ff:ff:ff:ff:ff:ff:ff:ff:
ff:ff:fc
B:
5a:c6:35:d8:aa:3a:93:e7:b3:eb:bd:55:76:98:86:
bc:65:1d:06:b0:cc:53:b0:f6:3b:ce:3c:3e:27:d2:
60:4b
Generator (uncompressed):
04:6b:17:d1:f2:e1:2c:42:47:f8:bc:e6:e5:63:a4:
40:f2:77:03:7d:81:2d:eb:33:a0:f4:a1:39:45:d8:
98:c2:96:4f:e3:42:e2:fe:1a:7f:9b:8e:e7:eb:4a:
7c:0f:9e:16:2b:ce:33:57:6b:31:5e:ce:cb:b6:40:
68:37:bf:51:f5
Order:
00:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:ff:ff:
ff:ff:bc:e6:fa:ad:a7:17:9e:84:f3:b9:ca:c2:fc:
63:25:51
Cofactor: 1 (0x1)
Seed:
c4:9d:36:08:86:e7:04:93:6a:66:78:e1:13:9d:26:
b7:81:9f:7e:90
where you can see the values of the prime defining the finite field, the coefficients a,b of the curve, the generator (both the x- and y-coordinates of the point are packed into a single string), the order or size q of the generated group, and other parameters (cofactor and seed).
You can obtain a list of implemented elliptic curves with
$ openssl ecparam -list_curves
Finally, the generation of a keypair from a given parameters file (e.g.,
P-128_ecgroup.pem
) is exactly as above:
$ openssl genpkey -paramfile P-128_ecgroup.pem -text
producing the output
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgohhdkTqmahz8bwgh
BbDhmVyaTT4K+f4qatP6/oF8pb+hRANCAAQhmFI+84JDC+eHPmsbDl7qjZlAFDHM
9263g2FZjEs/zZ5W8T6ipYhu+krsX+j8/our09tWrV+5V0L1jkQtcPOb
-----END PRIVATE KEY-----
Private-Key: (256 bit)
priv:
00:a2:18:5d:91:3a:a6:6a:1c:fc:6f:08:21:05:b0:
e1:99:5c:9a:4d:3e:0a:f9:fe:2a:6a:d3:fa:fe:81:
7c:a5:bf
pub:
04:21:98:52:3e:f3:82:43:0b:e7:87:3e:6b:1b:0e:
5e:ea:8d:99:40:14:31:cc:f7:6e:b7:83:61:59:8c:
4b:3f:cd:9e:56:f1:3e:a2:a5:88:6e:fa:4a:ec:5f:
e8:fc:fe:8b:ab:d3:db:56:ad:5f:b9:57:42:f5:8e:
44:2d:70:f3:9b
ASN1 OID: prime256v1
NIST CURVE: P-256
where the secret key is an integer modulo the size of the group q, and the public key is a point in the elliptic curve (again, the two coordinates of the point are packed into a single string).
As all elliptic curves accepted by OpenSSL are indeed predefined curves, you can also skip the public parameters file generation and directly produce a keyfile with
$ openssl genpkey -algorithm ec -pkeyopt ec_paramgen_curve:P-256 -text
In the previous examples you can see the need of packing different mathematical objects together in a single file, and this requires the use of some formatting rules. Along with the human readable text output, OpenSSL uses a printable compressed format PEM and a binary format DER to store keys, ciphertext, signatures and certificates, among other binary objects.
The PEM format is a printable version (using the Base64 printable encoding) of the binary DER format, with additional headers and footers, like for instance:
-----BEGIN PRIVATE KEY-----
...
(base64 encoded binary DER content)
...
-----END PRIVATE KEY-----
DER format is basically an unambiguous way to pack a sequence of objects, and each individual object has three parts: type specification, length of the data, and the data itself.
For instance, an integer is encoded by as a byte sequence starting with the type identifier
0x02
followed by the number of bytes used in the binary representation of the integer, and then the binary representation itself.
The predefined types in DER include booleans, integers, bit strings, octet strings among other types, and aggregations of them.
You can use the command
asn1parse
of
openssl
to look inside a DER or a PEM file and to retrieve all individual entities stored into them.
In some
openssl
commands the user can choose the specific output format (DER or PEM) to store keys, ciphertexts, certificates and other binary objects. For instance, the option
-outform
format, where format is one of
der
or
pem
, used in conjunction with
openssl genpkey
selects the format used to store the generated keypair.
The previous commands show how to generate public / secret keypairs and store them into files. However, in the public key cryptography setting, public keys must be transmitted without revealing the corresponding secret keys. In OpenSSL one can extract the public part of the generated keypair and store it into a separate file. The command
$ openssl pkey -in private.pem -pubout -out public.pem
reads the keypair from the file
private.pem
, probably generated with
openssl genpkey
, and extracts and stores the public key into the file
public.pem
. Default input and output formats are PEM, but you can specify DER format in either input or output files with the options
-inform der
and
-outform der
.
Now, the resulting public key can be used in encryption or in signature verification, while the private key file is required for decryption and for signature generation.
Private key files can be generated in a protected way, by encrypting them with a symmetric key encryption scheme in the same call to
openssl genpkey
. See the
openssl
documentation for more details.
Form the keypairs generated as explained in the previous section one can perform public key encryption and decryption.
For the (plain) RSA public key encryption scheme the use of OpenSSL in the command line is quite easy, with the
openssl pkeyutl
command used in conjunction with the
-encrypt
and
-decrypt
options.
The main problem is that a public key encryption only allows encrypting messages with a very precise format (e.g., in RSA a message must be the binary encoding of an integer between 1 and n-1, where n is the public modulus). This means that, in practice, we would need a padding scheme, and possibly a chaining mode for long messages.
From a practical point of view, public key encryption schemes are only used to encrypt ephemeral keys to be used in symmetric encryption primitives (like encryption or MAC). Thus, in OpenSSL you can use
$ openssl pkeyutl -pubin -inkey myrsapubkey.pem -in ephemeralkey.bin -encrypt -pkeyopt \
$ rsa_padding_mode:oaep -out ciphertext.bin
to encrypt the short file
ephemeralkey.bin
with the RSA key contained in
myrsapubkey.pem
using a specific padding scheme like OAEP (see the documentation of OpenSSL for the implemented RSA padding algorithms), and store the encrypted data in
ciphertext.bin
.
There exist a maximum length for the message to be encrypted (the maximum length could be smaller than the length of n, because the padding string takes some minimal space).
Normally, short messages can be encrypted successfully, except if you specify
-pkeyopt rsa_padding_mode:none
, in which only messages with exactly the same binary length of n, and not greater than n as an integer, can be encrypted.
Decryption is performed in a similar way (you also have to specify the same padding scheme used in encryption), but now you provide the private key instead of the public one, and use the option
-decrypt
instead of
-encrypt
.
$ openssl pkeyutl -inkey myrsaprivkey.pem -in ciphertext.bin -decrypt -pkeyopt \
$ rsa_padding_mode:oaep -out decrypted.bin
The generation of the common key in the Diffie-Hellman Key Agreement requires one secret key (say, Alice's secret key) and one public key (sat, Bob's public key).
Given the files (generated as above)
alice_priv.pem
and
bob_publ.pem
, Alice can generate the common secret with
$ openssl pkeyutl -inkey alice_priv.pem -peerkey bob_publ.pem -derive -out common.bin
Similarly, Bob can execute
$ openssl pkeyutl -inkey bob_priv.pem -peerkey alice_publ.pem -derive -out common.bin
to obtain the same result.
According to the specification of the Diffie-Hellman Key Agreement protocol, the two keypairs must be produced with the same group (i.e., the same parameters file). If the group corresponds to the normal (i.e., non elliptic curve based) Diffie-Hellman Agreement, then the common secret is the binary representation of gsAsB, where sA and sB are the secret keys of the two parties, and g is the group generator. Otherwise, in the elliptic curve based protocol, the common secret is the binary representation of the x-coordinate of the point (sAsB)G, where G is the base point (generator) of the subgroup.
The common secret must never be directly used as a symmetric key. Instead, it must be hashed or transformed with a secure key derivation function. For instance, you can pipe the previous generation commands and the hash computation with
$ openssl pkeyutl -inkey alice_priv.pem -peerkey bob_publ.pem -derive | openssl dgst \
$ -sha256 -binary > commonkey.bin
which produces a secure shared 256 bit symmetric key, ready to be used with any encryption or MAC operation.
In this practical exercise you will implement a hybrid encryption scheme consisting of the combination of a version of Hashed ElGamal encryption, a symmetric encryption scheme and a MAC.
Namely, you will use a normal Diffie-Hellman key exchange, with a group size of 256 bits. The common secret resulting from a Diffie-Hellman key agreement is 256 bits long. Then, the hash function SHA256 is applied to the common secret to obtain a 256 bits symmetric key, that is split into two 128 bits keys: one, k1, for AES-128-CBC encryption and the other, k2, for SHA256-HMAC.
At system setup, all parties willing to exchange encrypted messages must agree on a particular DH public parameters file. In this lab the third group in RFC5114 will be used.
Any party can generate the public parameters file with
$ openssl genpkey -genparam -algorithm dhx -pkeyopt dh_rfc5114:3 -out param.pem
Before encrypting a file, the recipient (say Alice) must have been generated a long-term Diffie-Hellman keypair, and then she must have published the corresponding public key. Namely, the recipient needs to perform the following steps:
Generate the long-term keypair with
$ openssl genpkey -paramfile param.pem -out alice_pkey.pem
Extract the long-term public key with
$ openssl pkey -in alice_pkey.pem -pubout -out alice_pubkey.pem
Publish the files
param.pem
and
alice_pubkey.pem
. In real life, she would need to obtain a certificate for this public key form a certification authority to prevent impersonation attacks, but we will ignore this part in the lab in order to focus on the encryption and decryption operations.
Now, the encryption operation run by the sender (say Bob) consists of:
Compute an ephemeral Diffie-Hellman keypair r,a=gr with
openssl genpkey
using the file
param.pem
published by Alice, and store it in the file
ephpkey.pem
.
Extract the corresponding ephemeral public key file (in PEM format) with
openssl pkey
and store it in the file
ephpubkey.pem
.
Derive a common secret from the secret ephemeral key r, contained in
ephpkey.pem
, and Alice's long-term public key, contained in
alice_pubkey.pem
, with
openssl pkeyutl
with the
-derive
option.
Apply SHA256 to the common secret with
openssl dgst
(see the previous practical work), and split it into two halves to obtain k1 and k2.
Starting from the 32 bytes long binary file with the hash value, you can use
head -c 16
and
tail -c 16
to extract the first and the last 16 bytes.
Encrypt the desired file with AES-128-CBC using key k1, with
openssl enc -aes-128-cbc
and store the result in the file
ciphertext.bin
(see previous labs).
Some useful tools helps converting binary files into the plain hexadecimal representation, like
xxd -p
.
You would need to provide an iv for the encryption operation.
You can generate a random one with
openssl rand 16
and store it in the file
iv.bin
.
Use key k2 to compute the SHA256-HMAC tag of the concatenation of
iv.bin
and
ciphertext.bin
with
openssl dgst -hmac -sha256
to obtain the binary file
tag.bin
(again, you can find the details in previous labs).
The final ciphertext consists of the four files
ephpubkey.pem
,
iv.bin
,
ciphertext.bin
and
tag.bin
.
Ideally, a single file in PEM or DER format joining the previous four files would be a better option.
You can do that by concatenating the printable (base64 encoded) files with adequate headers and footers.
For instance, you can start from the file
ephpubkey.pem
that already is in PEM format, then concatenate it with the base64 encoding of
ciphertext.bin
,
iv.bin
and
tag.bin
with some PEM style headers and footers added:
(put here the file ephpubkey.pem as it is) (it already contains its own header and footer lines) -----BEGIN AES-128-CBC IV----- (put here the 64bit encoding of file iv.bin) -----END AES-128-CBC IV----- -----BEGIN AES-128-CBC CIPHERTEXT----- (put here the 64bit encoding of file ciphertext.bin) -----END AES-128-CBC CIPHERTEXT----- -----BEGIN SHA256-HMAC TAG----- (put here the 64bit encoding of file tag.bin) -----END SHA256-HMAC TAG-----
To convert files between binary and base64 encoding you can use the special OpenSSL pseudocipher in
openssl enc
with the
-a
option.
In the encryption direction the input is interpreted as a binary file and the output is the corresponding printable base64 encoding.
In the decryption direction (with the
-d
option), the conversion is done in the opposite way.
Decryption can be performed with a similar procedure:
Parse the ciphertext file and obtain the four components (undoing the base64 encoding when necessary)
ephpubkey.pem
,
iv.bin
,
ciphertext.bin
and
tag.bin
.
Use files
alice_pkey.pem
and
ephpubkey.pem
to recover the common secret with
openssl pkeyutl -derive
.
Apply SHA256 to the previous result and split the value into the two keys k1 and k2.
Recompute the SHA256-HMAC from the concatenation of the files
iv.bin
and
ciphertext.bin
using the key k2.
If the result is different from the file
tag.bin
, then abort the decryption operation and report the error.
Use
openssl enc -d -aes-128-cbc
with the key k1 and the iv given in
iv.bin
to decrypt the file
ciphertext.bin
and recover the plaintext.
As a result you would provide three scripts: one for parameter and key generation, another for encryption and a third one for decryption.
You can test your scripts at different levels:
Locally: You can generate your own keys, encryptions and decryptions, and they should behave consistently, i.e., with successful authentications. However, this tests do not guarantee that you implemented the system properly, but only than the three scripts are consistent.
Externally: You can test your scripts against files generated by others. Namely, given a secret key and a ciphertext your decryption script must be able to successfully recover the message without any authentication error. This test ensures some degree of compatibility of your implementation and the reference implementation used to generate the external supplied files.
Final test: If the two previous requirements are fulfiled, then you can probably encrypt a message with an external public key and the recipient must be able to successfully recover the message with the corresponding secret key.
To perform these tests (specially the two last ones) you must use the auxiliary files (keys and ciphertext) available on the subject webpage.