8 releases (4 stable)

Uses old Rust 2015

1.2.0 Nov 25, 2019
1.1.0 Sep 3, 2019
1.0.1 Feb 25, 2018
1.0.0 Dec 5, 2017
0.1.0-alpha4 Jan 28, 2017

#456 in Hardware support

Download history 2512/week @ 2023-11-20 2604/week @ 2023-11-27 2275/week @ 2023-12-04 2004/week @ 2023-12-11 2187/week @ 2023-12-18 933/week @ 2023-12-25 1297/week @ 2024-01-01 1775/week @ 2024-01-08 2891/week @ 2024-01-15 2486/week @ 2024-01-22 2047/week @ 2024-01-29 2358/week @ 2024-02-05 3789/week @ 2024-02-12 2861/week @ 2024-02-19 3721/week @ 2024-02-26 4018/week @ 2024-03-04

14,505 downloads per month
Used in 39 crates (3 directly)

MIT license

21KB
380 lines

pcsc-rust

crates.io docs.rs license

Linux, macOS, Windows:

Rust bindings to the PC/SC API for smart card communication.

  • Nice, safe API.
  • Tested on Linux, Windows, macOS.
  • Mostly zero overhead.

See the Documentation for more details.

See the pcsc/examples directory for some common tasks.

Contents

The pcsc-sys crate contains direct, low-level bindings to the C API.

The pcsc crate contains high-level Rust wrappers.

Usage

In your Cargo.toml:

[dependencies]
pcsc = "2"

Example

Connect to the card in the first available reader, send the card an APDU command, print the APDU response.

use pcsc::*;

fn main() {
    // Establish a PC/SC context.
    let ctx = match Context::establish(Scope::User) {
        Ok(ctx) => ctx,
        Err(err) => {
            eprintln!("Failed to establish context: {}", err);
            std::process::exit(1);
        }
    };

    // List available readers.
    let mut readers_buf = [0; 2048];
    let mut readers = match ctx.list_readers(&mut readers_buf) {
        Ok(readers) => readers,
        Err(err) => {
            eprintln!("Failed to list readers: {}", err);
            std::process::exit(1);
        }
    };

    // Use the first reader.
    let reader = match readers.next() {
        Some(reader) => reader,
        None => {
            println!("No readers are connected.");
            return;
        }
    };
    println!("Using reader: {:?}", reader);

    // Connect to the card.
    let card = match ctx.connect(reader, ShareMode::Shared, Protocols::ANY) {
        Ok(card) => card,
        Err(Error::NoSmartcard) => {
            println!("A smartcard is not present in the reader.");
            return;
        }
        Err(err) => {
            eprintln!("Failed to connect to card: {}", err);
            std::process::exit(1);
        }
    };

    // Send an APDU command.
    let apdu = b"\x00\xa4\x04\x00\x0A\xA0\x00\x00\x00\x62\x03\x01\x0C\x06\x01";
    println!("Sending APDU: {:?}", apdu);
    let mut rapdu_buf = [0; MAX_BUFFER_SIZE];
    let rapdu = match card.transmit(apdu, &mut rapdu_buf) {
        Ok(rapdu) => rapdu,
        Err(err) => {
            eprintln!("Failed to transmit APDU command to card: {}", err);
            std::process::exit(1);
        }
    };
    println!("APDU response: {:?}", rapdu);
}

Example output:

$ ./target/debug/examples/readme
Using reader: "SCM Microsystems Inc. SCR 355 [CCID Interface] 00 00"
Sending APDU: [0, 164, 4, 0, 10, 160, 0, 0, 0, 98, 3, 1, 12, 6, 1]
APDU response: [106, 130]

License

The MIT license.


lib.rs:

Low level bindings to the PCSC C API.

The following platforms are supported:

  • On Windows, the built-in WinSCard.dll library and "Smart Card" service. See MSDN for documentation of the implemented API.

  • On macOS, the built-in PCSC framework.

  • On Linux, BSDs and (hopefully) other systems, the PCSC lite library and pcscd daemon. See pcsclite for documentation of the implemented API.

    pcsclite is detected at build time using pkg-config. See the pkg-config crate for more information.

    If you do not want to use pkg-config, you may instead export the following environment variables when building the crate:

    • PCSC_LIB_DIR: A directory in which to search for a dynamic library implementing the PCSC API.
    • PCSC_LIB_NAME: The name of the library. Defaults to pcsclite.

Dependencies