This documentation shows you how to create test certificates with openssl. You start with selfmade certificate-authority certificates which can be used to sign marketpartner certificates. A typical certificate-chain has the following structure: root-ca > sub-ca > marketpartner.

This guide is based on the following guide: https://jamielinux.com/docs/openssl-certificate-authority

You can find the openssl documentation here.

Overview

The Root-CA creates its key-pair. (1.2)

The Root-CA signs its certificate itself. (1.3)

The Sub-CA creates its key-pair. (2.2)

The Sub-CA creates its CSR. (2.3)

The Root-CA takes the CSR and signs the certificate of the Sub-CA. (2.4)

The marketpartner creates its key-pair. (3.2)

The marketpartner creates its CSR. (3.3)

The Sub-CA takes the CSR and signs the certificate of the marketpartner. (3.4)

Prerequesites

You have to install openssl. This can be done either with a linux-shell or with cygwin under windows.

openssl.cnf

You need the openssl.cnf and you find it in the attachment of this guide, or here. Download the file to your system.

The openssl.cnf file will be copied during the next steps. The copies will be modified by the scripts.

Directory Structure

Files (certificates, keys, …) are always stored where they are created. For example the private key of a marketpartner is created by the marketpartner and stored in marketpartner/private. The related certificate is signed by the sub-ca and stored in sub-ca/certs. Furthermore the certificate is copied to its owner.

All files will be stored in subdirectories of baseDir (compare section shell variables). There will be a subdirectory for every ca and for every marketpartner. Certificates and keys will be stored in subdirectories of these directories.

Script Structure

If you follow this guide, there is no need to change the shellscripts. You have to configure the shell-variables and execute the scripts. An expert might want to change the scripts or the openssl.cnf.

Instead all scripts are combined in gen_cert.sh or compare the attachment of this guide. If you use the combined script, you must change the global variables in the head of the script.

An updated version of all scripts is provided in Attachments B. Here the environment variables are used inside the openssl.cnf and you configure the environment variables with source subject.sh. This simplifies all processes. Furthermore the new version includes the algorithm RSA-PSS and the subject-alternative name.

Configure shell variables

Execute these commands in your shell to configure the mandatory variables:

opensslFilepath="/home/agohr/openssl.cnf"
export opensslFilepath
baseDir="/home/agohr/certs"
export baseDir
caName="skl-energy"
export caName
marketpartnerName="rsc-energy"
export marketpartnerName
count=`date '+%Y-%m-%d-%H-%M-%S'`
count="100"
export count
crlHostUrl="http://localhost:8080/sample"
export crlHostUrl
passw="b2bbp"
export passw

The values are examples.

Make sure the opensslFilepath exists.

Make sure the baseDir exists and is empty.

You have to increase the count value for every new key you generate. Thus every key and certificate has a unique name.

The variable crlHostUrl must be changed if you want to host the CRL. Compare section CRL Hosting.

The variable passw is used as password to protect the private keys. Don’t forget the password, otherwise you cannot use the private keys anymore.

We export the variables, thus we can use them inside the following scripts.

Root-CA

install (1.1)

The Root-CA will be installed into the directory $baseDir/$caName-root with the following commands:

#!/bin/bash

cd $baseDir
rootCaName=$caName-root
mkdir $rootCaName
cd $rootCaName
mkdir certs crl newcerts private
touch index.txt
echo 1000 > serial
cp $opensslFilepath ./openssl.cnf
sed -i "s|^baseDir           = .*|baseDir           = ${baseDir}|" openssl.cnf
sed -i "s/^commonNameId      = .*/commonNameId      = ${rootCaName}/" openssl.cnf
sed -i "s/^count             = .*/count             = ${count}/" openssl.cnf
sed -i 's/^policy            = policy_loose.*/policy            = policy_strict/' openssl.cnf

After executing these commands you might configure the copied file openssl.cnf: update section req_distinguished_name. These values are part of the certificates and help to identify the ca.

create private key and certificate

Increase the variable count in shell.

Create the key (1.2)

#!/bin/bash

rootCaName=$caName-root
cd $baseDir/$rootCaName
fileName=$rootCaName-$count
openssl genrsa -aes128 -passout pass:$passw -out private/$fileName.key.pem 2048

Parameter details:

  • -aes128 private key encryption algorithm
  • -passout pass:b2bbp password to protect the key is b2bbp
  • 2048 the size of the private key to generate in bits.

When you execute the command without argument passout, you have to provide a passphrase to protect the key. Don’t forget this phrase, you cannot use the key without it. The key is stored in directory ./private.

Create the certificate (1.3)

#!/bin/bash

rootCaName=$caName-root
cd $baseDir/$rootCaName
sed -i "s/^count             = .*/count             = ${count}/" openssl.cnf
fileName=$rootCaName-$count
openssl req -config openssl.cnf \
-key private/$fileName.key.pem \
-new -x509 -days 7300 -sha256 -extensions v3_ca \
-passin pass:$passw \
-subj "/C=DE/ST=NRW/L=Cologne/O=$caName/OU=$caName/CN=$fileName/emailAddress=$rootCaName@b2bbp.org" \
-out certs/$fileName.cert.pem

Parameter details:

  • -extensions this configuration is defined in openssl.cnf
  • -days 7300 the validity of the certificate
  • -passin pass:b2bbp password to open the given private key is b2bbp
  • -subj name fields to identify the owner of the certificate. Must match with sub-ca for C, ST, O.

When you execute the command without argument subj, you have to provide Country, State, Locality, Organization, Organization Unit, Common Name & Email of the root-ca. Defaults are configured via openssl.cnf in section req_distinguished_name. You must use different common names for different certificates.

The certificate is stored in directory ./certs.

Sub-CA

Precondition: root-ca key and certificate have been created.

install (2.1)

The Sub-CA will be installed into the directory $baseDir/$caName-sub with the following commands:

#!/bin/bash

subCaName=$caName-sub
cd $baseDir
mkdir $subCaName
cd $subCaName
mkdir certs crl newcerts private csr
touch index.txt
echo 1000 > serial
echo 1000 > crlnumber
cp $opensslFilepath ./openssl.cnf
sed -i "s|^baseDir           = .*|baseDir           = ${baseDir}|" openssl.cnf
sed -i "s/^commonNameId      = .*/commonNameId      = ${subCaName}/" openssl.cnf
sed -i "s/^count             = .*/count             = ${count}/" openssl.cnf
sed -i "s|^crlHostUrl        = .*|crlHostUrl        = ${crlHostUrl}|" openssl.cnf

After executing these commands you might configure the copied file openssl.cnf: update section req_distinguished_name. These values are part of the certificates and help to identify the ca.

create private key and certificate

Increase the shell-variable count.

create the key (2.2)

#!/bin/bash

subCaName=$caName-sub
cd $baseDir/$subCaName
fileName=$subCaName-$count
openssl genrsa -aes128 -passout pass:$passw -out private/$fileName.key.pem 2048

For details compare section Root-CA / create the key

create the certificate sign request (2.3)

The certificate has to be signed by the root-ca. Thus we create a sign request.

#!/bin/bash

subCaName=$caName-sub
cd $baseDir/$subCaName
sed -i "s/^count             = .*/count             = ${count}/" openssl.cnf
fileName=$subCaName-$count
openssl req -config openssl.cnf -new -sha256 \
-key private/$fileName.key.pem \
-passin pass:$passw \
-subj "/C=DE/ST=NRW/L=Cologne/O=$caName/OU=$caName/CN=$fileName/emailAddress=$subCaName@b2bbp.org" \
-out csr/$fileName.csr.pem

For details compare section Root-CA / create the certificate

create the certificate (2.4)

The root-ca signs the certificate of the sub-ca.

#!/bin/bash

subCaName=$caName-sub
rootCaName=$caName-root
cd $baseDir/$rootCaName
sed -i "s/^count             = .*/count             = ${count}/" openssl.cnf
fileName=$subCaName-$count
openssl ca -config openssl.cnf -extensions v3_intermediate_ca \
-days 3650 -notext -md sha256 -batch \
-in $baseDir/$subCaName/csr/$fileName.csr.pem \
-passin pass:$passw \
-out certs/$fileName.cert.pem
cp certs/$fileName.cert.pem $baseDir/$subCaName/certs/

For details compare section Root-CA / create the certificate.

CRL

A sub-ca can maintain a CRL (certificate revocation list) for certificates signed by it.

revoke certificate (3.6)

Set the environment variable fileName="sde-energy-1" to a certificate you want to revoke.

#!/bin/bash

subCaName=$caName-sub
cd $baseDir/$subCaName
sed -i "s/^count             = .*/count             = ${count}/" openssl.cnf
# fileName=$marketpartnerName-$count
openssl ca -config openssl.cnf \
-passin pass:$passw -batch -revoke certs/$fileName.cert.pem

create the CRL (2.5)

#!/bin/bash

subCaName=$caName-sub
cd $baseDir/$subCaName
sed -i "s/^count             = .*/count             = ${count}/" openssl.cnf
openssl ca -config openssl.cnf \
-gencrl -passin pass:$passw -batch -out crl/$subCaName.crl.pem

Hint: You still can create an empty CRL if you have not revoked any certificate.

CRL Hosting

You can use a tomcat to host a crl. You need to deploy a war that does not use a password (B2B does unfortunatelly). A possible war can be found here. Put the crl.pem file into the unpacked war. If you use this war and if you configure tomcat on port 8080, the crl test.crl.pem can be reached by url http://localhost:8080/sample/test.crl.pem.

Marketpartner

Precondition: root-ca and sub-ca key and certificate have been created.

install (3.1)

A marketpartner will be installed into the directory $baseDir/$marketpartnerName with the following commands:

#!/bin/bash

cd $baseDir
mkdir $marketpartnerName
cd $marketpartnerName
mkdir certs private csr
touch index.txt
echo 1000 > serial
cp $opensslFilepath ./openssl.cnf
sed -i "s|^baseDir           = .*|baseDir           = ${baseDir}|" openssl.cnf
sed -i "s/^commonNameId      = .*/commonNameId      = ${marketpartnerName}/" openssl.cnf
sed -i "s/^count             = .*/count             = ${count}/" openssl.cnf

After executing these commands you might configure the copied file openssl.cnf: update section req_distinguished_name. These values are part of the certificates and help to identify the marketpartner.

create key and certificate

Increase the shell-variable count.

create the key (3.2)

#!/bin/bash

cd $baseDir/$marketpartnerName
fileName=$marketpartnerName-$count
openssl genrsa -aes128 -passout pass:$passw -out private/$fileName.key.pem 2048

For details compare section Root-CA / create the key

create the sign request (3.3)

The certificate has to be signed by the sub-ca. Thus we create a sign request.

#!/bin/bash

cd $baseDir/$marketpartnerName
fileName=$marketpartnerName-$count
sed -i "s/^count             = .*/count             = ${count}/" openssl.cnf
openssl req -config openssl.cnf \
-key private/$fileName.key.pem \
-passin pass:$passw \
-subj "/C=DE/ST=NRW/L=Cologne/O=$marketpartnerName/OU=$marketpartnerName/CN=$fileName/emailAddress=$marketpartnerName@b2bbp.org" \
-new -sha256 -out csr/$fileName.csr.pem

For details compare section Root-CA / create the certificate

sign the certificate (3.4)

The sub-ca signs the certificate of the marketpartner.

#!/bin/bash

subCaName=$caName-sub
cd $baseDir/$subCaName
sed -i "s/^count             = .*/count             = ${count}/" openssl.cnf
fileName=$marketpartnerName-$count
openssl ca -config openssl.cnf \
-extensions usr_cert -days 1095 -notext -md sha256 \
-in $baseDir/$marketpartnerName/csr/$fileName.csr.pem \
-passin pass:$passw -batch \
-out certs/$fileName.cert.pem
cp certs/$fileName.cert.pem $baseDir/$marketpartnerName/certs/

For details compare section Root-CA / create the certificate.

p12 key (3.5)

You might want to combine key and certificate into the p12-format which the SecurityServer can read as key:

#!/bin/bash

cd $baseDir/$marketpartnerName
fileName=$marketpartnerName-$count
openssl pkcs12 -export \
-in certs/$fileName.cert.pem \
-inkey private/$fileName.key.pem \
-passin pass:$passw -passout pass:$passw > private/$fileName.p12

BDEW conformity

Algorithm RSA-PSS

Use RSA-PSS to create the private key. Therefore instead of

openssl genrsa ...

use

openssl genpkey -algorithm rsa-pss -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 -pass pass:$passw -out private/$cn.key

Extension SubjectAlternativeName

