Skip to content

Instantly share code, notes, and snippets.

@Riduidel
Forked from jirutka/keytool-import.sh
Last active January 24, 2018 08:10
Show Gist options
  • Save Riduidel/a10bf15f787271f406280bbc27e2aae5 to your computer and use it in GitHub Desktop.
Save Riduidel/a10bf15f787271f406280bbc27e2aae5 to your computer and use it in GitHub Desktop.
Script to import key/certificate pairs into an existing Java keystore
#!/bin/bash
#
# The MIT License
#
# Copyright 2013-2015 Jakub Jirutka <[email protected]>.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# -----BEGIN HELP-----
# Import pair of certificate and key in PEM format into a Java keystore.
#
# Usage:
# @SCRIPT_NAME@ -s KEYSTORE -k KEYFILE -c CERTFILE -a ALIAS [options]
# @SCRIPT_NAME@ -s KEYSTORE -z PKCS12 [options]
#
# Options:
# -s KEYSTORE --keystore KEYSTORE Keystore to import certificate to (required).
# -z PKCS12 --pkcs12 PKCS12 PKCS#12 temporary keystore. Can also be given as parameter (in this case, the KEYFILE and CERTFILE are ignored
# -k KEYFILE --key KEYFILE Private key file in PEM format to import (required).
# -c CERTFILE --cert CERTFILE Certificate file in PEM format to import (required).
# -a ALIAS --alias ALIAS Unique alias of the certificate (required).
# -p PASS --passphrase PASS Passphrase of the keystore (read from stdin if not specified).
# -d PASS --pkcs12passphrase PASS Passphrase of the pkcs#12 keystore. Required when pkcs12 is set
# -i CERTFILE --cert-chain CERTFILE File with intermediate certificates in PEM format (optional).
# -h --help Show this message.
#
# -----END HELP-----
set -e
SCRIPT_NAME="$(basename $0)"
temp_dir=
#====================== Functions ======================#
# Prints message and exits.
die() {
echo -e "${SCRIPT_NAME}: $1" >&2
exit ${2:-2}
}
# Cleans temp directory.
cleanup() {
if [[ -n "$temp_dir" && -d "$temp_dir" ]]; then
rm -rf "$temp_dir"
fi
}
# Prints usage help.
usage() {
cat "$0" \
| sed -En '/-{5}BEGIN HELP-{5}/,/-{5}END HELP-{5}/p' \
| sed -E "s/^# ?//; 1d;\$d; s/@SCRIPT_NAME@/${SCRIPT_NAME}/"
}
#========================= Main ========================#
keystore=
key=
cert=
cert_alias=
passphrase=
int_cert=
while [ $# -gt 0 ]; do
case $1
in
-k | --key)
key=$2
shift 2
;;
-c | --cert)
cert=$2
shift 2
;;
-a | --alias)
cert_alias=$2
shift 2
;;
-s | --keystore)
keystore=$2
shift 2
;;
-p | --passphrase)
passphrase=$2
shift 2
;;
-z | --pkcs12)
pkcs12=$2
shift 2
;;
-d | --pkcs12passphrase)
pkcs12pass=$2
shift 2
;;
-i | --cert-chain)
int_cert=$2
shift 2
;;
-h | --help)
usage
exit 0
;;
*)
die "Unknown option $1"
;;
esac
done
if [[ -z "$key" || -z "$cert" || -z "$cert_alias" ]]; then
if [ -z "$pkcs12" ]; then
usage
exit 1
fi
fi
if [ -z "$pkcs12" ]; then
for file in "$key" "$cert"; do
if [[ -n "$file" && ! -f "$file" ]]; then
die "File $file does not exist"
fi
done
fi
if [ ! -f "$keystore" ]; then
storedir=$(dirname "$keystore")
if [ ! -d "$storedir" ]; then
mkdir -p $storedir
fi
if [ ! -w "$storedir" ]; then
die "Directory $storedir does not exist or is not writable"
fi
fi
if [ -z "$passphrase" ]; then
read -p 'Enter passphrase for keystore $keystore: ' -s passphrase
echo ''
fi
if [ ! -f "$keystore" ]; then
# Directory exists and keystore do not ? Well, in that case, let's create the keystore !
# For that, we create a useless key in that store
keytool \
-genkey \
-alias useless_key \
-dname CN=useless_key \
-keystore "$keystore" \
-keypass "$passphrase" \
-storepass "$passphrase"
keytool \
-delete \
-alias useless_key \
-keystore "$keystore" \
-keypass "$passphrase" \
-storepass "$passphrase"
fi
if [ ! -f "$pkcs12" ]; then
temp_dir=$(mktemp -q -d /tmp/${SCRIPT_NAME}.XXXX)
trap cleanup EXIT
trap '{ cleanup; exit 127; }' INT TERM
pkcs12="${temp_dir}/pkcs12"
pkcs12pass = passphrase
# bundle cert and key in PKCS12
openssl pkcs12 \
-export \
-in "$cert" \
-inkey "$key" \
-out "$pkcs12" \
-password "pass:${passphrase}" \
-name "$cert_alias" \
${int_cert:+-certfile "$int_cert"}
# print cert
echo -n "Importing \"$cert_alias\" with "
openssl x509 -noout -fingerprint -in "$cert"
fi
# import PKCS12 to keystore
keytool \
-importkeystore \
-deststorepass "$passphrase" \
-destkeystore "$keystore" \
-srckeystore "$pkcs12" \
-srcstoretype 'PKCS12' \
-srcstorepass "$pkcs12pass"
# change alias password to be the keystore one
if [ -m "$cert_alias" ]; then
echo "chaning password of $cert_alias"
keytool \
-keypasswd \
-alias "$cert_alias" \
-storepass "$passphrase" \
-keystore "$keystore" \
-keypass "$pkcs12pass" \
-new "$passphrase" \
;
else
echo "no cert alias to change password of"
fi
@Riduidel
Copy link
Author

This fork supports direct injection of certificates from a PKCS12 file, while original file required separated private/public keys

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment