Skip to content

FIDO command line utility

Martin Paljak edited this page Dec 13, 2022 · 6 revisions

Working with FIDO2/U2F devices from command line

Download fido.jar (for all machines with Java 17+) or fido.exe for Windows machines from Release area

alias fido="java -jar ~/Downloads/fido.jar"

Notes:

  • Windows requires administrator rights. UAC is supported, but recommendation is to run the terminal/console as Administrator
  • Linux does not support USB HID device auto-selection, must always specify the exact device path to use. Communication is also not stable. See #8
  • macOS requires Intel Java also on Apple Silicon machines, due to hid4java/hidapi architecture. See #8

Feature overview/status

  • Algorithms supported (creating, using, listing): P-256, Ed25519
  • Biometric enrolment will be added after v1.0

Environment variables:

  • $FIDO_USB_DEVICE - default argument for -U
  • $FIDO_NFC_DEVICE - default argument for -N
  • $FIDO_PIN - default argument for -pin
  • $FIDO_TRACE - set to true to show exception traces in debug mode

Device selection

By default attached HID authenticator is used.

To use a NFC reader, use

fido -N [<optional PC/SC reader name>]

If you have multiple readers, list them with fido -N:

$ fido -N
PC/SC readers:
- Yubico YubiKey FIDO+CCID 01
- Yubico YubiKey FIDO+CCID
- ACS ACR1252 Dual Reader

If you have many USB HID authenticators, you can specify one with

fido -U <HID device name or path (Linux)>

If you have multiple FIDO USB tokens connected, list them with fido -U:

$ fido -U
USB HID devices:
- Solo 4.1.5 (v0.0.0 by SoloKeys, supporting U2F_V2, FIDO_2_0)
- YubiKey FIDO (v5.5.6 by Yubico, supporting U2F_V2, FIDO_2_0)
- Yubikey 4 U2F+CCID (v4.3.7 by Yubico, supporting U2F_V2)

Working with U2F/FIDO2 combo devices.

By default FIDO2 is preferred. For combo devices specify -1/--u2f to force U2F when registering or authenticating. Only a subset of options is supported via U2F.

Get authenticator info

fido -i

Example with a YubiKey FIDO BIO Nano:

$ fido -U "yubikey fido" -i                                                          
YubiKey FIDO (v5.5.6, [U2F_V2, FIDO_2_0])
{
  versions : [ "U2F_V2", "FIDO_2_0", "FIDO_2_1_PRE", "FIDO_2_1" ],
  extensions : [ "credProtect", "hmac-secret", "largeBlobKey", "credBlob", "minPinLength" ],
  aaguid : "16 d8522d9f575b486688a9ba99fa02f35b",
  options : {
    rk : true,
    up : true,
    uv : true,
    plat : false,
    uvToken : true,
    alwaysUv : true,
    credMgmt : true,
    authnrCfg : true,
    bioEnroll : true,
    clientPin : true,
    largeBlobs : true,
    pinUvAuthToken : true,
    setMinPINLength : true,
    makeCredUvNotRqd : false,
    credentialMgmtPreview : true,
    userVerificationMgmtPreview : true
  },
  maxMsgSize : 1200,
  pinUvAuthProtocols : [ 2, 1 ],
  maxCredentialCountInList : 8,
  maxCredentialIdLength : 128,
  transports : [ "usb" ],
  algorithms : [ {
    alg : -7,
    type : "public-key"
  }, {
    alg : -8,
    type : "public-key"
  } ],
  maxSerializedLargeBlobArray : 1024,
  forcePINChange : false,
  minPINLength : 4,
  firmwareVersion : 328966,
  maxCredBlobLength : 32,
  maxRPIDsForSetMinPINLength : 1,
  preferredPlatformUvAttempts : 3,
  uvModality : 2,
  remainingDiscoverableCredentials : 23
}

With X-FIDO applet over NFC reader:

$ fido -N 1252 -i -debug                                                                                                                                        
SCardConnect("ACS ACR1252 Dual Reader", T=*) -> T=1, 3B8980015343453720000020204A
A>> T=1 (4+0008) 00A40400 08 A0000006472F0001 00
A<< (0006+2) (339ms) 5532465F5632 9000
>> authenticatorGetInfo
A>> T=1 (4+0001) 80100000 000001 04 0000
A<< (0177+2) (37ms) 00AC0183665532465F5632684649444F5F325F306C4649444F5F325F315F50524502826B6372656450726F746563746B686D61632D7365637265740350AC5EBF97149E4B1C977300DB72D399E204A662726BF5627570F5627576F464706C6174F469636C69656E7450696EF47563726564656E7469616C4D676D7450726576696577F50519025806810107080818400981636E66630A81A263616C672664747970656A7075626C69632D6B65790D060E0D 9000
<< CTAP1_ERR_SUCCESS
{
  versions : [ "U2F_V2", "FIDO_2_0", "FIDO_2_1_PRE" ],
  extensions : [ "credProtect", "hmac-secret" ],
  aaguid : "16 ac5ebf97149e4b1c977300db72d399e2",
  options : {
    rk : true,
    up : true,
    uv : false,
    plat : false,
    clientPin : false,
    credentialMgmtPreview : true
  },
  maxMsgSize : 600,
  pinUvAuthProtocols : [ 1 ],
  maxCredentialCountInList : 8,
  maxCredentialIdLength : 64,
  transports : [ "nfc" ],
  algorithms : [ {
    alg : -7,
    type : "public-key"
  } ],
  minPINLength : 6,
  firmwareVersion : 13
}
SCardDisconnect("ACS ACR1252 Dual Reader", true) tx:24/rx:161 in 410ms

Register / make a credential

Use -r/--register. It takes parameter in the form of user@domain. Domain is used as RP ID or AppID for U2F. FIDO2 UID can be specified with --uid <uid in hex> (by default the username part is hashed with SHA-256 to get the user ID)

Here's an example to make a resident credential, store associated public key into lisa-pubkey.txt and credential ID into lisa-credential.txt

$ fido -r lisa@example.com -rk -debug -pubkey lisa-pubkey.txt -credential lisa-credential.txt -pin 123456
>> authenticatorClientPIN
{
  pinProtocol : 1,
  subCommand : 2
}
<< CTAP1_ERR_SUCCESS
{
  keyAgreement : {
    1 : 2,
    3 : -25,
    -1 : 1,
    -2 : "32 5190fb983a8fb6edffee074347418577675b640988abbfa667f1dad5cc3ad7e8",
    -3 : "32 eefe2d4a784ed62e0789ee7ae4b7b6fc7a20227a80cee9a9558c6de496e3a2b8"
  }
}
>> authenticatorClientPIN
{
  pinProtocol : 1,
  subCommand : 5,
  keyAgreement : {
    1 : 2,
    3 : -25,
    -1 : 1,
    -2 : "32 7f46abfd7bd3d29eb175dac6ac9b4d8cdb704b3470f739c92956904db17cf7de",
    -3 : "32 9b69c51d2d670161ff08eb16169b91dbac6ec837ce069baeb5c30d6c69ba23c8"
  },
  pinHashEnc : "16 138997a4e89f5bb82010cec097fc0d8e"
}
<< CTAP1_ERR_SUCCESS
{
  pinToken : "32 eebbd6b5d192b47c6e506397d8bdc386c7f92c104466113698fad43c4cddae2d"
}
>> authenticatorMakeCredential
{
  clientDataHash : "32 1edc30ad6ea2033bc83473dbd4c2641c5d946371b0ad4c28bd056ed2e5f2a9fb",
  rp : {
    id : "example.com",
    name : "example.com"
  },
  user : {
    id : "32 d84fe7e07bedb227cffff10009151d96fc944f6a1bd37cff60e8e4626a1eb1c3",
    name : "lisa"
  },
  pubKeyCredParams : [ {
    alg : -7,
    type : "public-key"
  } ],
  options : {
    rk : true
  },
  pinAuth : "16 e69fbd4fb86742167f19a62c5e912a32",
  pinProtocol : 1
}
Are you there? Make touch!
<< CTAP1_ERR_SUCCESS
{
  fmt : "packed",
  authData : "180 a379a6f6eeafb9a55e378c118034e2751e682fab9f2d30ab13d2125586ce19474500000002ee882879721c491397753dfcce97072a0030c7d3e1113a1d7e908bec9b23e556bfc249b59c82cbb25d431bc15fa97cd0e5b6422e8ebaa6b577d769caa12544d8dd23a5010203262001215820c7d3e1113a1d7e908bec9b23e5e87cc3c3a483c7e465a192c61f8f6e93dd85e32258203c22ca7e59aae37480a16efe499518900127e03344b5694dd4d2628872ab1bae",
  attStmt : {
    alg : -7,
    sig : "72 30460221009a4c808445bd2f05048d0487799e090992c3e1d073a3857887bf16f4562d27c4022100b92ec6f69cd09b61b1c7622d2988808ec35dd1ec6d2d943d98ab3a4c8bc44b0c",
    x5c : [ "733 308202d9308201c1a003020102020900defb7d43e133925a300d06092a864886f70d01010b0500302e312c302a0603550403132359756269636f2055324620526f6f742043412053657269616c203435373230303633313020170d3134303830313030303030305a180f32303530303930343030303030305a306f310b300906035504061302534531123010060355040a0c0959756269636f20414231223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e3128302606035504030c1f59756269636f205532462045452053657269616c20313133323332393935303059301306072a8648ce3d020106082a8648ce3d03010703420004cc75603d960c924b9f41f8883cfe6d5aec2096480a67407b4cae0c6dc5224cbdcf445c2e53a3cbaf2f6883b6c63f404039751b2d915f12b71c881069df146e8aa38181307f3013060a2b0601040182c40a0d0104050403050403302206092b0601040182c40a020415312e332e362e312e342e312e34313438322e312e373013060b2b0601040182e51c0201010404030205203021060b2b0601040182e51c01010404120410ee882879721c491397753dfcce97072a300c0603551d130101ff04023000300d06092a864886f70d01010b05000382010100476dcc1ebbcaac543b25ed04c674598b063e9b9b94aa3a8fcd015c555a46a504a6f92c9d69c9f89c0782dbc7e9e03629ba4d6eee68e77602ad8a1e265a053647275632d2e8cec3df4597a3c747e33461b96bb4a72944b8677813bf9b528ad82419d87dffd1f67a1f24fc37eb23a9b9ac4566e5a6624c6fa48eeb13ba4b448a30d788ce066fc30c39dfc478506612945a187a5065025281eb1d8ce35d9dceb7b8cedd8036a724ba807cdcc2c682386a396ecf7be374a578c7bcf22a5dd277e67faa88ff1bea99d1161b1f2c7049b3ad4811fd163d4e2e242af82cfd7c1110f14a447dc6d434c3d5b88a5d75647e1c0e2dd3c56f45ec35f1e959c2349207c1f482" ]
  }
}
{
  rpIdHash : "a379a6f6eeafb9a55e378c118034e2751e682fab9f2d30ab13d2125586ce1947",
  flags : [ "UP", "AT" ],
  counter : 2,
  attestation : {
    aaguid : "ee882879-721c-4913-9775-3dfcce97072a",
    credentialID : "c7d3e1113a1d7e908bec9b23e556bfc249b59c82cbb25d431bc15fa97cd0e5b6422e8ebaa6b577d769caa12544d8dd23",
    publicKey : {
      crv : "P-256",
      kty : "EC",
      x : "c7d3e1113a1d7e908bec9b23e5e87cc3c3a483c7e465a192c61f8f6e93dd85e3",
      y : "3c22ca7e59aae37480a16efe499518900127e03344b5694dd4d2628872ab1bae"
    }
  }
}

Authenticate / get assertion with credential

Use -a/--authenticate. Specify the public key with -pubkey <pubkey file or key in hex> to verify the assertion. Specify the credential to use (if not using discoverable credentials) with -credential <file or credential in hex>

$ fido -a lisa@example.com -debug -pubkey lisa-pubkey.txt
>> authenticatorGetAssertion
{
  rpId : "example.com",
  clientDataHash : "32 91bcca732c5babf113a658603f4f9b4446e0bf63915f645e2d08c4d103356bcd",
  options : {
    up : true
  }
}
Are you there? Make touch!
<< CTAP1_ERR_SUCCESS
{
  credential : {
    id : "48 c7d3e1113a1d7e908bec9b23e556bfc249b59c82cbb25d431bc15fa97cd0e5b6422e8ebaa6b577d769caa12544d8dd23",
    type : "public-key"
  },
  authData : "37 a379a6f6eeafb9a55e378c118034e2751e682fab9f2d30ab13d2125586ce1947010000000d",
  signature : "71 30450221008c303a094518ca2a1ee3448aa6718e2e0a15c35b9ccf198a5da360ac50e8949a02204e17f8f4b0bad2b7c5df2ed8a0150bf871c5a04d147e1ed55a69cde3c78f7243",
  publicKeyCredentialUserEntity : {
    id : "32 d84fe7e07bedb227cffff10009151d96fc944f6a1bd37cff60e8e4626a1eb1c3"
  }
}
Authenticator data: 
{
  rpIdHash : "a379a6f6eeafb9a55e378c118034e2751e682fab9f2d30ab13d2125586ce1947",
  flags : [ "UP" ],
  counter : 13
}
Verified OK