How to add the SubjectAlternativeName to the certificate:

Mapa

openssl.cnf

[ usr_cert ]
subjectAltName = @alt_names

[alt_names]
email = ago-energy@b2bbp.org

Don’t forget to use the extension usr_cert in query.

Issuer

openssl.cnf

copy_extensions = copy 

Or you add the same configuration as in Mapa to openssl.cnf of the issuer and use it during the signing.

attachments A

openssl.cnf

# OpenSSL root CA configuration file.

baseDir           = /home/agohr/certs
commonNameId      = skl-energy-root-ca
count             = 1
crlHostUrl        = http://localhost:8080/sample
# localhost only for testing

[ ca ]
# `man ca`
default_ca = CA_default

[ CA_default ]
dir               = $baseDir/$commonNameId
certs             = $dir/certs
crl_dir           = $dir/crl
new_certs_dir     = $dir/newcerts
database          = $dir/index.txt
serial            = $dir/serial
RANDFILE          = $dir/private/.rand
keyCertName       = $commonNameId-$count
private_key       = $dir/private/$keyCertName.key.pem
certificate       = $dir/certs/$keyCertName.cert.pem

crlnumber         = $dir/crlnumber
crl               = $dir/crl/$commonNameId.crl.pem
crl_extensions    = crl_ext
default_crl_days  = 365
# default_crl_days would be shorter in production environment

default_md        = sha256

name_opt          = ca_default
cert_opt          = ca_default
default_days      = 1090
preserve          = no
policy            = policy_loose

unique_subject    = no

[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req ]
# Options for the `req` tool (`man req`).
default_bits        = 2048
distinguished_name  = req_distinguished_name
string_mask         = utf8only

# SHA-1 is deprecated, so use SHA-2 instead.
default_md          = sha256

# Extension to add when the -x509 option is used.
x509_extensions     = v3_ca

