BCFKS creation using cert and key - bouncycastle

How can I create BCFKS if I have to store client cert.pem and key.pem in it?
The command I'm using is:
keytool -import -alias 3 -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -providerpath /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.141-2.6.10.5.el7.x86_64/jre/lib/ext/bc-fips-1.0.1.jar -storepass test123 -storetype BCFKS -keystore bcfipsKeyStore-1.bcfks -file cert-kmipclient.der
but with this I can only store the certificate not it's key. Also this command is hanging in my REDHat machine. It worked few times but most of the time it is hanging and not returning anything.

You can use this for generate different keys and also BCFKS:
#!/usr/bin/env bash
set -x
# Certificates password.
PASS=123456
# Server.
SERVER_DN="CN=localhost,OU=RC,O=RC,L=Los Angelest,S=CA,C=US"
# Client.
CLIENT_DN="CN=www.localhost.com,OU=RC,O=RC,L=Los Angelest,S=CA,C=US"
# Cleanup.
rm -vf node.*
rm -vf client.*
rm -vf wc.*
rm -vf ca.*
rm -vf in*
rm -vf seri*
rm -vf trust*
rm -vf *pem
rm -vf *cnf
rm -vf *conf
# ca key config.
cat << EOF > ca_key.conf
[req]
prompt = no
distinguished_name = dn
req_extensions = req_ext
[ dn ]
countryName = US
stateOrProvinceName = CA
localityName = Los Angelest
organizationName = localhost
commonName = localhost
organizationalUnitName = localhost
emailAddress = localhost#localhost.com
[ req_ext ]
subjectAltName = #alt_names
[ alt_names ]
DNS.1 = localhost
EOF
# ca configuration file
cat << EOF > ca.cnf
[ ca ]
default_ca = CertificateAuthority
[ CertificateAuthority ]
certificate = ./ca.pem
database = ./index.txt
private_key = ./ca.key
new_certs_dir = ./
default_md = sha1
policy = policy_match
serial = ./serial
default_days = 365
[policy_match]
commonName = supplied
EOF
# webconsole configuration file
cat << EOF > wc.conf
[req]
prompt = no
distinguished_name = dn
req_extensions = req_ext
[ dn ]
countryName = US
stateOrProvinceName = CA
localityName = Los Angelest
organizationName = localhost
commonName = localhost
organizationalUnitName = localhost
emailAddress = localhost#localhost.com
[ req_ext ]
subjectAltName = #alt_names
[ alt_names ]
DNS.1 = localhost
IP.1 = 127.0.0.1
EOF
touch index.txt
echo 01 > serial
# Generate CA
openssl req -new -newkey rsa:2048 -nodes -config ca_key.conf -out ca.csr -keyout ca.key
openssl x509 -trustout -signkey ca.key -req -in ca.csr -out ca.pem
keytool -deststorepass ${PASS} -noprompt -import -file ca.pem -alias CertificateAuthority -keystore trust.jks
# Generate node certificates
keytool -genkey -keyalg RSA -keysize 2048 -alias node -deststorepass ${PASS} -keystore node.jks -noprompt \
-dname ${SERVER_DN} \
-storepass ${PASS} \
-keypass ${PASS}
keytool -deststorepass ${PASS} -certreq -alias node -file node.csr -keystore node.jks
openssl ca -batch -config ca.cnf -out node.pem -infiles node.csr
keytool -deststorepass ${PASS} -import -alias ca -keystore node.jks -file ca.pem -noprompt
keytool -deststorepass ${PASS} -import -alias node -keystore node.jks -file node.pem -noprompt
keytool -importkeystore -srcstoretype JKS -deststoretype PKCS12 -srckeystore node.jks -destkeystore node.p12 -srcstorepass ${PASS} -deststorepass ${PASS} -srcalias node -destalias node -noprompt
openssl pkcs12 -in node.p12 -out ca_odbc.pem -passin pass:${PASS} -nodes
# Generate Client cerificates
keytool -genkey -keyalg RSA -keysize 2048 -alias client -deststorepass ${PASS} -keystore client.jks -noprompt \
-dname ${CLIENT_DN} \
-storepass ${PASS} \
-keypass ${PASS}
keytool -deststorepass ${PASS} -certreq -alias client -file client.csr -keystore client.jks
openssl ca -batch -config ca.cnf -out client.pem -infiles client.csr
keytool -deststorepass ${PASS} -import -alias ca -keystore client.jks -file ca.pem -noprompt
keytool -deststorepass ${PASS} -import -alias client -keystore client.jks -file client.pem -noprompt
keytool -importkeystore -srcstoretype JKS -deststoretype PKCS12 -srckeystore client.jks -destkeystore client.p12 -srcstorepass ${PASS} -deststorepass ${PASS} -srcalias client -destalias client -noprompt
openssl pkcs12 -in client.p12 -out client.pem -passin pass:${PASS} -nodes
# Generate web console cerificates
openssl genrsa -des3 -passout pass:${PASS} -out wc.key 1024
openssl req -new -passin pass:${PASS} -key wc.key -config wc.conf -out wc.csr
openssl x509 -req -days 365 -in wc.csr -CA ca.pem -CAkey ca.key -set_serial 01 -extensions req_ext -extfile wc.conf -out wc.crt
openssl pkcs12 -export -in wc.crt -inkey wc.key -passin pass:${PASS} -certfile wc.crt -out wc.p12 -passout pass:${PASS}
keytool -importkeystore -srckeystore wc.p12 -srcstoretype PKCS12 -destkeystore wc.jks -deststoretype JKS -noprompt -srcstorepass ${PASS} -deststorepass ${PASS}
# Convert java keystore format from jks to bcfks
keytool -importkeystore -srckeystore node.jks -srcstoretype JKS -srcstorepass ${PASS} \
-destkeystore node.bcfks -deststorepass ${PASS} -deststoretype BCFKS -providername BCFIPS \
-provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -providerpath bc-fips-1.0.2.jar
keytool -importkeystore -srckeystore trust.jks -srcstoretype JKS -srcstorepass ${PASS} \
-destkeystore trust.bcfks -deststorepass ${PASS} -deststoretype BCFKS -providername BCFIPS \
-provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -providerpath bc-fips-1.0.2.jar

