Skip to content

Instantly share code, notes, and snippets.

@darconeous
Created March 17, 2020 21:46
Show Gist options
  • Save darconeous/adb1b2c4b15d3d8fbc72a5097270cdaf to your computer and use it in GitHub Desktop.
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"
@jaredvacanti
Copy link

Thanks to your clarifications, I was able to track down the example attestation certificate in the Fido Alliance's spec page FIDO U2F Raw Message Formats:

Assume we have a U2F token with the following private attestation key:

f3fccc0d00d8031954f90864d43c247f4bf5f0665c6b50cc17749a27d1cf7664

the corresponding public key:

048d617e65c9508e64bcc5673ac82a6799da3c1446682c258c463fffdf58dfd2fa3e6c378b53d795c4a4dffb4199edd7862f23abaf0203b4b8911ba0569994e101

and the following attestation cert:

[
[
Version: V3
Subject: CN=PilotGnubby-0.4.1-47901280001155957352 Signature Algorithm: SHA256withECDSA, OID = 1.2.840.10045.4.3.2
Key: EC Public Key
X:
8d617e65c9508e64bcc5673ac82a6799da3c1446682c258c463fffdf58dfd2fa Y:
3e6c378b53d795c4a4dffb4199edd7862f23abaf0203b4b8911ba0569994e101

Validity: [From: Tue Aug 14 11:29:32 PDT 2012, To: Wed Aug 14 11:29:32 PDT 2013]

Issuer: CN=Gnubby Pilot
SerialNumber: [ 47901280 00115595 7352] ]

Algorithm: [SHA256withECDSA]
Signature:
0000: 30 44 02 20 60 CD B6 06 1E 9C 22 26 2D 1A AC 1D 0D. `....."&-...
0010: 96 D8 C7 08 29 B2 36 65 31 DD A2 68 83 2C B8 36 ....).6e1..h.,.6
0020: BC D3 0D FA 02 20 63 1B 14 59 F0 9E 63 30 05 57 ..... c..Y..c0.W
0030: 22 C8 D8 9B 7F 48 88 3B 90 89 B8 8D 60 D1 D9 79 "....H.;....`..y
0040: 59 02 B3 04 10 DF Y.....
]

...
...

Posting here in case anyone else has the same confusion. Thanks again!

@makkarpov
Copy link

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
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

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

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