[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName                     = Country Name (2 letter code)
stateOrProvinceName             = State or Province Name
localityName                    = Locality Name
0.organizationName              = Organization Name
organizationalUnitName          = Organizational Unit Name
commonName                      = Common Name
emailAddress                    = Email Address

# Optionally, specify some defaults.
countryName_default             = DE
stateOrProvinceName_default     = NRW
localityName_default            = Cologne
0.organizationName_default      = SKL Energy
organizationalUnitName_default  = SKL Energy Certificate Authority
commonName_default              = SKL Energy Root CA
emailAddress_default            = skl-energy-root-ca@b2bbp.org

[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
crlDistributionPoints = URI:$crlHostUrl/$commonNameId.crl.pem

[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
crlDistributionPoints = URI:$crlHostUrl/$commonNameId.crl.pem

[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier=keyid:always

[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning

gen_cert.sh

#!/bin/bash

opensslFilepath="/home/agohr/openssl.cnf"
export opensslFilepath
baseDir="/home/agohr/certs"
export baseDir
caName="skl-energy"
export caName
marketpartnerName="rsc-energy"
export marketpartnerName
count=`date '+%Y-%m-%d-%H-%M-%S'`
count="100"
export count
crlHostUrl="http://localhost:8080/sample"
export crlHostUrl
passw="b2bbp"
export passw

rootCaName=$caName-root
subCaName=$caName-sub

# private function
install() {
	commonNameId=$1
	cd $baseDir
	mkdir $commonNameId
	cd $commonNameId
	mkdir certs crl newcerts private csr
	touch index.txt
	echo 1000 > serial
	echo 1000 > crlnumber
	cp $opensslFilepath ./openssl.cnf
	sed -i "s|^baseDir           = .*|baseDir           = ${baseDir}|" openssl.cnf
	sed -i "s/^commonNameId      = .*/commonNameId      = ${commonNameId}/" openssl.cnf
	sed -i "s/^count             = .*/count             = ${count}/" openssl.cnf
	sed -i "s|^crlHostUrl        = .*|crlHostUrl        = ${crlHostUrl}|" openssl.cnf
}

# private function
gen_key() {
	commonNameId=$1
	cd $baseDir/$commonNameId
	fileName=$commonNameId-$count
	openssl genrsa -aes128 -passout pass:$passw -out private/$fileName.key.pem 2048
}

1_1_install_root_ca() {
	install $rootCaName
	sed -i 's/^policy            = .*/policy            = policy_strict/' openssl.cnf
}

1_2_gen_key_root_ca() {
	gen_key $rootCaName
}

1_3_self_sign_cert_root_ca() {
	cd $baseDir/$rootCaName
	sed -i "s/^count             = .*/count             = ${count}/" openssl.cnf
	fileName=$rootCaName-$count
	openssl req -config openssl.cnf \
	-key private/$fileName.key.pem \
	-new -x509 -days 7300 -sha256 -extensions v3_ca \
	-passin pass:$passw \
	-subj "/C=DE/ST=NRW/L=Cologne/O=$caName/OU=$caName/CN=$fileName/emailAddress=$rootCaName@b2bbp.org" \
	-out certs/$fileName.cert.pem
}

2_1_install_sub_ca() {
	install $subCaName
}

2_2_gen_key_sub_ca() {
	gen_key $subCaName
}

2_3_request_cert_sign_sub_ca_root_ca() {
	cd $baseDir/$subCaName
	sed -i "s/^count             = .*/count             = ${count}/" openssl.cnf
	fileName=$subCaName-$count
	openssl req -config openssl.cnf -new -sha256 \
	-key private/$fileName.key.pem \
	-passin pass:$passw \
	-subj "/C=DE/ST=NRW/L=Cologne/O=$caName/OU=$caName/CN=$fileName/emailAddress=$subCaName@b2bbp.org" \
	-out csr/$fileName.csr.pem
}

2_4_sign_cert_root_ca_sub_ca() {
	cd $baseDir/$rootCaName
	sed -i "s/^count             = .*/count             = ${count}/" openssl.cnf
	fileName=$subCaName-$count
	openssl ca -config openssl.cnf -extensions v3_intermediate_ca \
	-days 3650 -notext -md sha256 -batch \
	-in $baseDir/$subCaName/csr/$fileName.csr.pem \
	-passin pass:$passw \
	-out certs/$fileName.cert.pem
	cp certs/$fileName.cert.pem $baseDir/$subCaName/certs/
}

2_5_gen_crl_sub_ca() {
	cd $baseDir/$subCaName
	sed -i "s/^count             = .*/count             = ${count}/" openssl.cnf
	openssl ca -config openssl.cnf \
	-gencrl -passin pass:$passw -batch -out crl/$subCaName.crl.pem
}

3_1_install_marketpartner() {
	install $marketpartnerName
}

3_2_gen_key_marketpartner() {
	gen_key $marketpartnerName
}

3_3_request_cert_sign_marketpartner_sub_ca() {
	cd $baseDir/$marketpartnerName
	fileName=$marketpartnerName-$count
	sed -i "s/^count             = .*/count             = ${count}/" openssl.cnf
	openssl req -config openssl.cnf -new -sha256 \
	-key private/$fileName.key.pem \
	-passin pass:$passw \
	-subj "/C=DE/ST=NRW/L=Cologne/O=$marketpartnerName/OU=$marketpartnerName/CN=$fileName/emailAddress=$marketpartnerName@b2bbp.org" \
	-out csr/$fileName.csr.pem
}

3_4_sign_cert_sub_ca_marketpartner() {
	cd $baseDir/$subCaName
	sed -i "s/^count             = .*/count             = ${count}/" openssl.cnf
	fileName=$marketpartnerName-$count
	openssl ca -config openssl.cnf \
	-extensions usr_cert -days 1095 -notext -md sha256 \
	-in $baseDir/$marketpartnerName/csr/$fileName.csr.pem \
	-passin pass:$passw -batch \
	-out certs/$fileName.cert.pem
	cp certs/$fileName.cert.pem $baseDir/$marketpartnerName/certs/
}

3_5_gen_p12_marketpartner() {
	cd $baseDir/$marketpartnerName
	fileName=$marketpartnerName-$count
	openssl pkcs12 -export \
	-in certs/$fileName.cert.pem \
	-inkey private/$fileName.key.pem \
	-passin pass:$passw -passout pass:$passw > private/$fileName.p12
}

3_6_revoke_cert_sub_ca_marketpartner() {
	cd $baseDir/$subCaName
	sed -i "s/^count             = .*/count             = ${count}/" openssl.cnf
	fileName=$marketpartnerName-$count
	openssl ca -config openssl.cnf \
	-passin pass:$passw -batch -revoke certs/$fileName.cert.pem
}

case $1 in
        1_1_install_root_ca) 1_1_install_root_ca
            ;;
        1_2_gen_key_root_ca) 1_2_gen_key_root_ca
            ;;
        1_3_self_sign_cert_root_ca) 1_3_self_sign_cert_root_ca
            ;;
        2_1_install_sub_ca) 2_1_install_sub_ca
            ;;
        2_2_gen_key_sub_ca) 2_2_gen_key_sub_ca
            ;;
        2_3_request_cert_sign_sub_ca_root_ca) 2_3_request_cert_sign_sub_ca_root_ca
            ;;
        2_4_sign_cert_root_ca_sub_ca) 2_4_sign_cert_root_ca_sub_ca
            ;;
        2_5_gen_crl_sub_ca) 2_5_gen_crl_sub_ca
            ;;
        3_1_install_marketpartner) 3_1_install_marketpartner
            ;;
        3_2_gen_key_marketpartner) 3_2_gen_key_marketpartner
            ;;
        3_3_request_cert_sign_marketpartner_sub_ca) 3_3_request_cert_sign_marketpartner_sub_ca
            ;;
        3_4_sign_cert_sub_ca_marketpartner) 3_4_sign_cert_sub_ca_marketpartner
            ;;
        3_5_gen_p12_marketpartner) 3_5_gen_p12_marketpartner
            ;;
        3_6_revoke_cert_sub_ca_marketpartner) 3_6_revoke_cert_sub_ca_marketpartner
            ;;
		all) 1_1_install_root_ca
			1_2_gen_key_root_ca
			1_3_self_sign_cert_root_ca
			2_1_install_sub_ca
			2_2_gen_key_sub_ca
			2_3_request_cert_sign_sub_ca_root_ca
			2_4_sign_cert_root_ca_sub_ca
			2_5_gen_crl_sub_ca
			3_1_install_marketpartner
			3_2_gen_key_marketpartner
			3_3_request_cert_sign_marketpartner_sub_ca
			3_4_sign_cert_sub_ca_marketpartner
			3_5_gen_p12_marketpartner
			3_6_revoke_cert_sub_ca_marketpartner
			;;
        *) echo "unknown command"
            ;;
esac

Attachments B

openssl.cnf

# OpenSSL root CA configuration file.

[ ca ]
# `man ca`
default_ca = CA_default

[ CA_default ]
dir              = ${ENV::dir}
certs            = $dir/certs
crl_dir          = $dir/crl
new_certs_dir    = $dir/newcerts
database         = $dir/index.txt
serial           = $dir/serial
RANDFILE         = $dir/private/.rand
keyCertName      = ${ENV::cn}
private_key      = $dir/private/$keyCertName.key
certificate      = $dir/certs/$keyCertName.cer

crlnumber        = $dir/crlnumber
crl              = $dir/crl/$keyCertName.crl
crl_extensions   = crl_ext
default_crl_days = 365
# default_crl_days would be shorter in production environment

default_md       = sha256

name_opt         = ca_default
cert_opt         = ca_default
default_days     = 1090
preserve         = no
policy           = policy_strict

unique_subject   = no

copy_extensions  = copy
# only if you trust the requesting party

[ policy_strict ]
countryName            = match
organizationName       = match
organizationalUnitName = optional
commonName             = supplied
emailAddress           = optional

[ policy_loose ]
countryName            = optional
organizationName       = optional
organizationalUnitName = optional
commonName             = supplied
emailAddress           = optional

[ req ]
# `man req`.
default_bits       = 2048
distinguished_name = req_distinguished_name
string_mask        = utf8only

default_md         = sha256

# Extension to add when the -x509 option is used.
x509_extensions    = v3_ca

req_extensions = usr_cert

