Skip to content

Instantly share code, notes, and snippets.

@usmansaleem
Last active January 19, 2023 02:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save usmansaleem/4336014530df62bd921cbb20cb2772db to your computer and use it in GitHub Desktop.
Save usmansaleem/4336014530df62bd921cbb20cb2772db to your computer and use it in GitHub Desktop.
Custom Root CA and Intermediate CA to sign the server cert using keytool (Web3Signer TLS)

Generate Root CA, Web3Signer server and client certificate

This example uses JDK's keytool utility to generate custom CA and signs web3signer and client certs and shows how to setup Web3Signer with them. The openssl example can be seen here.


Note: password 123456 is used in these examples


Generate Root CA (alias root - CN=root.mycompany.com)

keytool -genkeypair -keystore root.p12 -alias root -dname "CN=root.mycompany.com" -ext bc:c -keyalg rsa
keytool -keystore root.p12 -alias root -exportcert -rfc > root.pem

Generate Web3Signer server certificate (alias = web3signer)

The Web3Signer certificate CN should be the hostname where web3signer is hosted. In this example, I am using localhost. The san extension should be used to specify the other hostname and IP addresses from which Web3Signer is served. For example, -ext san=dns:localhost,dns:myhost1,ip:127.0.0.1,ip:10.0.0.5

 keytool -genkeypair -keystore web3signer_keystore.p12 -storetype PKCS12 -alias web3signer \
-keyalg RSA -keysize 2048 -validity 90 -dname "CN=localhost, OU=PegaSys, O=ConsenSys, L=Brisbane, ST=QLD, C=AU" \
-ext san=dns:localhost,ip:127.0.0.1

Create Web3Signer CSR and sign it using Root CA.

Take a note of extensions. These are usually required.

keytool -storepass 123456 -keystore web3signer_keystore.p12 \
-certreq -alias web3signer | keytool -storepass 123456 \
-keystore root.p12 -gencert -alias root -ext ku:c=dig,kE -rfc \
> web3signer.pem

Import signed web3signer certificates

cat root.pem web3signer.pem | keytool -keystore web3signer_keystore.p12 \
-importcert -alias web3signer -storepass 123456 -noprompt

web3signer_keystore.p12 now contains the CA chain as well as signed certificate. Time to get Web3Signer start with TLS enabled. In the following example, Web3Signer is using tls-allow-any-client: true.

Create docker-compose.yml and web3signer configuration

mkdir -p ./config/keys
cp ./web3signer_keystore.p12 ./config
cat <<EOF >./config/password.txt
123456
EOF
cat <<EOF >./config/config.yaml
http-listen-host: "0.0.0.0"
http-listen-port: 9000
http-host-allowlist: "*"

key-store-path: /var/config/keys

# tls options
tls-keystore-file: /var/config/web3signer_keystore.p12 
tls-keystore-password-file: /var/config/password.txt 
# tls-known-clients-file: /var/config/knownClients.txt
tls-allow-any-client: true

# eth2 subcommand options
eth2.slashing-protection-enabled: false
EOF
cat <<EOF >./docker-compose.yaml
version: "3.9"
   
services:
  web3signer:
    image: consensys/web3signer:develop
    command: --config-file=/var/config/config.yaml eth2
    volumes:
      - ./config:/var/config
    ports:
      - "9000:9000"
EOF

Run Web3Signer using docker compose

docker compose up

...
tlscerts-web3signer-1  | 2023-01-17 02:52:59.659+00:00 | pool-2-thread-1 | INFO  | DefaultArtifactSignerProvider | Total signers (keys) currently loaded in memory: 0
tlscerts-web3signer-1  | 2023-01-17 02:53:00.140+00:00 | main | INFO  | Runner | Web3Signer has started with TLS enabled, and ready to handle signing requests on 0.0.0.0:9000

Use curl with upcheck

» curl --cacert ./root.pem https://localhost:9000/upcheck
OK%

Web3Signer TLS with mutual authentication

Following scenario means that client will present its certificate to web3Signer for mutual TLS authentication. Hence Web3Signer needs to add the client's certificate fingerprint in the known clients.

Create the keystore for the client of Web3Siger (such as Teku or curl)

Similar to Web3Signer certificate, we will generate and sign certificate for the "curl" utility (This can be certificate for Teku or other consensus client with appropriate CN name)

» keytool -genkeypair -keystore curl_keystore.p12 -alias curl \
-keyalg RSA -validity 90 -dname "CN=curl, OU=PegaSys, O=ConsenSys, L=Brisbane, ST=QLD, C=AU" \
-ext san=dns:localhost,ip:127.0.0.1 -storepass 123456
Generating 2,048 bit RSA key pair and self-signed certificate (SHA256withRSA) with a validity of 90 days
	for: CN=curl, OU=PegaSys, O=ConsenSys, L=Brisbane, ST=QLD, C=AU

Generate the CSR and sign it using CA.

keytool -storepass 123456 -keystore curl_keystore.p12 \
-certreq -alias curl | keytool -storepass 123456 \
-keystore root.p12 -gencert -alias root -ext ku:c=dig,kE -rfc \
> curl.pem

Import signed curl certificate back into curl's keystore

cat root.pem curl.pem | keytool -keystore curl_keystore.p12 \
-importcert -alias curl -storepass 123456 -noprompt

Certificate fingerprints (SHA256)

Now we need to figure out the certificate fingerprint which can be used by Web3Signer to accept this certificate. It might be different in your setup, so take a note of SHA256 fingerprint for "curl" alias as shown in following output.

» keytool -list -v -keystore ./curl_keystore.p12 -alias curl
Enter keystore password:
Alias name: curl
Creation date: 17 Jan 2023
Entry type: PrivateKeyEntry
Certificate chain length: 3
Certificate[1]:
Owner: CN=curl, OU=PegaSys, O=ConsenSys, L=Brisbane, ST=QLD, C=AU
Issuer: CN=ca.mycompany.com
Serial number: 8395936a7ae79404
Valid from: Tue Jan 17 16:00:41 AEST 2023 until: Mon Apr 17 16:00:41 AEST 2023
Certificate fingerprints:
	 SHA1: F2:DF:60:59:16:D8:AD:28:1D:23:45:86:34:22:65:0F:00:49:9A:88
	 SHA256: D2:FD:82:FC:FB:07:16:3F:5A:CC:08:B7:BC:CE:EB:70:37:D4:84:FB:DB:53:BF:37:0B:BF:51:95:5C:4C:2F:94

Create knownClients.txt file in ./config using the CN curl as alias and fingerprint.

cat <<EOF >./config/knownClients.txt
curl D2:FD:82:FC:FB:07:16:3F:5A:CC:08:B7:BC:CE:EB:70:37:D4:84:FB:DB:53:BF:37:0B:BF:51:95:5C:4C:2F:94
EOF

Modify Web3Signer's config file ./config/config.yaml

Modify Web3Signer's config file so that it uses the knownClients.txt file. The tls options should look like:

...
# tls options
tls-keystore-file: /var/config/web3signer_keystore.p12
tls-keystore-password-file: /var/config/password.txt
tls-known-clients-file: /var/config/knownClients.txt
# tls-allow-any-client: true
...

Bring Web3Signer up (via docker compose)

docker compose up

Connect to Web3Signer using curl

curl --cacert ./root.pem --cert-type P12 --cert curl_keystore.p12:123456 https://localhost:9000/upcheck
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment