Skip to content

Instantly share code, notes, and snippets.

@darconeous
Created March 17, 2020 21:46
Show Gist options
  • Select an option

  • Save darconeous/adb1b2c4b15d3d8fbc72a5097270cdaf to your computer and use it in GitHub Desktop.

Select an option

Save darconeous/adb1b2c4b15d3d8fbc72a5097270cdaf to your computer and use it in GitHub Desktop.
Installer script for ledger-u2f-javacard
#!/bin/sh
GP=${GP-java -jar gp.jar}
set -v
set -e
# This is for the ACR122U to put it into
# a nice state where it won't time out on us.
$GP -d -v -a ff0041ff00 -a ff00520000 || true
$GP -d -v \
--uninstall U2FApplet.cap
$GP -d -v \
--install U2FApplet.cap \
--create A0000006472F0001 \
--params "000140f3fccc0d00d8031954f90864d43c247f4bf5f0665c6b50cc17749a27d1cf7664"
$GP -d -v \
-a "00 A4 04 00 08 A0 00 00 06 47 2F 00 01" \
-a "80 01 00 00 80 30 82 01 3c 30 81 e4 a0 03 02 01 02 02 0a 47 90 12 80 00 11 55 95 73 52 30 0a 06 08 2a 86 48 ce 3d 04 03 02 30 17 31 15 30 13 06 03 55 04 03 13 0c 47 6e 75 62 62 79 20 50 69 6c 6f 74 30 1e 17 0d 31 32 30 38 31 34 31 38 32 39 33 32 5a 17 0d 31 33 30 38 31 34 31 38 32 39 33 32 5a 30 31 31 2f 30 2d 06 03 55 04 03 13 26 50 69 6c 6f 74 47 6e 75 62 62 79 2d 30 2e 34 2e 31 2d 34 37 39 30" \
-a "80 01 00 80 80 31 32 38 30 30 30 31 31 35 35 39 35 37 33 35 32 30 59 30 13 06 07 2a 86 48 ce 3d 02 01 06 08 2a 86 48 ce 3d 03 01 07 03 42 00 04 8d 61 7e 65 c9 50 8e 64 bc c5 67 3a c8 2a 67 99 da 3c 14 46 68 2c 25 8c 46 3f ff df 58 df d2 fa 3e 6c 37 8b 53 d7 95 c4 a4 df fb 41 99 ed d7 86 2f 23 ab af 02 03 b4 b8 91 1b a0 56 99 94 e1 01 30 0a 06 08 2a 86 48 ce 3d 04 03 02 03 47 00 30 44 02 20 60 cd" \
-a "80 01 01 00 40 b6 06 1e 9c 22 26 2d 1a ac 1d 96 d8 c7 08 29 b2 36 65 31 dd a2 68 83 2c b8 36 bc d3 0d fa 02 20 63 1b 14 59 f0 9e 63 30 05 57 22 c8 d8 9b 7f 48 88 3b 90 89 b8 8d 60 d1 d9 79 59 02 b3 04 10 df"
@makkarpov
Copy link
Copy Markdown

makkarpov commented Aug 29, 2021

I made an extended version of script that will generate really private private keys and corresponding attestation cert:

#!/bin/bash

function usage {
  echo "usage: $0 <cap file> <gp jar> <certificate subject> [extra gp args...]" >&2
  echo "" >&2
  echo "Generates fresh key and certificate, installs applet on a card and" >&2
  echo "uploads a certificate, giving you ready-to-use card" >&2
  echo "" >&2
  echo "If you have a locked card, specify extra arguments like '--key XXX'" >&2
  exit 2
}

if [ -z "$1" -o -z "$2" -o -z "$3" ]; then
  usage
fi

CAP_FILE="$1"
GP_JAR="$2"
CERT_SUBJECT="$3"
shift 3

echo "++ Generating keys and certificates..."

set -e # make shell exit on errors

[ -d "certs" ] || mkdir certs
[ -f "certs/private.pem" ] || openssl ecparam -genkey -name P-256 -out "certs/private.pem"

## Extract OpenSSL config: config is needed to avoid space-consuming extensions like "Subject key info"
if [ ! -f "certs/config.conf" ]; then
  base64 -d <<EOF | gzip -d > "certs/config.conf"
H4sIAJrPK2ECA22MQQqAMAwE73lF/+DZl5QSxC4axFSbKvb3VjzqdWZnvcvYXaAoVkSnQ2xGZB1W
uP5R/BX0YFwFapLU2u7suDGCjjVvhRfUBjUR+f+HQP5NAt0Vsx1wgAAAAA==
EOF
fi

# Generate self-signed cert
[ -f "certs/cert.crt" ] || openssl req -x509 -config "certs/config.conf" -key "certs/private.pem" \
  -sha256 -days 36500 -nodes -out "certs/cert.crt" -subj "/CN=$CERT_SUBJECT"
  
# Convert from PEM to DER
openssl x509 -in "certs/cert.crt" -outform DER -out "certs/cert.cer"

# Convert private key to just 32 raw bytes
PRIVATE_KEY=$(openssl ec -in "certs/private.pem" -text 2>/dev/null | grep -A 3 priv: | tail -n +2 | tr -d ':[:space:]')
CERT_LENGTH=$(stat --printf "%s" "certs/cert.cer")

echo "++ Installing everything on card..."

function gp {
  echo "+ java -jar \"$GP_JAR\" $@"
  java -jar "$GP_JAR" $@
}

gp "$@" \
  --install "$CAP_FILE" \
  --create A0000006472F0001 \
  --params "00$(printf "%04x" "$CERT_LENGTH")$PRIVATE_KEY"

OFFSET=0
FRAGMENT=64
APDUS=(--apdu "00A4040008A0000006472F0001")

while [ "$OFFSET" -lt "$CERT_LENGTH" ]; do
  CERT_CHUNK=$(dd if="certs/cert.cer" bs=1 skip="$OFFSET" count="$FRAGMENT" status=none | xxd -p -c 9999)
  CHUNK_LENGTH=$(($(echo "$CERT_CHUNK" | wc -c) / 2))
  APDUS=(${APDUS[@]} --apdu "8001$(printf "%04x%02x" "$OFFSET" "$CHUNK_LENGTH")$CERT_CHUNK")  
  OFFSET=$(($OFFSET+$FRAGMENT))
done

# Install the certificate
gp ${APDUS[@]}

@darconeous
Copy link
Copy Markdown
Author

I made an extended version of script that will generate really private private keys and corresponding attestation cert:

That's really cool! Thanks for writing that up!

One of the reasons why I avoid doing this for my own tokens is that it makes the token uniquely identifiable across services, which is something I was trying to avoid.

@makkarpov
Copy link
Copy Markdown

Well, homebrew U2F token is sufficiently unique on it's own :)

@ROZcloud
Copy link
Copy Markdown

ROZcloud commented May 8, 2026

Script for windows

This script works on Windows, you need to place it in the directory with the files gp.exe and U2FAApplet.cap
To use the script, copy and paste it into script.cmd and run it in the appropriate directory.

This applet is compatible according to the table

Card System Support
J3R??? Windows
J3R??? Linux
J3R??? MacOS ⚠️
J3R??? Android

Script

gp.exe -d -v --install U2FApplet.cap --create A0000006472F0001 --params "000140f3fccc0d00d8031954f90864d43c247f4bf5f0665c6b50cc17749a27d1cf7664"

gp.exe -d -v -a "00 A4 04 00 08 A0 00 00 06 47 2F 00 01" -a "80 01 00 00 80 30 82 01 3c 30 81 e4 a0 03 02 01 02 02 0a 47 90 12 80 00 11 55 95 73 52 30 0a 06 08 2a 86 48 ce 3d 04 03 02 30 17 31 15 30 13 06 03 55 04 03 13 0c 47 6e 75 62 62 79 20 50 69 6c 6f 74 30 1e 17 0d 31 32 30 38 31 34 31 38 32 39 33 32 5a 17 0d 31 33 30 38 31 34 31 38 32 39 33 32 5a 30 31 31 2f 30 2d 06 03 55 04 03 13 26 50 69 6c 6f 74 47 6e 75 62 62 79 2d 30 2e 34 2e 31 2d 34 37 39 30" -a "80 01 00 80 80 31 32 38 30 30 30 31 31 35 35 39 35 37 33 35 32 30 59 30 13 06 07 2a 86 48 ce 3d 02 01 06 08 2a 86 48 ce 3d 03 01 07 03 42 00 04 8d 61 7e 65 c9 50 8e 64 bc c5 67 3a c8 2a 67 99 da 3c 14 46 68 2c 25 8c 46 3f ff df 58 df d2 fa 3e 6c 37 8b 53 d7 95 c4 a4 df fb 41 99 ed d7 86 2f 23 ab af 02 03 b4 b8 91 1b a0 56 99 94 e1 01 30 0a 06 08 2a 86 48 ce 3d 04 03 02 03 47 00 30 44 02 20 60 cd" -a "80 01 01 00 40 b6 06 1e 9c 22 26 2d 1a ac 1d 96 d8 c7 08 29 b2 36 65 31 dd a2 68 83 2c b8 36 bc d3 0d fa 02 20 63 1b 14 59 f0 9e 63 30 05 57 22 c8 d8 9b 7f 48 88 3b 90 89 b8 8d 60 d1 d9 79 59 02 b3 04 10 df"

Windows does not support FIDO2 or U2F on Smart Cards, it only supports USB HID

@ROZcloud
Copy link
Copy Markdown

ROZcloud commented May 9, 2026

All functions work, I recommend testing on Android with NFC

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