The SSL pinning utility tool is used to sign SSL certificates.
You can use either of the following options:
- Use the Java utility
ssl-pinning-tool.jar
- Use
openssl
commands manually
Both approaches are described in chapters below.
Only Java version 17+ is supported at the moment.
Before signing the SSL certificate, you will need to generate a new ECDSA key pair and store it in the keypair.pem
file. You need to store this file securely. This key pair will be used to sign current certificate and all future certificates. If you already signed a certificate before, skip this step and use the previously generated key pair.
The keypair.pem
contains the private key. The public key can be printed as described in chapter Export public key.
The following command generates the key pair in PEM format. The key pair is protected by password of your choice.
java -jar ssl-pinning-tool.jar keygen -o keypair.pem -p [password]
Store the key pair and private key password safely! You will need it next time you replace SSL certificate to generate new signatures.
This command will retrieve the SSL certificate into PEM file:
openssl s_client -showcerts -connect my.domain.com:443 -servername my.domain.com < /dev/null | openssl x509 -outform PEM > cert.pem
Make sure to replace my.domain.com
in both -connect
and -servername
options with your domain name.
This command will generate the SSL certificate signature:
java -jar ssl-pinning-tool.jar sign -k keypair.pem -c cert.pem -o output.json -p [password]
The output file will contain SSL certificate signature:
{
"name" : "my.domain.com",
"fingerprint" : "jymEKdgGPv1zSp61CYya5c2fR9fTLe8tKnWF6857iLA=",
"expires" : 1543322263,
"signature" : "MEUCICOs9bb6TIEmRNHCekxn9URADLYuuZnk4aftpVDzdwmWAiEAlU2r9VDEnAWryxvbAsSJfIlCQjKfumdFbZeUKda166w="
}
Alternatively, you can prepare certificate signature from information about the certificate. This approach is useful when the certificate is not deployed yet.
You need following information:
- Domain common name, e.g.
my.domain.com
- Certificate fingerprint in HEX format, for example:
8f298429d8063efd734a9eb5098c9ae5cd9f47d7d32def2d2a7585ebce7b88b0
- SSL certificate expiration time as Unix timestamp in seconds, e.g.
1543322263
This command will generate the SSL certificate signature:
java -jar ssl-pinning-tool.jar sign -k keypair.pem -f 8f298429d8063efd734a9eb5098c9ae5cd9f47d7d32def2d2a7585ebce7b88b0 -t 1543322263 -n my.domain.com -o output.json -p [password]
The output file will contain JSON with SSL certificate signature:
{
"name" : "my.domain.com",
"fingerprint" : "jymEKdgGPv1zSp61CYya5c2fR9fTLe8tKnWF6857iLA=",
"expires" : 1543322263,
"signature" : "MEUCICOs9bb6TIEmRNHCekxn9URADLYuuZnk4aftpVDzdwmWAiEAlU2r9VDEnAWryxvbAsSJfIlCQjKfumdFbZeUKda166w="
}
This JSON snippet should be added into the final list of certificate fingerprints. If you have any previous certificate signatures, please merge them with the snipped. This JSON file will be published on a web server for mobile clients:
{
"fingerprints": [
{
"name" : "my.domain.com",
"fingerprint" : "jymEKdgGPv1zSp61CYya5c2fR9fTLe8tKnWF6857iLA=",
"expires" : 1543322263,
"signature" : "MEUCICOs9bb6TIEmRNHCekxn9URADLYuuZnk4aftpVDzdwmWAiEAlU2r9VDEnAWryxvbAsSJfIlCQjKfumdFbZeUKda166w="
}
]
}
Mobile app developers will need the public key from generated key pair in order to be able to verify signatures.
You can convert EC private key to public key and print it:
java -jar ssl-pinning-tool.jar export -k keypair.pem -p [password]
Server app developers might need the private key from generated key pair in order to be able to dynamically compute signatures. For example, our Mobile Utility Server uses the private key from this utility output.
You can convert EC private key to the appropriate format and print it:
java -jar ssl-pinning-tool.jar export-private -k keypair.pem -p [password]
Error:
SEVERE: Failed to load private key, error: unable to read encrypted data: javax.crypto.BadPaddingException: pad block corrupted
This error is shown when the private key password is invalid.
Alternatively, you can perform all steps above using openssl
command.
You can use openssl
command to download certificate, generate keypair and prepare the certificate signature. The scripts below should work on Linux or Mac OS X.
This command will retrieve the SSL certificate into DER format which is suitable for computing the SHA-256 fingerprint:
openssl s_client -showcerts -connect my.domain.com:443 -servername my.domain.com < /dev/null | openssl x509 -outform DER > cert.der
Make sure to replace my.domain.com
in both -connect
and -servername
options with your domain name.
This command will generate a new ECDSA key pair and store it in the keypair.pem
file. You need to store this file securely.
openssl ecparam -name prime256v1 -genkey | openssl pkcs8 -topk8 -v2 aes-128-cbc > keypair.pem
Store the key pair and private key password safely! You will need it next time you replace SSL certificate to generate new signatures.
This command converts a server certificate stored in the cert.der
file to SHA-256 fingerprint in binary form, encoded as Base64 and stored in fingerprint.txt
file.
FINGERPRINT_BASE64=`openssl dgst -sha256 -binary < cert.der | openssl enc -base64 -A`
In order to compute the signature, you need to have values of certificate common name and expiration timestamp.
To obtain common name, call:
COMMON_NAME=`openssl x509 -noout -subject -inform der -in cert.der | sed -n '/^subject/s/^.*CN=//p'`
To obtain expiration timestamp, call:
EXPIRATION_TIME=`openssl x509 -noout -dates -inform der -in cert.der | grep notAfter | sed -e 's#notAfter=##'`
if date --version >/dev/null 2>/dev/null; then
# Linux
UNIXTIMESTAMP_EXPIRATION=`date -d "$EXPIRATION_TIME" "+%s"`
else
# MacOSX
UNIXTIMESTAMP_EXPIRATION=`date -j -f "%b %d %H:%M:%S %Y %Z" "$EXPIRATION_TIME" "+%s"`
fi
This sequence of commands signs the fingerprint from fingerprint.txt
with the private key from the provided key pair file keypair.pem
and stores the result signature as a Base64 encoded file sign.txt
.
Prepare a signature base string as $COMMON_NAME + '&' + $UNIXTIMESTAMP_EXPIRATION + '&' + $FINGERPRINT:
echo -n "$COMMON_NAME" > signature_base_string.txt
echo -n "&" >> signature_base_string.txt
echo -n "$UNIXTIMESTAMP_EXPIRATION" >> signature_base_string.txt
echo -n "&" >> signature_base_string.txt
echo -n "$FINGERPRINT_BASE64" >> signature_base_string.txt
You can verify the signature base string by printing it:
cat signature_base_string.txt
Sign the signature base string with private key from the key pair:
openssl dgst -sha256 -sign keypair.pem signature_base_string.txt > signature_raw.txt
Encode result as Base64:
SIGNATURE_BASE64=`openssl enc -base64 -A < signature_raw.txt`
Mobile app developers will need the public key from generated key pair in order to be able to verify signatures.
You can convert EC private key to public key:
openssl ec -in keypair.pem -pubout
You need to encode the data into JSON. If you have any previous certificate signatures, please merge them with the generated file. This JSON file will be published on a web server for mobile clients:
echo "{" > fingerprints.json
echo " \"fingerprints\": [" >> fingerprints.json
echo " {" >> fingerprints.json
echo " \"name\": \"$COMMON_NAME\"," >> fingerprints.json
echo " \"fingerprint\": \"$FINGERPRINT_BASE64\"," >> fingerprints.json
echo " \"expires\": $UNIXTIMESTAMP_EXPIRATION," >> fingerprints.json
echo " \"signature\": \"$SIGNATURE_BASE64\"" >> fingerprints.json
echo " }" >> fingerprints.json
echo " ]" >> fingerprints.json
echo "}" >> fingerprints.json
You can obtain the JSON output using command:
cat fingerprints.json
Mobile app developers will need the public key from generated key pair in order to be able to verify signatures.
The openssl
command cannot export ECDSA public key in raw format, so you will need to use our Java utility for the export.
You can convert EC private key to public key and print it:
java -jar ssl-pinning-tool.jar export -k keypair.pem -p [password]