Currently there are three public key algorithm in popular. RSA public key
DSA Public key
and ECDSA Public key
.
openssl provides ways to generate those different public keys in command line
RSA stands for Rivest, Shamir and Adelman
, which is most popular public-key algorithm, it could be used for key-exchange (encrypt data) and sign data. since rsa used for key-exchange, the compromise of a private key can be used to decrypt any previously traffic, it is recommended to use perfect forward secrecy
afforded by Diffe-Hellman key exchange.
Algorithm
There exists two numbers e
and d
which could make for a given m
public key
is composed with e and n
private key
is componsed with d and n, for rsa private key (PEM),e is also included.
openssl sub commands
openssl genrsa
: gen rsa private key
openssl rsa
: handle with rsa keys
The following commands could be used to generate a RSA private key in PEM format. this PEM format is in RSA Private key format which contains the public key modulus.
openssl genrsa -out rsa_priv.pem 2048
to check the content of the key.pem
file. the -noout
flag indicates not output the private key content. from the output, we can see this pem file contains both private key and public key.
openssl rsa -text -in rsa_priv.pem -noout
===
output:
version Version,
modulus INTEGER, -- n
publicExponent INTEGER, -- e
privateExponent INTEGER, -- d
prime1 INTEGER, -- p
prime2 INTEGER, -- q
exponent1 INTEGER, -- d mod (p-1)
exponent2 INTEGER, -- d mod (q-1)
coefficient INTEGER, -- (inverse of q) mod p
otherPrimeInfos OtherPrimeInfos OPTIONAL
to retrieve the rsa public key from the key.pem out, we can issue
openssl rsa -in rsa_priv.pem -pubout -out rsa_pub.pem
to check the public key content,we can issue
openssl rsa -text -pubin -in rsa_pub.pem -noout
==
output:
modulus INTEGER, -- n
publicExponent INTEGER -- e
To check if two key file are related, we can check the n modulus
contains in the key file is equals or not
openssl rsa -pubin -in rsa_pub.pem -modulus -noout | openssl md5
openssl rsa -in rsa_priv.pem -modulus -noout | openssl md5
The above rsa_pub.pem is pure public key, which could not be used as certification, to use certification, we need to create x509 public key (aka certificate)
DSA: Digital Signature Algorithm
Algorithm
For given three numbers g, p and q, there are a pair of number x and y, which could make
q is generated by g and p.
public key
: y
private key
: x
Openssl sub commands
openssl dsaparam
: gen dsa params.
openssl gendsa
: gen dsa private key
openssl dsa
: handle with dsa keys
The following command is used to generate dsa public key. as the above algorithm, dsa need a param which composed with g,p and q, so to generate dsa public/private key, we need first generate the dsa params.
Generate dsaparam dsa_param.pem
openssl dsaparam -out dsa_param.pem 1024
we can see the content of dsa_param.pem
openssl dsaparam -in dsa_param.pem -text -noout
==
output
P: xxx
Q: xxx
G: xxx
Use dsa_param.pem
to generate dsa key: dsa_priv.pem
openssl gendsa dsa_param.pem -out dsa_priv.pem
we can check the contenxt of dsa_priv.pem, we can see the dsa private key contains both private and public
key, samilar with rsa keys
openssl dsa -in dsa_priv.pem -text -noout -modulus
==
output
priv:
pub:
P:
Q:
G:
Alternately, The above two steps could be combine together using -genkey
of dsaparam
openssl dsaparam -genkey -out dsa_priv.pem
Extract public key from dsa private key
openssl dsa -in dsa_priv.pem -pubout -out dsa_pub.pem
check the content
openssl dsa -pubin -in dsa_pub.pem -text -noout
==
output
pub:
P:
Q:
G:
Relay on the ellipic curve division (ECD). ECDSA keys are much smaller than RSA and DSA, and ECDSA predefined a list of params which could be used to generate keys.
openssl ecparam
: handle ecparam and gen ec private keys.
openssl ec
: handle with ec keys
Get list of predefined ec param
openssl ecparam -list_curves
==
output
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
...
we could rely on those params to create ec params short name, choose prime192v2
from above
openssl ecparam -name prime192v2 -out ecparam.pem
Check the content
openssl ecparam -in ecparam.pem -text
==
ASN1 OID: prime192v1
NIST CURVE: P-192
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBAQ==
-----END EC PARAMETERS-----
Alternately, same with rsa, we can directly generate the private key by providing the params name
openssl ecparam -name prime192v2 -genkey -noout -out ec_key.pem
Then we can use the ec param created above to create ec private key. the ec_key.pem like rsa and dsa key, are composed with params, public and private key.
openssl ecparam -in ecparam.pem -genkey -noout -out ec_key.pem
extra contenxt
openssl ec -in ec_key.pem -text -noout
==
result
priv:
pub:
ASN1 OID:
NIST CURVE:
extract the public key from private key
openssl ec -in ec_key.pem -pubout -out ec_pub.pem
openssl ec -pubin -in ec_pub.pem -text -noout
==
pub:
ASN1 OID:
NIST CURVE:
reference: matching a private key to a public key
The above private key and public key are pure private/public key, which could not be treated as x509 certificate. x509 certificate is composed with two parts
- public key
- User identify
and x509 certificate could be signed by own private key or by ca private key. if it is signed by its own private key, it is a self-signed certificate, if it signed by CA, it is CA signed certification
see the picture below:
The following is details description and steps using openssl to handle x509 certification. Some description for the openssl command
-
openssl x509
Certification display and signing utility, reference: openssl x509
Options:
-req
: by default,x509
expect the certificate as input, if-req
is added, csr is expected as input.-signkey
: cause the input file be signed using supplied private key. -
openssl req
Certification request and generating utility, reference: openssl req
-x509
: by default, the req output is csr, if-x509
is added, the outpus is a self signed certification.-new
: generates a new csr, promt the user for relevant filed values. if-key
is not provided, it will generate the private key using the specified configuration file.-key
: read the private key-newkey
: generate csr and new private key together. supportrsa:<length>
,dsa:<dsaparam>
andec:<length>
-out
: by default, the certification key will print in standout if -out is not privided.-pubout
: By default public key is not print in standout, if-pubout
, print the public key to standout.-keyout
: by default, private key is named asprivkey.pem
, using this option can rename the private key file.
Generate x509 self-signed certificate
- generate rsa self-signed certificate using existing private key.
if private key exists, generate a self-signed x509 certification using promoted information.
openssl req -x509 -new -key rsa_priv.pem -out rsa_cert.pem
we could check the rsa_cert.pem
openssl x509 -in rsa_cert.pem -noout -text
==
Certificate:
Data:
Version: 3 (0x2) . # x509 verisons, support v1,v2 and v3
Serial Number:
ff:0a:ff:45:8a:4b:6d:5e . # this is the unique id
Signature Algorithm: sha256WithRSAEncryption . # algorithm used to generate the signauture
Issuer: C=CN, ST=BJ, L=BJ, O=IBM, OU=IBM, CN=tao/[email protected] ## who issue the certificate
Validity # date validity
Not Before: Jul 3 09:26:21 2019 GMT
Not After : Aug 2 09:26:21 2019 GMT
Subject: C=CN, ST=BJ, L=BJ, O=IBM, OU=IBM, CN=tao/[email protected] . ## user name
Subject Public Key Info: ## public key info
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
xxxxxxxxx
Exponent: 65537 (0x10001)
X509v3 extensions: ## v3 extensions
X509v3 Subject Key Identifier:
D2:60:47:AA:89:3F:21:F3:5C:38:BC:27:A1:43:74:AA:19:BE:08:3F
X509v3 Authority Key Identifier:
keyid:D2:60:47:AA:89:3F:21:F3:5C:38:BC:27:A1:43:74:AA:19:BE:08:3F
X509v3 Basic Constraints:
CA:TRUE
Signature Algorithm: sha256WithRSAEncryption . ## the signature for the who
xxxxxxx
- generate ecdsa certificate
openssl req -x509 -new -key ec_key.pem -out ec_cert1.pem
check the key
openssl x509 -in ec_cert1.pem -text
==
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
d5:01:27:dc:50:18:07:5c
Signature Algorithm: ecdsa-with-SHA256
Issuer: C=AU, ST=AU, L=AU, O=AU, OU=AU, CN=AU/emailAddress=AU
Validity
Not Before: Jul 3 10:07:38 2019 GMT
Not After : Aug 2 10:07:38 2019 GMT
Subject: C=AU, ST=AU, L=AU, O=AU, OU=AU, CN=AU/emailAddress=AU
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (192 bit)
pub:
xxx
ASN1 OID: prime192v1
NIST CURVE: P-192
X509v3 extensions:
X509v3 Subject Key Identifier:
5E:1E:DB:B4:6A:DA:EB:67:99:77:38:50:7E:39:B9:41:2C:95:62:27
X509v3 Authority Key Identifier:
keyid:5E:1E:DB:B4:6A:DA:EB:67:99:77:38:50:7E:39:B9:41:2C:95:62:27
X509v3 Basic Constraints:
CA:TRUE
Signature Algorithm: ecdsa-with-SHA256
xxx
- generate dsa certificate
openssl req -x509 -new -key dsa_priv.pem -out dsa_cert.pem
openssl x509 -in dsa_cert.pem -text -noout
output
==
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
8a:83:12:ea:5f:08:50:9f
Signature Algorithm: dsa_with_SHA256
Issuer: C=CN, ST=BJ, L=BJ, O=IBM, OU=IBM, CN=tao/[email protected]
Validity
Not Before: Jul 3 10:17:50 2019 GMT
Not After : Aug 2 10:17:50 2019 GMT
Subject: C=CN, ST=BJ, L=BJ, O=IBM, OU=IBM, CN=tao/[email protected]
Subject Public Key Info:
Public Key Algorithm: dsaEncryption
pub:
xxx
P:
xxx
Q:
xxx
G:
xxx
X509v3 extensions:
X509v3 Subject Key Identifier:
71:B7:5F:4F:EB:7C:84:67:7E:75:F2:CC:8F:6C:E5:04:A3:88:02:90
X509v3 Authority Key Identifier:
keyid:71:B7:5F:4F:EB:7C:84:67:7E:75:F2:CC:8F:6C:E5:04:A3:88:02:90
X509v3 Basic Constraints:
CA:TRUE
Signature Algorithm: dsa_with_SHA256
r:
xxx
s:
xxx
- Generate the private key and x509 self-sgined certification together
using rsa
openssl req -x509 -newkey rsa:2048 -keyout rsa_priv.pem -out rsa_cert.pem
using dsa params
openssl req -x509 -newkey dsa:dsa_param.pem -keyout dsa_priv.pem -out dsa_cert.pem
using ecdsa params
openssl req -x509 -newkey ec:ecparam.pem -keyout ec_priv.pem -out ec_cert.pem
-
Use
csr
andprivate key
to generate x509 certificateTo get the certificate signed by CA, instead of give them the private key (should not do this), we can create a csr and send to CA for sign, the result is a CA signed certificate. self-signed certification can also follow this process.
To better understand this process, we could split certificate request into two steps
-
Generate the csr based on the private key, notes there is no
-x509
, the result is csr, not certificate. the below command will promote you to input the configuration valueopenssl req -new -key rsa_priv.pem -out rsa.csr
we can also create a csr.conf file to provide those values, see create csr conf
openssl req -new -key rsa_priv.pem -out rsa.csr -conf csr.conf
-
Generate the certificate using csr and signed by the private key.
openssl x509 -req -in rsa.csr -signkey rsa_priv.pem -out rsa_cert.pem
-
Generate x509 internal CA signed certificate
For internal CA signed certification, we need CA certificate and CA private key exists to sign. ca_cert.pem
and
ca_priv.pem
.
We will generate the csr using our own private key rsa.csr
and leverage the openssl x509
to sign
`-CA`: the ca certificate file
`-CAkey`: the ca private key
```
openssl x509 -req -in rsa.csr -CA ca_crt.pem -CAkey ca_key.pem \
-CAcreateserial -out rsa_crt.pem -days 10000 \
-extensions v3_ext -extfile csr.conf
```
Generate x509 public CA-signed certificate
For extenral CA signed certification, we need send the csr generated by our private key to CA for sign. the returned is certification file in various format. notes, we need keep our private key confidential.
see the picture below
when client use browser to visit a https site, firstly, the https server will send its certification to the browser, this certification could be a self-signed certification, internal CA signed certification or public CA signed certification. A certification is combine of public key and user identity information and signatures. The browser will fisrt to verify if the hostname visited match the CN of the certification, if not, will report the unstrust warning.
Self-signed certification: if it is a self-signed certification, the client browser will report warning that the certification is not trusted. unless we install this self-signed certification into our browser and trust it.
Internal CA signed certification:
if it is a internal CA signed certification, browser will try to extract the DN of the issuer
and look for installed trusted CA, find the match CA and use the public key of that CA to verify the signature of server certification. if the server certificaiton is signed by the internal CA's private key, then verification will success.
match:
openssl x509 -in ca.crt -subject_hash
= openssl x509 -in server.crt -issuer_hash
verify:
openssl verify -CAfile ca.crt server.crt
Private Key (intenral CA) --- sign server certification (encrypt the hash) --> signature Public Key(internal CA)--- verify sign of server certification (encrypt the hash) --> signagure1
if(signature == signagure1){ success. }
Public CA signed certification: if it is public CA signed certification, similar with internal CA signed certification, will go through the CA chain to verify the signature to the root CA. if all pass, then accept the server certification.
How to difference self-signed certification and CA signed using openssl
openssl -in cert.pem -text -noout
self-signed, the issuer is same with the subject
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
b0:e9:3e:cb:df:32:ba:7f
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=CN, ST=BJ, L=BJ, O=IBM, OU=IBM, CN=TAO/[email protected]
Validity
Not Before: Jul 4 01:59:38 2019 GMT
Not After : Aug 3 01:59:38 2019 GMT
Subject: C=CN, ST=BJ, L=BJ, O=IBM, OU=IBM, CN=TAO/[email protected]
Subject Public Key Info:
CA signed, the issuer points to a different certification, different with subject
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
e1:15:46:0d:c5:eb:74:33
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=CN, ST=BJ, L=BJ, O=IBM, OU=IBM, CN=TAO/[email protected]
Validity
Not Before: Jul 4 02:55:09 2019 GMT
Not After : Nov 19 02:55:09 2046 GMT
Subject: C=CN, ST=BJ, L=BJ, O=IBM, OU=IBM, CN=*.fyre.ibm.com
Subject Public Key Info:
If clients and Server are signed by the same CA, it is easy to understand certificate of A can verify the certificate of B.
If the client and server are signed by different CA, if two CA did not know each other, A can not verify B.
So in the real word, different CA are all signed by its parent CA and back to the same root CA, and this chain is installed in the computer system to make sure the recerieved can verified each other.
There are various x509 certification file format, like PEM
, DER
, PKCS12
, PKCS7
.
PEM
and PKCS7
are use BASE64 ASCII encoding.
DER
and PKCS12
are binary files.
Different format has differnet recommended extension names, see picture below
PEM format
Most CA provides this format, extensions could be .pem,.crt,.key or .cer
. the PEM format can include the certification file, intermediate file and priviate key in one single file, or have different file for each. we can use cat
command to combine those files. certification are separate by standard separations
Certification
---- BEGIN CERTIFICATE----
----END CERTIFICATE----
Private key
---- BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----
CSR
-----BEGIN CERTIFICATE REQUEST-----
-----END CERTIFICATE REQUEST-----
Convert pem to der
openssl x509 -outform der -in ca.pem -out ca.der
Convert pem to pkcs7
openssl crl2pkcs7 -nocrl -certfile ca.pem -out ca.p7b -certfile CACert.cer
convert pem to pkcs12, we can put the private key, rootCA and ca certification file together into pkcs12
openssl pkcs12 -export -chain -in myca_crt.pem -inkey myca_priv.key -out myca.p12 -CAfile ./rootca.crt
PKCS7 format
PKCS7 is also in base64 ASCII encoding format. difference is, only certification and chain could be put in PKCS7 format, private key can not. windows and tomcat use this format.
-----BEGIN PKCS7-----
-----END PKCS7-----
convert pkcs7 to pem
openssl pkcs7 -print_certs -in ca.p7b -out ca.pem
DER format
DER format are in binary format of certification, which is mostly used in java based application.
Convert der to pem
openssl x509 -inform der -in ca.der -out ca.pem
PKCS12 format
PKCS12 format is in binary format, which can store the certification, intermediate and private key in a single p12 or pfx file with password protection.
Convert PKCS12 to pem, as PKCS12 contains multiple files, we have multiple options to print out
Extract the client ca only.
-nokey
: not create private key in pem
-clcerts
: create client certificate in pem
openssl pkcs12 -in ca.p12 -out test1.pem -clcerts -nokeys
extract the root ca certificate
openssl pkcs12 -in ca.p12 -out rootca.pem -cacerts -nokeys
extract the private key only
-nodes
: not encrypt the private key.
openssl pkcs12 -in ca.p12 -out key.pem -nocerts -nodes
JKS format
keystore
JKS is java keystore certification, which contains the certification, intermediate and private key together. the keystore could have multiple entries, each entry have a alias.
JKS is handled by java keytool
truststore
truststore contains application server's trusted certificates, include the public keys and other entities, not include the private key. for the trusted certificates, the server has confirmed that public key in the certificate belongs to the certificate owner.
keystore and truststore could be used in java base application, and could be define in JVM level by
-Djavax.net.ssl.keyStore
and -Djavax.net.ssl.trustStore
display the keystore information
keytool -list -v -keystore ${keystore.file} -storepass ${keystore.pass}
import PEM certification into keystore
keytool -import -noprompt -trustcacerts -alias ${cert.alias} -file ${cert.file} -keystore ${keystore.file} -storepass ${keystore.pass}
Export the certification and chain into pkcs7 format
keytool -export -noprompt -alias ${cert.alias} -file ${cert.file} -keystore ${keystore.file} -storepass ${keystore.pass}
check the der format cert
keytool -v -printcert -file ca.der
import the der format into java truststore
keytool -importcert -alias startssl -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit -file ca.der
check the der import
keytool -keystore "$JAVA_HOME/jre/lib/security/cacerts" -storepass changeit -list | grep startssl
Export the certification to PEM format
keytool -export -noprompt -rfc -alias ${cert.alias} -file ${cert.file} -keystore ${keystore.file} -storepass ${keystore.pass}
Delete the certification from the keystore.
keytool -delete -noprompt -alias ${cert.alias} -keystore ${keystore.file}
-storepass ${keystore.pass}
Reference: different certification file
SSH keys are not like openssl generated keys. ssh private key usually not encrypted, it depends on the filesystem permission to ensure the security. ssh usually does not relay on certifications include public key, certifications are locates in different filesystem.
generate ssh key pairs:
two file will generated, rsakey and rsakey.pub, while the second is the public key.
ssh-keygen -t rsa/dsa/ecdsa/eddsa -f rsakey
we can always use the -y
option to see the public key for a given private key.
ssh-keygenb -y -f rsakey