[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName                    = Country Name (2 letter code)
0.organizationName             = Organization Name
organizationalUnitName         = Organizational Unit Name
commonName                     = Common Name
emailAddress                   = Email Address

# Optionally, specify some defaults.
countryName_default            = ${ENV::country}
0.organizationName_default     = ${ENV::organization}
organizationalUnitName_default = ${ENV::unit}
commonName_default             = ${ENV::cn}
emailAddress_default           = ${ENV::email}

[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints       = critical, CA:true
keyUsage               = critical, digitalSignature, cRLSign, keyCertSign

[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints       = critical, CA:true, pathlen:0
keyUsage               = critical, digitalSignature, cRLSign, keyCertSign

[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints       = CA:FALSE
nsCertType             = client, email
nsComment              = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid,issuer
keyUsage               = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage       = clientAuth, emailProtection
crlDistributionPoints  = URI:${ENV::crlHostUrl}/${ENV::cn}.crl
subjectAltName = @alt_names

[alt_names]
email = ${ENV::san}

[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier = keyid:always

All Commands

# preconditions
# * openssl installed
# openssl.cnf is available in your working directory

# Root-CA, Sub-CA and Mapa are potentially different organizations and may run on different servers. Thus each has its own home dir, own enviroment variables and own openssl.cnf. I assume they cannot access each other.

#########
# 1. Root-CA Key & Certificate
#########

#################################
# 1.0 configure subject
#################################

# copy the following configuration to a shell script 'subject.sh'

#!/bin/bash

# the following env variables are used in openssl.cnf
export country=DE
export organization=skl-energy
export unit=root-ca
export fullName=$organization-$unit
export cn=$fullName
export subject="/C=$country/O=$organization/OU=$unit/CN=$cn"

export email=$fullName@b2bbp.org
export passw=b2bbp
export crlHostUrl=http://localhost:8080/sample

export baseDir=/home/agohr/certs
export dir=$baseDir/$fullName

export san=$email

#################################
# 1.1 install root-ca directory & database
#################################

# subject.sh must be available and configured
# openssl.cnf must be available

source subject.sh
mkdir $dir
cp subject.sh $dir
cp openssl.cnf $dir
cd $dir
mkdir private certs newcerts csr crl
# database files: indext.txt & serial
touch index.txt
touch index.txt.attr
echo 1000 > serial
echo 1000 > crlnumber

######################################
# 1.2 create private key
######################################

cd $dir
source subject.sh

# create the keypair. The key size is 2048; the exponent is 65537
openssl genpkey -algorithm rsa-pss -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 -pass pass:$passw -out private/$cn.key

######################################
# 1.3 create self-signed certificate
######################################

cd $dir
source subject.sh

# create the certificate
openssl req -config openssl.cnf -key private/$cn.key -new -x509 -days 7300 -sha256 -extensions v3_ca -passin pass:$passw -subj $subject -out certs/$cn.cer

# verify
openssl x509 -noout -text -in certs/$cn.cer

#########
# 2. Sub-CA Key & Certificate
#########

#################################
# 2.0 configure subject.sh
#################################

# copy the following configuration to a shell script 'subject.sh'

#!/bin/bash

# the following env variables are used in openssl.cnf

export country=DE
export organization=skl-energy
export unit=sub-ca
export fullName=$organization-$unit
export cn=$fullName
export subject="/C=$country/O=$organization/OU=$unit/CN=$cn"

export email=$fullName@b2bbp.org
export passw=b2bbp
export crlHostUrl=http://localhost:8080/sample

export baseDir=/home/agohr/certs
export dir=$baseDir/$fullName

export san=$email

#################################
# 2.1 install sub-ca directory & database
#################################

# subject.sh must be available and configured
# openssl.cnf must be available

source subject.sh
mkdir $dir
cp subject.sh $dir
cp openssl.cnf $dir
cd $dir
sed -i "s/= policy_strict/= policy_loose/" openssl.cnf
sed -i "s/= usr_cert/= v3_intermediate_ca/" openssl.cnf
# remove authorityKeyIdentifier from [ v3_intermediate_ca ]
mkdir private certs newcerts csr crl
# database files: indext.txt & serial
touch index.txt
touch index.txt.attr
echo 1000 > serial
echo 1000 > crlnumber

######################################
# 2.2 create private key
######################################

# $dir belongs to sub-ca
cd $dir
source subject.sh

# create the keypair. The key size is 2048; the exponent is 65537
openssl genpkey -algorithm rsa-pss -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 -pass pass:$passw -out private/$cn.key

######################################
# 2.3 request certificate signing
######################################

# $dir belongs to sub-ca
cd $dir
source subject.sh

# create the request
openssl req -config openssl.cnf -new -sha256 -key private/$cn.key -passin pass:$passw -subj $subject -out csr/$cn.csr

# verify
openssl req -text -in csr/$cn.csr

# provide the request-file to the root-ca/csr directory, e.g.
cp csr/skl-energy-sub-ca.csr ../skl-energy-root-ca/csr

######################################
# 2.4 sign certificate
######################################

# $dir belongs to root-ca
cd $dir
source subject.sh

# configure here to cn of the sub-ca
export issued=skl-energy-sub-ca
export san=$issued@b2bbp.org

# sign the certificate
openssl ca -config openssl.cnf -days 3650 -notext -md sha256 -batch -extensions v3_intermediate_ca -in csr/$issued.csr -passin pass:$passw -out certs/$issued.cer

# verify
openssl x509 -noout -text -in certs/$issued.cer

# deliver the certificate to the sub-ca/certs directory, e.g.
cp certs/skl-energy-sub-ca.cer ../skl-energy-sub-ca/certs/

################
# 3. Mapa Key, Certificate & related CRL
################

#################################
# 3.0 configure subject.sh
#################################

# copy the following configuration to a shell script 'subject.sh'

#!/bin/bash

# the following env variables are used in openssl.cnf

export country=DE
export organization=ago-energy
export unit=net
export fullName=$organization-$unit
# best practise: unique name for every certificate -> solved here with current date
export id=19-08-07
export cn=$fullName-$id
export subject="/C=$country/O=$organization/OU=$unit/CN=$cn"

export email=$fullName@b2bbp.org
export passw=b2bbp
export crlHostUrl=http://localhost:8080/sample

export baseDir=/home/agohr/certs
export dir=$baseDir/$fullName

export san=$email

#################################
# 3.1 install mapa directory
#################################

# subject.sh must be available and configured
# openssl.cnf must be available

source subject.sh
mkdir $dir
cp subject.sh $dir
cp openssl.cnf $dir
cd $dir
# remove authorityKeyIdentifier from [ usr_cert ] in openssl.cnf
mkdir private certs csr

######################################
# 3.2 create private key
######################################

# $dir belongs to mapa
cd $dir
source subject.sh

# create the keypair. The key size is 2048; the exponent is 65537
openssl genpkey -algorithm rsa-pss -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 -pass pass:$passw -out private/$cn.key

######################################
# 3.3 request certificate signing
######################################

# $dir belongs to mapa
cd $dir
source subject.sh

# create the request
openssl req -config openssl.cnf -new -sha256 -key private/$cn.key -passin pass:$passw -subj $subject -out csr/$cn.csr

# verify
openssl req -text -in csr/$cn.csr

# provide the request-file to the sub-ca/csr directory, e.g.
cp csr/ago-energy-19-08-07.csr ../skl-energy-sub-ca/csr

######################################
# 3.4 sign certificate
######################################

# $dir belongs to sub-ca
cd $dir
source subject.sh

# configure here cn & san of the mapa
export issuedName=ago-energy
export issued=$issuedName-19-08-07
export san=$issuedName@b2bbp.org

# sign the certificate
openssl ca -config openssl.cnf -days 1095 -notext -md sha256 -batch -extensions usr_cert -in csr/$issued.csr -passin pass:$passw -out certs/$issued.cer

# verify
openssl x509 -noout -text -in certs/$issued.cer

# deliver the certificate to the mapa/certs directory, e.g.
cp certs/ago-energy-19-08-07.cer ../ago-energy/certs/

######################################
# 3.5 p12 key format
######################################

# $dir belongs to mapa
cd $dir
source subject.sh

openssl pkcs12 -export -in certs/$cn.cer -inkey private/$cn.key -passin pass:$passw -passout pass:$passw > private/$cn.p12

#verify
openssl pkcs12 -info -in private/$cn.p12

######################################
# 3.6 revoke certificate
######################################

# $dir belongs to sub-ca
cd $dir
source subject.sh

# configure here to cn of the mapa
issued=ago-energy-19-08-07

openssl ca -config openssl.cnf -passin pass:$passw -batch -revoke certs/$issued.cer

######################################
# 3.7 create CRL
######################################

# $dir belongs to sub-ca
cd $dir
source subject.sh

openssl ca -config openssl.cnf -gencrl -passin pass:$passw -batch -out crl/$cn.crl

View Me   Edit Me