![license](https://img.shields.io/github/license/gebogebogebo/ctap-hid-fido2)
![macOS](https://img.shields.io/badge/macOS-Supported-orange)
![Windows](https://img.shields.io/badge/Windows-Supported-orange)
![Raspberry-Pi](https://img.shields.io/badge/Raspberry_Pi-Supported-orange)
# ctap-hid-fido2
Rust FIDO2 CTAP library ( and cli tool [ctapcli](README_ctapcli.md) ).
Authentication using FIDO2-compliant security keys (e.g. Yubikey) is possible.
## Features
- Register and Authenticate.
- Register or change PIN.
- Enrollment and deletion of fingerprints.
- Management of credentials recorded in security keys.
## Version
### Ver 3.5.2
- Dependency Updates.
### Ver 3.5.1
- Dependency Updates.
### Ver 3.5.0
- Specify multiple key_types in MakeCredentialArgsBuilder.
- ED25519 support.
- update dependencies → base64, x509-parser, hidapi, clap, env_logger
- remove dependencies → serde_json, ihex, base64-url
### Ver 3.4.2
- update dependencies → aes, cbc, x509-parser, rpassword
- remove dependencies → block-modes
### Ver 3.4.1
- Bug fix
### Ver 3.4.0
- Update `MakeCredentialArgs`
- change `rkparam` → `user_entity`
- add `resident_key`
- examples → [discoverable credentials/resident-key](https://github.com/gebogebogebo/ctap-hid-fido2/blob/5c8a4c8e9517bf305b41589ddc0343ea3a9ae994/examples/test-with-pin-rk/main.rs#L53-L118)
### Ver 3.3.1
- Implement `Authenticator Confi`g - `force_change_pin()`. → [Authenticator Config(CTAP 2.1)](README_Authenticator_Config.md)
### Ver 3.3.0
- Implement `Credential Blob Extension`. → [Register and Authenticate Examples](README_Register_and_Authenticate.md)
### Ver 3.2.0
- Implement `Authenticator Config` - `set_min_pin_length()`. → [Authenticator Config(CTAP 2.1)](README_Authenticator_Config.md)
- Implement `Set Min Pin Length Extension`. → [Register and Authenticate Examples](README_Register_and_Authenticate.md)
- Implement `Large Blob` → [Large Blob(CTAP 2.1)](README_Large_Blob.md)
### Ver 3.1.0
- Implement `Authenticator Config` - `toggle_always_uv()`. → [Authenticator Config(CTAP 2.1)](README_Authenticator_Config.md)
- add cli tool [ctapcli](README_ctapcli.md)
### Ver 3.0.0
- The usage has changed from Ver2. → [How to Use](#how-to-use).
## How to use Registration and Authentication
```rust
use ctap_hid_fido2::{
fidokey::{GetAssertionArgsBuilder, MakeCredentialArgsBuilder},
verifier, Cfg, FidoKeyHidFactory,
};
fn main() {
let rpid = "reg-auth-example-app";
let pin = get_input_with_message("input PIN:");
println!("Register");
// create `challenge`
let challenge = verifier::create_challenge();
// create `MakeCredentialArgs`
let make_credential_args = MakeCredentialArgsBuilder::new(rpid, &challenge)
.pin(&pin)
.build();
// create `FidoKeyHid`
let device = FidoKeyHidFactory::create(&Cfg::init()).unwrap();
// get `Attestation` Object
let attestation = device
.make_credential_with_args(&make_credential_args)
.unwrap();
println!("- Register Success");
// verify `Attestation` Object
let verify_result = verifier::verify_attestation(rpid, &challenge, &attestation);
if !verify_result.is_success {
println!("- ! Verify Failed");
return;
}
// store Credential Id and Publickey
let userdata_credential_id = verify_result.credential_id;
let userdata_credential_public_key = verify_result.credential_public_key;
println!("Authenticate");
// create `challenge`
let challenge = verifier::create_challenge();
// create `GetAssertionArgs`
let get_assertion_args = GetAssertionArgsBuilder::new(rpid, &challenge)
.pin(&pin)
.credential_id(&userdata_credential_id)
.build();
// get `Assertion` Object
let assertions = device.get_assertion_with_args(&get_assertion_args).unwrap();
println!("- Authenticate Success");
// verify `Assertion` Object
if !verifier::verify_assertion(
rpid,
&userdata_credential_public_key,
&challenge,
&assertions[0],
) {
println!("- ! Verify Assertion Failed");
}
}
pub fn get_input() -> String {
let mut word = String::new();
std::io::stdin().read_line(&mut word).ok();
return word.trim().to_string();
}
pub fn get_input_with_message(message: &str) -> String {
println!("{}", message);
let input = get_input();
println!();
input
}
```
- See [How to use](#How to use) and [Examples](#Examples) for detailed instructions.
## Description
**ctap-hid-fido2** is a crate implementing [CTAP 2.0 and 2.1](https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html), allowing direct control of FIDO2-compliant Authenticators such as Yubikey.
For more information on FIDO, see [FIDO Alliance Page](https://fidoalliance.org/).
- Implements FIDO2 CTAP 2.0 & 2.1 (HID)
- [Client to Authenticator Protocol (CTAP)](https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html)
- Supported FIDO key
- [Yubikey Bio](https://www.yubico.com/products/yubikey-bio-series/)
- [Yubikey](https://www.yubico.com/products/)
- FEITIAN ePass FIDO(A4B)
- FEITIAN BioPass K27 USB Security Key
- FEITIAN AllinPass FIDO2 K33
- [SoloKey](https://github.com/solokeys/solo)
- [Nitrokey FIDO2](https://www.nitrokey.com/)
- [OpenSK](https://github.com/google/OpenSK)
- Idem Key
## Author
gebo
## Build and run
#### macOS
Nothing in particular to worry about using it.
#### Windows
- **Run as administrator**
In Windows, the security key via HID cannot be accessed unless the executing exe has administrator privileges.
#### raspberry Pi
- **installing `libusb` and `libudev` package**
(The same may be true for Linux, such as Ubuntu)
If you get the following error with the libusb-1.0 dependency and cannot build, you can solve the problem by doing the following.
```sh
sudo apt install -y libusb-1.0-0-dev libudev-dev
```
## How to use
**PIN has to be set**
Unless noted in the following Examples, a PIN must be set in the Authenticator.
**create FidoKeyHid object**
First, create a device object with `FidoKeyHidFactory::create`.
If no Authenticator can be detected on the HID device, an error will result.
```rust
use ctap_hid_fido2::{Cfg, FidoKeyHidFactory};
...
let device = match FidoKeyHidFactory::create(&Cfg::init()) {
Ok(d) => d,
Err(e) => {
println!("error: {:?}", e);
return;
}
};
```
If more than one Authenticator is detected, an error will result. See the following description for **Multi-Authenticator support**
**Cfg**
The argument `Cfg` is fine with the default value you create using `init()`, but you can customize it to change the behavior a bit, see [Cfg definition](https://github.com/gebogebogebo/ctap-hid-fido2/blob/24df395e4ce1c3bcacdba69c63fc3a8ff5510d2c/src/lib.rs#L39-L55).
**FidoKeyHid**
Use Authenticator with the methods implemented in `FidoKeyHid`.
For example, `get_pin_retries()` can be used to obtain the number of PIN retries.
```rust
match device.get_pin_retries() {
Ok(retry) => println!("{}", retry),
Err(e) => println!("error: {:?}", e),
}
```
**Multi-Authenticator support**
If you have multiple Authenticators connected to the HID and want to control each device individually, use `get_fidokey_devices()` and `create_by_params()`.
```rust
let devs = ctap_hid_fido2::get_fidokey_devices();
for dev in devs {
println!("- vid=0x{:04x} , pid=0x{:04x} , info={:?}",dev.vid, dev.pid, dev.info);
let fidokey = FidoKeyHidFactory::create_by_params(&vec![dev.param], &Cfg::init()).unwrap();
let info = fidokey.get_info().unwrap();
println!("{}", info);
}
```
## Examples
See the following links for examples of various patterns.
- [Register and Authenticate Examples](README_Register_and_Authenticate.md)
- [Get Authenticator info and Util Examples](README_Get_Info.md)
- [Credential management (CTAP 2.1)](README_Credential_management.md)
- [Biometric management (CTAP 2.1)](README_Biometric_management.md)
- [Authenticator Config(CTAP 2.1)](README_Authenticator_Config.md)
- [Large Blob(CTAP 2.1)](README_Large_Blob.md)
## CLI tool
CLI tool can be used.
- [ctapcli](README_ctapcli.md)