List credentials stored in authenticator (discoverable / resident keys) NB! FIDO_2_1_PRE style

Use -l/--list. Requires PIN.

Example (-debug omitted for brevity):

$ fido -l -pin 123456                                  
Found 1 credentials, 24 slots remaining:
- lisa@example.com

To delete a credential, specify its ID or try a username@domain pair:

fido -delete lisa@example.com

X-FIDO commands

Commands can be generalized for all other objects/documents described in profile.

Get PIN config (the pin document):

$ fido -G pin
CBOR >>>
{
  get : "pin"
}
CBOR <<<
{
  pin : {
    managed : false,
    change : false,
    destruct : false,
    tries : 8,
    policy : {
      min : 4,
      max : 63,
      allow_lower : true,
      require_lower : false,
      allow_upper : true,
      require_upper : false,
      allow_number : true,
      require_number : false,
      allow_special : true,
      require_special : false
    }
  }
}

Set pin.change to true

$ fido -T localhost:3333 -S pin.change=true # OR -S '{pin: {change: true}}'
CBOR >>>
{
  set : {
    pin : {
      change : true
    }
  }
}
CBOR <<<
{
  pin : {
    managed : false,
    change : true,
    destruct : false,
    tries : 8,
    policy : {
      min : 4,
      max : 63,
      allow_lower : true,
      require_lower : false,
      allow_upper : true,
      require_upper : false,
      allow_number : true,
      require_number : false,
      allow_special : true,
      require_special : false
    }
  }
}

Available commands

$ fido --help
Option                                           Description                       
------                                           -----------                       
-1, --u2f                                        Force use of U2F                  
-D, --del, --x-del <String: msg>                 Send {del: ...}                   
-G, --get, --x-get <String: msg>                 Send {get: ...}                   
-N, --nfc [String: reader]                       Use specific NFC reader           
-S, --set, --x-set <String: msg>                 Send {set: ...}                   
-T, --tcp [String: host:port]                    Use APDU over TCP (test)          
-U, --usb [String: name/path]                    Use specific USB HID device       
-V, --version                                    Show program version              
-W, --wink                                       Wink ;)                           
-a, --authenticate <String: [user@]domain>       Get assertion / authenticate      
-c, --credential <String: hex/b64url/file>       Credential ID                     
--cdh, --client-data-hash <String: hex/b64url>   Client data hash                  
--change-pin <String: new PIN>                   Set new PIN (FIDO2)               
-d, --debug                                      Show wire traces                  
--discoverable, --rk                             Discoverable (FIDO2)              
--ed25519                                        Use Ed25519 keys                  
-h, --help                                       Show information about the program
--hmac-secret [String: hex]                      Use hmac-secret (FIDO2)           
-i, --info                                       Get info (FIDO2)                  
--k256, --secp256k1                              Use Bitcoin keys                  
-l, --list-credentials                           List credentials (pre)            
--no-presence, --no-up                           Do not require UP (touch)         
-p, --pin [String: PIN]                          Use PIN (FIDO2)                   
--p256, --secp256r1                              Use P-256 keys                    
--protect <Integer>                              Use credProtect (FIDO2)           
--pubkey <String: value/file>                    Credential public key             
-r, --register <String: [user@]domain>           Make credential / register        
--uid <String: value/file>                       User identifier                   
--uv, --verification                             Do UV (PIN/biometrics)            
-v, --verbose                                    Show CBOR messages                
--x-auth-gp-key <String: hex/file>               Use GP key                        
--x-auth-key <String: hex/file>                  Use key for auth                  
--x-auth-origin <String: domain>                 Use origin for auth               

More information: https://github.com/martinpaljak/FIDO2
Clone this wiki locally