Protecting The Cybersecurity Crown Jewels

There have been a number of recent hacks — including Solar Winds — which has involved an intruder discovering the private key used to sign…

Photo by Gvantsa Javakhishvili on Unsplash

Protecting The Cybersecurity Crown Jewels: Encrypting The Private Key

It does no good to create a 2,048-bit RSA key pair for your systems, and then protect it with “Qwerty123”

There have been a number of recent hacks — including Solar Winds — which has involved an intruder discovering the private key used to sign software, and then inserting a back-door into the software. When updates are then pushed out, the software update is seen as being trust worthy, as it has been signed by the private key of the software company, and proven with their public key.

Along with this, the loss of a private key could result in an intruder gaining access to a public cloud infrastructure or even to a private GitHub (as SSH authentication with the private key is often used). The access to the private key can also allow a company to be impersonated, and to setup trusted fake sites (as the private key will prove the validity of the web site).

The protection of the private key is thus important, and it should never be stored in an unprotected format. This private key is part of a key pair and is typically an RSA or an ECC key. The private key is used to sign data, and the public key then proves it, or a public key is used to encrypt data, and then the private can decrypt it:

With RSA, we create two prime numbers (p and q), and then compute:

N=pq

And then select e and d. Our public key is:

Pub=(e,N)

and private key:

Priv=(d,N)

If we have a message of M, the encrypted ciphertext value is:

Enc=M^e (mod N)

and we decrypt with:

Dec=Enc^d (mod N)

We normally select e as 65,537, and then determine d

to solve:

e×d(mod(p−1)(q−1))=1

Using OpenSSL to generate and protect the private key

For a keypair, we can use a symmetric key to protect the private key and generate this symmetric key from a password. The symmetric key methods are: 3DES, 128-bit AES, 192-bit AES and 256-bit AES. For a 512-bit RSA key pair with a password of “test” and with 256-bit AES encryption, we generate the command [here]:

openssl genrsa -aes256 -passout pass:test 512

And the result is:

-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIBvTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQI/68wiptiTW8CAggA
MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBC5Mfsi1O8/ssBXKVs+rBdfBIIB
YKlVoguwKJabQfKTpWQ6ZOhUszkoDnA+NNNkKxc4+9yKCTD6THxxkEXv6oY9uFxi
j83PJIcXS1q3bPntdgUKcZdwjpy1jiKYwH8dkvWwKH5WcrRhd003CiFumZC0zBu3
A89Nn+OlP2iFEKSQGlWllXoHhA0OcQX/mWgRPMlZzHCtF0Zl0AhumL56nq+c34+U
WJrHxpVSa3yl18uJqWuTF27ZybTzKPknA8TKiarqtOinQLD4ktCu5Acoawxf3fYz
og9SxvYPAbX3eMNxdasSA6vjOSOJ6Py+gX2TBluFe2dL3YTCvUP1ibWLLIrpV/rN
79JhSE0xBGnJY+awu5U/8xsoHatzkuPZRqFPJwtOFfJn9VSHCXPmEEj3kZd6TUbz
Hz742oEQCNrzQjWJKDptGw77SHkZgvWzwY5if3eZzvMPsT9ztsSAgGoOur+AOac1
fJ8raR/4sanN4lNni6spVdw=
-----END ENCRYPTED PRIVATE KEY-----

and then reveal with:

openssl rsa -passout pass:test -text

and which gives:

Private-Key: (512 bit, 2 primes)
modulus:
00:aa:ed:d7:e9:ce:cc:fc:3f:42:4c:61:76:58:3d:
7b:f6:f0:df:b0:6e:f1:e4:a0:3b:75:2c:fd:ee:45:
22:b1:a2:8b:bb:bb:cf:a7:26:16:9e:e0:b2:db:e0:
de:44:87:62:9e:6f:78:07:cc:2b:d9:8b:fc:a8:7e:
5b:db:a6:bd:23
publicExponent: 65537 (0x10001)
privateExponent:
00:97:46:dc:fa:ae:ee:38:a9:7b:f1:c1:a8:4d:bc:
4c:c4:66:b6:72:9e:1e:33:ab:a4:33:b6:58:1e:d2:
cd:3b:cc:1f:65:ce:29:5f:46:dd:68:d8:54:ac:d1:
4c:9a:dc:d8:25:fd:70:7f:05:aa:32:21:ad:a4:2f:
a6:b9:23:0a:31
prime1:
00:dd:5d:19:cf:78:03:84:ab:70:3d:51:fc:9b:bc:
a7:a7:44:9d:5b:38:70:f6:61:a3:8c:cd:dc:de:0e:
fe:aa:27
prime2:
00:c5:ac:8b:5a:81:e1:84:d3:77:d0:7b:26:73:0b:
76:f4:d4:97:a7:f8:54:f1:e7:c0:0b:56:9f:38:01:
e9:9e:a5
exponent1:
23:28:8b:55:e9:60:dd:ac:81:0a:2c:40:6b:d7:dd:
e4:f2:3f:ef:e2:1a:06:f7:e1:0b:17:13:52:6d:9d:
43:17
exponent2:
3c:de:08:7a:f2:0b:53:2f:1a:71:a3:ba:0f:2a:b4:
92:66:f3:db:d0:e7:b7:25:39:49:44:7e:fa:6b:fc:
57:d1
coefficient:
3e:9a:cd:a5:2c:ec:8a:76:0d:1d:6b:75:4a:68:a8:
6e:98:16:10:70:c5:20:52:d1:97:43:7a:11:2b:a3:
7d:ac
-----BEGIN PRIVATE KEY-----
MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqu3X6c7M/D9CTGF2
WD179vDfsG7x5KA7dSz97kUisaKLu7vPpyYWnuCy2+DeRIdinm94B8wr2Yv8qH5b
26a9IwIDAQABAkEAl0bc+q7uOKl78cGoTbxMxGa2cp4eM6ukM7ZYHtLNO8wfZc4p
X0bdaNhUrNFMmtzYJf1wfwWqMiGtpC+muSMKMQIhAN1dGc94A4SrcD1R/Ju8p6dE
nVs4cPZho4zN3N4O/qonAiEAxayLWoHhhNN30Hsmcwt29NSXp/hU8efAC1afOAHp
nqUCICMoi1XpYN2sgQosQGvX3eTyP+/iGgb34QsXE1JtnUMXAiA83gh68gtTLxpx
o7oPKrSSZvPb0Oe3JTlJRH76a/xX0QIgPprNpSzsinYNHWt1SmiobpgWEHDFIFLR
l0N6ESujfaw=
-----END PRIVATE KEY-----

In the example above privateExponent is d, the publicExponent is e, prime 1 is p, prime 2 is q, modulus is N. Notice, that the prime numbers are 256-bits long, and that the modulus is 512-bits long. So, if we say we have 512-bit RSA, then this is created with two 256-bit prime numbers. Overall, in production, we need at least 2048-bit RSA, and so we need prime numbers that are at least 1,024-bit prime numbers.

The code is here:

https://asecuritysite.com/openssl/rsa_keygen2

Conclusions

It is fairly easy to run OpenSSL and try lots of passwords. If we use a weak password, it can be fairly easy to crack the private key. Thus, make sure you use a password with a high entropy value, otherwise, your random keys will be easily broken.

And, if you can, store your private key in a HSM (Hardware Storage Module), and/or on a physical storage device which is not connected to the Internet.