Related

Extract private key from PFX file which doesn't contain certificate using Bouncy Castle

Here is my scenario:
Using the following openssl command to generate the pfx file which doesn't contains cert:
openssl.exe genrsa -aes256 -out E:\Temp\test.pem -passout pass:123456 2048 2
openssl.exe pkcs12 -keypbe PBE-SHA1-3DES -aes256 -export -nocerts -inkey E:\Temp\test.pem -out E:\Temp\test.pfx -passin pass:123456 -passout pass:123456
I am trying to parse the key out of the pfx file using bouncy castle. here is the simple code:
string psw = "123456";
string pfxPath = #"E:\Temp\test.pfx";
using (Stream stream = File.Open(pfxPath, FileMode.Open))
{
Pkcs12Store pkcs = new Pkcs12StoreBuilder().Build();
pkcs.Load(stream, psw.ToArray());
}
However, pkcs is empty. I think it is because the PFX file doesn't have a certificate. So my question is: is there a way that bouncy castle can handle this situation?

Pass certificates into requests lib

I have https server written on Python which uses self singed certs:
server_cert = 'certs/server/server.crt'
server_key = 'certs/server/server.key'
client_certs = 'certs/client/client.crt'
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.verify_mode = ssl.CERT_REQUIRED
context.load_cert_chain(certfile=server_cert, keyfile=server_key)
context.load_verify_locations(cafile=client_certs)
Steps to certs generate:
openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=localhost/UID=testnotifier" -keyout ${certs}/server/server.key -out ${certs}/server/server.crt
openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=localhost/UID=testnotifier" -keyout ${certs}/client/client.key -out ${certs}/client/client.crt
Also I have https client:
#!/usr/bin/python3
import socket
import ssl
host_addr = '127.0.0.1'
host_port = 8082
server_sni_hostname = 'localhost'
server_cert = 'certs/server/server.crt'
client_cert = 'certs/client/client.crt'
client_key = 'certs/client/client.key'
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH, cafile=server_cert)
context.load_cert_chain(certfile=client_cert, keyfile=client_key)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn = context.wrap_socket(s, server_side=False, server_hostname=server_sni_hostname)
conn.connect((host_addr, host_port))
conn.send(b"Hello, world!")
conn.close()
This works, but I want to send different requests to some path, e.g. /rest/v1/fill.
So, I decided to use requests or urllib3 lib.
I'm trying to pass certificates to this libs
https = urllib3.PoolManager(cert_file=client_cert, cert_reqs='CERT_REQUIRED', ca_certs=server_cert, key_file=client_key)
https.request('GET', 'https://localhost:8082/rest/v1/fill')
but client hangs with both of libs:
/home/marat/.local/lib/python3.6/site-packages/urllib3/connection.py:362: SubjectAltNameWarning: Certificate for localhost has no `subjectAltName`, falling back to check for a `commonName` for now. This feature is being removed by major browsers and deprecated by RFC 2818. (See https://github.com/shazow/urllib3/issues/497 for details.)
SubjectAltNameWarning
^CTraceback (most recent call last):
File "/home/marat/.local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 377, in _make_request
httplib_response = conn.getresponse(buffering=True)
TypeError: getresponse() got an unexpected keyword argument 'buffering'
server's output:
Client connected: 127.0.0.1:40026
SSL established. Peer: {'subject': ((('countryName', 'US'),), (('stateOrProvinceName', 'Denial'),), (('localityName', 'Springfield'),), (('organizationName', 'Dis'),), (('commonName', 'localhost'),), (('userId', 'testnotifier'),)), 'issuer': ((('countryName', 'US'),), (('stateOrProvinceName', 'Denial'),), (('localityName', 'Springfield'),), (('organizationName', 'Dis'),), (('commonName', 'localhost'),), (('userId', 'testnotifier'),)), 'version': 3, 'serialNumber': '88F15B15B2D1ABE7', 'notBefore': 'Jun 5 11:35:38 2019 GMT', 'notAfter': 'Jun 4 11:35:38 2020 GMT'}
Received: b'GET / HTTP/1.1\r\nHost: localhost:8082\r\nAccept-Encoding: identity\r\n\r\n'
Closing connection
I would like to know how to pass certificates so that the client works as in the first version (with socket/ssl).
I worked incorrectly with certificates.
So, bash script for generate certificates:
generate_test_certs() {
echo "Generate test certs"
mkdir -p ${SCRIPT_PATH}/test/certs/{server,client,root}
local certs=${SCRIPT_PATH}/test/certs
local CN=localhost # common name
cat <<EOF > ${certs}/openssl.cnf
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = #alt_names
[alt_names]
DNS.1 = ${CN}
EOF
# Create root key
openssl genrsa -out ${certs}/root/rootCA.key 2048
openssl req -new -x509 -days 3650 -key ${certs}/root/rootCA.key -out ${certs}/root/rootCA.crt \
-subj "/C=US/ST=Denial/L=Springfield/O=Qwerty Inc./OU=Qwerty Operations/CN=Qwerty Root"
# Generate sign request
openssl req -new -newkey rsa:2048 -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=${CN}/UID=testnotifier" \
-keyout ${certs}/server/server.key -nodes -out ${certs}/server/server.csr
# Sign CSR by ROOT CA certificate
openssl x509 -req -days 3650 -in ${certs}/server/server.csr -CA ${certs}/root/rootCA.crt \
-CAkey ${certs}/root/rootCA.key -set_serial 01 -out ${certs}/server/server.crt \
-extfile ${certs}/openssl.cnf
# Generate client certificate
openssl req -new -newkey rsa:2048 -nodes -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=${CN}/UID=testnotifier" \
-keyout ${certs}/client/client.key -out ${certs}/client/client.csr
openssl x509 -req -days 3650 -in ${certs}/client/client.csr -CA ${certs}/root/rootCA.crt -CAkey ${certs}/root/rootCA.key \
-set_serial 01 -out ${certs}/client/client.crt
}
Nginx config for example:
server {
listen 451 ssl;
server_name tester;
ssl_certificate ../../../test/certs/server/server.crt;
ssl_certificate_key ../../../test/certs/server/server.key;
ssl_client_certificate ../../../test/certs/root/rootCA.crt;
ssl_verify_client optional;
ssl_verify_depth 3;
include ../../../conf/tester.rules.conf;
}
And finally python client
#!/usr/bin/python3
import requests
root_ca = 'certs/root/rootCA.crt'
client_cert = 'certs/client/client.crt'
client_key = 'certs/client/client.key'
resp = requests.get('https://localhost:451/qwe/rty',
cert=(client_cert, client_key), verify=root_ca)
print(resp.status_code)
print(resp.content)

I have .pem privatekey and .der encrypted file. I want to decrypt using nodejs

I have used the following commands to generate the encrypted file "Example.txt.der".
openssl genrsa -out privatekey.pem 2048
openssl req -new -sha256 -key privatekey.pem -out csr.csr
openssl req -x509 -sha256 -days 365 -key privatekey.pem -in csr.csr -out certificate.pem
openssl smime -encrypt -aes-256-cbc -binary -in Example.txt -outform DER -out Example.txt.der certificate.pem
I want to decrypt "Example.txt.der" using : privatekey.pem.
Try the below command:
openssl smime -decrypt -in Example.txt.der -inform DER -inkey privatekey.pem -out DecryptedExample.txt
It works using exec command.
const exec = require('child_process').exec; exec('openssl smime -decrypt -in ./encryptedConfig.txt -inkey ./privatekey.pem', (error, stdout, stderr) => { if (error) { console.log("error:",error); reject(error); } else { console.log("Config decrypt completed. Data: ",stdout); resolve(stdout); }

Certificate SSL_ERROR_BAD_CERT_DOMAIN for localhost / 127.0.0.1

I am creating a local app that starts a webserver in the localhost:8080 address. I am trying to create a certificate for it so that I can access it using HTTPS, but I am having a hard time doing this.
First I created my own CA and then I created a certificate with the localhost:8080 common name. Then I added my CA to the trusted authorities on my computer (I am using Windows 10 by the way), however when I opened my site I got the BAD_CERT_DOMAIN error using Firefox and Chrome.
I also tried to created another certificate using 127.0.0.1:8080 as the common name, but it also didn't work.
What I am doing wrong? Do these browsers always reject certificates with localhost as the CN?
UPDATE
I created a configuration file like this:
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = req_ext
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name (full name)
localityName = Locality Name (eg, city)
organizationName = Organization Name (eg, company)
commonName = Common Name (e.g. server FQDN or YOUR name)
[ req_ext ]
subjectAltName = #alt_names
[ alt_names ]
DNS.1 = localhost
DNS.2 = localhost:8080
DNS.3 = localhost:12125
DNS.4 = localhost:12126
DNS.5 = 127.0.0.1:8080
DNS.6 = 127.0.0.1:12125
DNS.7 = 127.0.0.1:12126
DNS.8 = 127.0.0.1
IP.1 = 127.0.0.1
And these are the commands that I am using to generate my certificate:
Sign request: openssl req -out myrequest.csr -newkey rsa:2048 -nodes -keyout mykey.key -config myconfig.conf
When I ran this command, the CN = localhost 127.0.0.1
Signining with my CA: openssl x509 -req -in myrequest.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out mycertificate.crt -days 36500 -sha256
However I am still getting the BAD_CERT_DOMAIN for both Firefox and Google Chrome, even after I tell them to trust my own CA.
I have followed #jww's advice and I re-wrote my config file as this:
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = req_ext
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name (full name)
localityName = Locality Name (eg, city)
organizationName = Organization Name (eg, company)
commonName = Common Name (e.g. server FQDN or YOUR name)
[ req_ext ]
subjectAltName = #alt_names
[ alt_names ]
DNS.1 = localhost
IP.1 = 127.0.0.1
Then I used this commands to generate my certificate.
Sign request: openssl req -out myrequest.csr -newkey rsa:2048 -nodes -keyout mykey.key -config myconfig.conf
Signining with my CA: openssl x509 -req -in myrequest.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out mycertificate.crt -days 36500 -sha256
So the problem really was that I was adding the port numbers to the IP and DNS addresses of my certificate sign request.

140568388757144:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:701:Expecting: ANY PRIVATE KEY [duplicate]

During my search, I found several ways of signing a SSL Certificate Signing Request:
Using the x509 module:
openssl x509 -req -days 360 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
Using the ca module:
openssl ca -cert ca.crt -keyfile ca.key -in server.csr -out server.crt
Note: I am unsure of the use of the right parameters for this one. Please advise correct usage if I am to use it.
What way should one use to sign certificate requests with your Certification Authority?
Is one method better than the other (for example, one being deprecated)?
1. Using the x509 module
openssl x509 ...
...
2 Using the ca module
openssl ca ...
...
You are missing the prelude to those commands.
This is a two-step process. First you set up your CA, and then you sign an end entity certificate (a.k.a server or user). Both of the two commands elide the two steps into one. And both assume you have a an OpenSSL configuration file already setup for both CAs and Server (end entity) certificates.
First, create a basic configuration file:
$ touch openssl-ca.cnf
Then, add the following to it:
HOME = .
RANDFILE = $ENV::HOME/.rnd
####################################################################
[ ca ]
default_ca = CA_default # The default ca section
[ CA_default ]
default_days = 365 # How long to certify for
default_crl_days = 30 # How long before next CRL
default_md = sha256 # Use public key default MD
preserve = no # Keep passed DN ordering
x509_extensions = ca_extensions # The extensions to add to the cert
email_in_dn = no # Don't concat the email in the DN
copy_extensions = copy # Required to copy SANs from CSR to cert
####################################################################
[ req ]
default_bits = 4096
default_keyfile = cakey.pem
distinguished_name = ca_distinguished_name
x509_extensions = ca_extensions
string_mask = utf8only
####################################################################
[ ca_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = US
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Maryland
localityName = Locality Name (eg, city)
localityName_default = Baltimore
organizationName = Organization Name (eg, company)
organizationName_default = Test CA, Limited
organizationalUnitName = Organizational Unit (eg, division)
organizationalUnitName_default = Server Research Department
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default = Test CA
emailAddress = Email Address
emailAddress_default = test#example.com
####################################################################
[ ca_extensions ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer
basicConstraints = critical, CA:true
keyUsage = keyCertSign, cRLSign
The fields above are taken from a more complex openssl.cnf (you can find it in /usr/lib/openssl.cnf), but I think they are the essentials for creating the CA certificate and private key.
Tweak the fields above to suit your taste. The defaults save you the time from entering the same information while experimenting with configuration file and command options.
I omitted the CRL-relevant stuff, but your CA operations should have them. See openssl.cnf and the related crl_ext section.
Then, execute the following. The -nodes omits the password or passphrase so you can examine the certificate. It's a really bad idea to omit the password or passphrase.
$ openssl req -x509 -config openssl-ca.cnf -days 365 -newkey rsa:4096 -sha256 -nodes -out cacert.pem -outform PEM
After the command executes, cacert.pem will be your certificate for CA operations, and cakey.pem will be the private key. Recall the private key does not have a password or passphrase.
You can dump the certificate with the following.
$ openssl x509 -in cacert.pem -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 11485830970703032316 (0x9f65de69ceef2ffc)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=MD, L=Baltimore, CN=Test CA/emailAddress=test#example.com
Validity
Not Before: Jan 24 14:24:11 2014 GMT
Not After : Feb 23 14:24:11 2014 GMT
Subject: C=US, ST=MD, L=Baltimore, CN=Test CA/emailAddress=test#example.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
Modulus:
00:b1:7f:29:be:78:02:b8:56:54:2d:2c:ec:ff:6d:
...
39:f9:1e:52:cb:8e:bf:8b:9e:a6:93:e1:22:09:8b:
59:05:9f
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
4A:9A:F3:10:9E:D7:CF:54:79:DE:46:75:7A:B0:D0:C1:0F:CF:C1:8A
X509v3 Authority Key Identifier:
keyid:4A:9A:F3:10:9E:D7:CF:54:79:DE:46:75:7A:B0:D0:C1:0F:CF:C1:8A
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Key Usage:
Certificate Sign, CRL Sign
Signature Algorithm: sha256WithRSAEncryption
4a:6f:1f:ac:fd:fb:1e:a4:6d:08:eb:f5:af:f6:1e:48:a5:c7:
...
cd:c6:ac:30:f9:15:83:41:c1:d1:20:fa:85:e7:4f:35:8f:b5:
38:ff:fd:55:68:2c:3e:37
And test its purpose with the following (don't worry about the Any Purpose: Yes; see "critical,CA:FALSE" but "Any Purpose CA : Yes").
$ openssl x509 -purpose -in cacert.pem -inform PEM
Certificate purposes:
SSL client : No
SSL client CA : Yes
SSL server : No
SSL server CA : Yes
Netscape SSL server : No
Netscape SSL server CA : Yes
S/MIME signing : No
S/MIME signing CA : Yes
S/MIME encryption : No
S/MIME encryption CA : Yes
CRL signing : Yes
CRL signing CA : Yes
Any Purpose : Yes
Any Purpose CA : Yes
OCSP helper : Yes
OCSP helper CA : Yes
Time Stamp signing : No
Time Stamp signing CA : Yes
-----BEGIN CERTIFICATE-----
MIIFpTCCA42gAwIBAgIJAJ9l3mnO7y/8MA0GCSqGSIb3DQEBCwUAMGExCzAJBgNV
...
aQUtFrV4hpmJUaQZ7ySr/RjCb4KYkQpTkOtKJOU1Ic3GrDD5FYNBwdEg+oXnTzWP
tTj//VVoLD43
-----END CERTIFICATE-----
For part two, I'm going to create another configuration file that's easily digestible. First, touch the openssl-server.cnf (you can make one of these for user certificates also).
$ touch openssl-server.cnf
Then open it, and add the following.
HOME = .
RANDFILE = $ENV::HOME/.rnd
####################################################################
[ req ]
default_bits = 2048
default_keyfile = serverkey.pem
distinguished_name = server_distinguished_name
req_extensions = server_req_extensions
string_mask = utf8only
####################################################################
[ server_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = US
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = MD
localityName = Locality Name (eg, city)
localityName_default = Baltimore
organizationName = Organization Name (eg, company)
organizationName_default = Test Server, Limited
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default = Test Server
emailAddress = Email Address
emailAddress_default = test#example.com
####################################################################
[ server_req_extensions ]
subjectKeyIdentifier = hash
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
subjectAltName = #alternate_names
nsComment = "OpenSSL Generated Certificate"
####################################################################
[ alternate_names ]
DNS.1 = example.com
DNS.2 = www.example.com
DNS.3 = mail.example.com
DNS.4 = ftp.example.com
If you are developing and need to use your workstation as a server, then you may need to do the following for Chrome. Otherwise Chrome may complain a Common Name is invalid (ERR_CERT_COMMON_NAME_INVALID). I'm not sure what the relationship is between an IP address in the SAN and a CN in this instance.
# IPv4 localhost
IP.1 = 127.0.0.1
# IPv6 localhost
IP.2 = ::1
Then, create the server certificate request. Be sure to omit -x509*. Adding -x509 will create a certificate, and not a request.
$ openssl req -config openssl-server.cnf -newkey rsa:2048 -sha256 -nodes -out servercert.csr -outform PEM
After this command executes, you will have a request in servercert.csr and a private key in serverkey.pem.
And you can inspect it again.
$ openssl req -text -noout -verify -in servercert.csr
Certificate:
verify OK
Certificate Request:
Version: 0 (0x0)
Subject: C=US, ST=MD, L=Baltimore, CN=Test Server/emailAddress=test#example.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:ce:3d:58:7f:a0:59:92:aa:7c:a0:82:dc:c9:6d:
...
f9:5e:0c:ba:84:eb:27:0d:d9:e7:22:5d:fe:e5:51:
86:e1
Exponent: 65537 (0x10001)
Attributes:
Requested Extensions:
X509v3 Subject Key Identifier:
1F:09:EF:79:9A:73:36:C1:80:52:60:2D:03:53:C7:B6:BD:63:3B:61
X509v3 Basic Constraints:
CA:FALSE
X509v3 Key Usage:
Digital Signature, Key Encipherment
X509v3 Subject Alternative Name:
DNS:example.com, DNS:www.example.com, DNS:mail.example.com, DNS:ftp.example.com
Netscape Comment:
OpenSSL Generated Certificate
Signature Algorithm: sha256WithRSAEncryption
6d:e8:d3:85:b3:88:d4:1a:80:9e:67:0d:37:46:db:4d:9a:81:
...
76:6a:22:0a:41:45:1f:e2:d6:e4:8f:a1:ca:de:e5:69:98:88:
a9:63:d0:a7
Next, you have to sign it with your CA.
You are almost ready to sign the server's certificate by your CA. The CA's openssl-ca.cnf needs two more sections before issuing the command.
First, open openssl-ca.cnf and add the following two sections.
####################################################################
[ signing_policy ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
####################################################################
[ signing_req ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
Second, add the following to the [ CA_default ] section of openssl-ca.cnf. I left them out earlier, because they can complicate things (they were unused at the time). Now you'll see how they are used, so hopefully they will make sense.
base_dir = .
certificate = $base_dir/cacert.pem # The CA certifcate
private_key = $base_dir/cakey.pem # The CA private key
new_certs_dir = $base_dir # Location for new certs after signing
database = $base_dir/index.txt # Database index file
serial = $base_dir/serial.txt # The current serial number
unique_subject = no # Set to 'no' to allow creation of
# several certificates with same subject.
Third, touch index.txt and serial.txt:
$ touch index.txt
$ echo '01' > serial.txt
Then, perform the following:
$ openssl ca -config openssl-ca.cnf -policy signing_policy -extensions signing_req -out servercert.pem -infiles servercert.csr
You should see similar to the following:
Using configuration from openssl-ca.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName :PRINTABLE:'US'
stateOrProvinceName :ASN.1 12:'MD'
localityName :ASN.1 12:'Baltimore'
commonName :ASN.1 12:'Test CA'
emailAddress :IA5STRING:'test#example.com'
Certificate is to be certified until Oct 20 16:12:39 2016 GMT (1000 days)
Sign the certificate? [y/n]:Y
1 out of 1 certificate requests certified, commit? [y/n]Y
Write out database with 1 new entries
Data Base Updated
After the command executes, you will have a freshly minted server certificate in servercert.pem. The private key was created earlier and is available in serverkey.pem.
Finally, you can inspect your freshly minted certificate with the following:
$ openssl x509 -in servercert.pem -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 9 (0x9)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=MD, L=Baltimore, CN=Test CA/emailAddress=test#example.com
Validity
Not Before: Jan 24 19:07:36 2014 GMT
Not After : Oct 20 19:07:36 2016 GMT
Subject: C=US, ST=MD, L=Baltimore, CN=Test Server
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:ce:3d:58:7f:a0:59:92:aa:7c:a0:82:dc:c9:6d:
...
f9:5e:0c:ba:84:eb:27:0d:d9:e7:22:5d:fe:e5:51:
86:e1
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
1F:09:EF:79:9A:73:36:C1:80:52:60:2D:03:53:C7:B6:BD:63:3B:61
X509v3 Authority Key Identifier:
keyid:42:15:F2:CA:9C:B1:BB:F5:4C:2C:66:27:DA:6D:2E:5F:BA:0F:C5:9E
X509v3 Basic Constraints:
CA:FALSE
X509v3 Key Usage:
Digital Signature, Key Encipherment
X509v3 Subject Alternative Name:
DNS:example.com, DNS:www.example.com, DNS:mail.example.com, DNS:ftp.example.com
Netscape Comment:
OpenSSL Generated Certificate
Signature Algorithm: sha256WithRSAEncryption
b1:40:f6:34:f4:38:c8:57:d4:b6:08:f7:e2:71:12:6b:0e:4a:
...
45:71:06:a9:86:b6:0f:6d:8d:e1:c5:97:8d:fd:59:43:e9:3c:
56:a5:eb:c8:7e:9f:6b:7a
Earlier, you added the following to CA_default: copy_extensions = copy. This copies extension provided by the person making the request.
If you omit copy_extensions = copy, then your server certificate will lack the Subject Alternate Names (SANs) like www.example.com and mail.example.com.
If you use copy_extensions = copy, but don't look over the request, then the requester might be able to trick you into signing something like a subordinate root (rather than a server or user certificate). Which means he/she will be able to mint certificates that chain back to your trusted root. Be sure to verify the request with openssl req -verify before signing.
If you omit unique_subject or set it to yes, then you will only be allowed to create one certificate under the subject's distinguished name.
unique_subject = yes # Set to 'no' to allow creation of
# several ctificates with same subject.
Trying to create a second certificate while experimenting will result in the following when signing your server's certificate with the CA's private key:
Sign the certificate? [y/n]:Y
failed to update database
TXT_DB error number 2
So unique_subject = no is perfect for testing.
If you want to ensure the Organizational Name is consistent between self-signed CAs, Subordinate CA and End-Entity certificates, then add the following to your CA configuration files:
[ policy_match ]
organizationName = match
If you want to allow the Organizational Name to change, then use:
[ policy_match ]
organizationName = supplied
There are other rules concerning the handling of DNS names in X.509/PKIX certificates. Refer to these documents for the rules:
RFC 5280, Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile
RFC 6125, Representation and Verification of Domain-Based Application Service Identity within Internet Public Key Infrastructure Using X.509 (PKIX) Certificates in the Context of Transport Layer Security (TLS)
RFC 6797, Appendix A, HTTP Strict Transport Security (HSTS)
RFC 7469, Public Key Pinning Extension for HTTP
CA/Browser Forum Baseline Requirements
CA/Browser Forum Extended Validation Guidelines
RFC 6797 and RFC 7469 are listed, because they are more restrictive than the other RFCs and CA/B documents. RFC's 6797 and 7469 do not allow an IP address, either.
In addition to answer of #jww, I would like to say that the configuration in openssl-ca.cnf,
default_days = 1000 # How long to certify for
defines the default number of days the certificate signed by this root-ca will be valid. To set the validity of root-ca itself you should use '-days n' option in:
openssl req -x509 -days 3000 -config openssl-ca.cnf -newkey rsa:4096 -sha256 -nodes -out cacert.pem -outform PEM
Failing to do so, your root-ca will be valid for only the default one month and any certificate signed by this root CA will also have validity of one month.
Sometimes, such as for testing, you just want a simplistic means of generating a signed certificate, without setting up a full-blown CA configuration. This is possible using just the openssl req and openssl x509 commands. You would never use this method for production certificates, but since it is useful for some non-production situations, here are the commands.
Generate a self-signed signing certificate
First, create a self-signed certificate that will be used as the root of trust:
openssl req -x509 -days 365 -key ca_private_key.pem -out ca_cert.pem
Or equivalently, if you want to generate a private key and a self-signed certificate in a single command:
openssl req -x509 -days 365 -newkey rsa:4096 -keyout ca_private_key.pem -out ca_cert.pem
Generate a certificate request
Next, create a certificate request for the certificate to be signed:
openssl req -new -key my_private_key.pem -out my_cert_req.pem
Again, you may generate the private key and the request simultaneously, if needed:
openssl req -new -newkey rsa:4096 -keyout my_private_key.pem -out my_cert_req.pem
Generate a signed certificate
Finally, use the self-signed signing certificate to generate a signed certificate from the certificate request:
openssl x509 -req -in my_cert_req.pem -days 365 -CA ca_cert.pem -CAkey ca_private_key.pem -CAcreateserial -out my_signed_cert.pem
I've found a convenient script sscg for this task - https://github.com/sgallagher/sscg
Here is an example for Fedora linux:
Installation:
sudo yum install sscg
Example:
sscg \
--ca-key-password-prompt \
--lifetime=3650 \
--country=XX \
--state=myState \
--locality=myCity \
--organization=myOrg \
--organizational-unit=myUnit \
--email=myemail#example.com \
--hostname=foo.example.com \
--subject-alt-name=*.example.com \
--ca-key-file=CA.key \
--ca-file=CA.pem \
--cert-key-file=foo.example.com.key \
--cert-file=foo.example.com.pem

Resources