Skip to content

A comprehensive Java library for interacting with PKCS#11 (Cryptoki) compatible hardware security modules (HSMs) and smart cards. This wrapper simplifies cryptographic operations while maintaining high security standards.

License

Notifications You must be signed in to change notification settings

SimpleMethod/PKCS11-Java-Wrapper

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

17 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ” PKCS11 Java Wrapper

πŸ“š Table of Contents

🌟 Introduction

Welcome to the PKCS11 Java Wrapper! This comprehensive Java library provides a robust and user-friendly interface for interacting with PKCS#11 (also known as Cryptoki) compatible hardware security modules (HSMs) and smart cards. Our project aims to simplify cryptographic operations while maintaining the highest security standards.

πŸš€ Features

  • πŸ”’ Secure initialization and management of PKCS#11 sessions
  • πŸ”‘ Key and certificate management
  • πŸ“ Digital signature creation and verification
  • πŸ” Data encryption and decryption
  • 🧰 Utility functions for common PKCS#11 operations
  • πŸ›‘οΈ Comprehensive exception handling for robust error management
  • πŸ“± Multi-device support with hot-plug capabilities
  • πŸ”„ Automatic device state monitoring
  • 🎯 Device filtering by capabilities and state
  • πŸ§ͺ Extensive test coverage ensuring reliability

πŸ“‚ Project Structure

Root:.
β”œβ”€β”€β”€lib
β”‚       // OpenSC and other PKCS#11 libraries
β”œβ”€β”€β”€src
β”‚   β”œβ”€β”€β”€main
β”‚   β”‚   β”œβ”€β”€β”€java
β”‚   β”‚   β”‚   └───pl
β”‚   β”‚   β”‚       └───mlodawski
β”‚   β”‚   β”‚           └───security
β”‚   β”‚   β”‚               β”œβ”€β”€β”€example
β”‚   β”‚   β”‚               β”‚       PKCS11Example.java
β”‚   β”‚   β”‚               └───pkcs11
β”‚   β”‚   β”‚                   β”‚   PKCS11Crypto.java
β”‚   β”‚   β”‚                   β”‚   PKCS11Initializer.java
β”‚   β”‚   β”‚                   β”‚   PKCS11DeviceManager.java
β”‚   β”‚   β”‚                   β”‚   PKCS11Manager.java
β”‚   β”‚   β”‚                   β”‚   PKCS11Session.java
β”‚   β”‚   β”‚                   β”‚   PKCS11Signer.java
β”‚   β”‚   β”‚                   β”‚   PKCS11Utils.java
β”‚   β”‚   β”‚                   β”œβ”€β”€β”€exceptions
β”‚   β”‚   β”‚                   β”‚       // Various exception classes
β”‚   β”‚   β”‚                   └───model
β”‚   β”‚   β”‚                           CertificateInfo.java
β”‚   β”‚   β”‚                           DeviceCapability.java
β”‚   β”‚   β”‚                           DeviceChangeListener.java
β”‚   β”‚   β”‚                           DeviceState.java
β”‚   β”‚   β”‚                           KeyCertificatePair.java
β”‚   β”‚   β”‚                           PKCS11Device.java
β”‚   β”‚   β”‚                           SupportedAlgorithm.java
β”‚   └───test
β”‚       └───java
β”‚           └───pl
β”‚               └───mlodawski
β”‚                   └───security
β”‚                       └───pkcs11
β”‚                               // Test classes for each main class

🏁 Getting Started

Prerequisites

  • Java Development Kit (JDK) 21 or higher
  • Maven 4.0.0 or higher
  • A PKCS#11 compatible hardware security module or smart card
  • The appropriate PKCS#11 library for your device (e.g., opensc-pkcs11.dll)

Installation

  1. Clone the repository:

    git clone https://github.com/SimpleMethod/PKCS11-Java-Wrapper.git
    
  2. Navigate to the project directory:

    cd PKCS11-Java-Wrapper
    
  3. Build the project using Maven:

    mvn clean install
    

πŸ–₯️ Usage

Basic Example

Here's a basic example of how to use the PKCS11 Java Wrapper:

import pl.mlodawski.security.pkcs11.*;
import java.nio.file.Paths;

public class PKCS11Example {
    public static void main(String[] args) {
        try (PKCS11Manager manager = new PKCS11Manager(Paths.get("path/to/pkcs11/library"))) {
            // Register device change listener
            manager.registerDeviceChangeListener(new DeviceChangeListener() {
                @Override
                public void onDeviceConnected(PKCS11Device device) {
                    System.out.println("Device connected: " + device.getLabel());
                }

                @Override
                public void onDeviceDisconnected(PKCS11Device device) {
                    System.out.println("Device disconnected: " + device.getLabel());
                }

                @Override
                public void onDeviceStateChanged(PKCS11Device device, DeviceState oldState) {
                    System.out.println("Device state changed: " + device.getLabel() + 
                                     " from " + oldState + " to " + device.getState());
                }

                @Override
                public void onDeviceError(PKCS11Device device, Exception error) {
                    System.err.println("Device error: " + device.getLabel() + 
                                     " - " + error.getMessage());
                }
            });

            // List available devices
            List<PKCS11Device> devices = manager.listDevices();
            System.out.println("Available devices: " + devices.size());

            // Select device and perform operations
            if (!devices.isEmpty()) {
                PKCS11Device selectedDevice = devices.get(0);
                String pin = "your_pin_here";

                try (PKCS11Session session = manager.openSession(selectedDevice, pin)) {
                    // Perform operations with session...
                }
            }
        }
    }
}

This example initializes the PKCS11 library, opens a session, and provides a menu-driven interface for various PKCS#11 operations.

Detailed Examples

Listing Certificates

private void listCertificates(PKCS11Manager manager, PKCS11Session session) {
    List<KeyCertificatePair> pairs = utils.findPrivateKeysAndCertificates(manager.getPkcs11(), session.getSession());
    System.out.println("\nAvailable certificate-key pairs:");
    for (int i = 0; i < pairs.size(); i++) {
        KeyCertificatePair pair = pairs.get(i);
        CertificateInfo certInfo = pair.getCertificateInfo();
        System.out.printf("%d: Subject: %s, Issuer: %s, Serial: %s, Not Before: %s, Not After: %s, CKA_ID: %s\n",
                i + 1,
                certInfo.getSubject(),
                certInfo.getIssuer(),
                certInfo.getSerialNumber(),
                certInfo.getNotBefore(),
                certInfo.getNotAfter(),
                pair.getCkaId());
    }
}

This method demonstrates how to list all available certificate-key pairs stored in the PKCS#11 token. Here's a breakdown of its functionality:

  1. It uses the PKCS11Utils class to find all private keys and their associated certificates within the current session.
  2. For each key-certificate pair found:
    • It retrieves detailed certificate information using the CertificateInfo object.
    • It prints out important certificate details, including:
      • The subject (owner) of the certificate
      • The issuer of the certificate
      • The serial number
      • The validity period (Not Before and Not After dates)
      • The CKA_ID, which is a unique identifier for the key-certificate pair in the PKCS#11 token

This method is crucial for users to identify and select the appropriate certificate for operations like signing or encryption.

Signing a Message

private void signMessage(PKCS11Manager manager, PKCS11Session session) throws Exception {
    KeyCertificatePair selectedPair = selectCertificateKeyPair(manager, session);

    System.out.print("Enter a message to sign: ");
    Scanner scanner = new Scanner(System.in);
    String messageToSign = scanner.nextLine();

    PKCS11Signer signer = new PKCS11Signer();
    byte[] signature = signer.signMessage(manager.getPkcs11(), session.getSession(), selectedPair.getKeyHandle(), messageToSign.getBytes());
    System.out.println("Signature: " + Base64.getEncoder().encodeToString(signature));

    boolean isSignatureValid = signer.verifySignature(messageToSign.getBytes(), signature, selectedPair.getCertificate());
    System.out.println("Signature status: " + (isSignatureValid ? "Valid" : "Invalid"));
}

This method showcases the process of digitally signing a message using a private key stored in the PKCS#11 token. Here's a step-by-step explanation:

  1. It first calls selectCertificateKeyPair() (not shown in the snippet) to allow the user to choose which key-certificate pair to use for signing.
  2. The user is prompted to enter a message to be signed.
  3. A PKCS11Signer object is created to handle the signing process.
  4. The signMessage() method is called with the following parameters:
    • The PKCS#11 instance
    • The current session
    • The handle of the selected private key
    • The message to be signed (converted to bytes)
  5. The resulting signature is encoded to Base64 for easy display and transmission.
  6. To demonstrate the full process, the method also verifies the signature immediately after creating it:
    • It uses the verifySignature() method, passing the original message, the signature, and the certificate associated with the signing key.
    • The verification result is printed, confirming whether the signature is valid.

This example demonstrates both the signing and verification process, which are crucial for ensuring data integrity and non-repudiation in cryptographic systems.

Encrypting and Decrypting Data

private void encryptDecryptData(PKCS11Manager manager, PKCS11Session session) {
    KeyCertificatePair selectedPair = selectCertificateKeyPair(manager, session);

    System.out.print("Enter data to encrypt: ");
    Scanner scanner = new Scanner(System.in);
    String dataToEncrypt = scanner.nextLine();

    PKCS11Crypto crypto = new PKCS11Crypto();

    byte[] encryptedData = crypto.encryptData(dataToEncrypt.getBytes(), selectedPair.getCertificate());
    System.out.println("Data encrypted successfully.");

    byte[] decryptedData = crypto.decryptData(manager.getPkcs11(), session.getSession(), selectedPair.getKeyHandle(), encryptedData);
    System.out.println("Decrypted data: " + new String(decryptedData));

    if (dataToEncrypt.equals(new String(decryptedData))) {
        System.out.println("Encryption and decryption successful: data integrity verified.");
    } else {
        System.out.println("Warning: Decrypted data does not match original input.");
    }
}

This method demonstrates the full cycle of encrypting and then decrypting data using the PKCS#11 token. Here's a detailed breakdown:

  1. Similar to the signing process, it starts by allowing the user to select a key-certificate pair.
  2. The user is prompted to enter some data to encrypt.
  3. A PKCS11Crypto object is created to handle both encryption and decryption.
  4. Encryption:
    • The encryptData() method is called with the input data and the selected certificate.
    • This method uses the public key from the certificate to encrypt the data.
  5. Decryption:
    • The decryptData() method is then called with the PKCS#11 instance, current session, private key handle, and the encrypted data.
    • This method uses the private key stored in the PKCS#11 token to decrypt the data.
  6. The decrypted data is converted back to a string and printed.
  7. As a final step, the method compares the original input with the decrypted output to verify that the process preserved data integrity.

This example showcases the complete encryption and decryption cycle, demonstrating how to secure data using asymmetric cryptography with keys stored in a PKCS#11 token.

Listing Supported Algorithms

private void listSupportedAlgorithms(PKCS11Manager manager, PKCS11Session session) {
    List<SupportedAlgorithm> algorithms = utils.listSupportedAlgorithms(manager.getPkcs11(), session.getSession(), 0);
    System.out.println("\nSupported algorithms:");
    for (SupportedAlgorithm algo : algorithms) {
        System.out.println(algo);
    }
}

This method demonstrates how to query and display the cryptographic algorithms supported by the PKCS#11 token. Here's what it does:

  1. It uses the PKCS11Utils class to retrieve a list of supported algorithms from the PKCS#11 token.
    • The listSupportedAlgorithms() method is called with the PKCS#11 instance, the current session, and a slot ID (0 in this case).
  2. It then iterates through the list of SupportedAlgorithm objects.
  3. Each algorithm is printed to the console.

The SupportedAlgorithm class (not shown here) likely contains information such as:

  • The algorithm's name
  • Its PKCS#11 mechanism code
  • The types of operations it supports (e.g., encryption, signing, key generation)

This functionality is crucial for developers and system administrators to understand the capabilities of their PKCS#11 token, ensuring that required cryptographic operations are supported before attempting to use them.

These detailed examples provide a comprehensive overview of the core functionalities of the PKCS11 Java Wrapper, demonstrating how to perform essential cryptographic operations using a PKCS#11 token.

πŸ—οΈ Architecture

The project is structured into several key components:

  • PKCS11Manager: Manages the lifecycle of the PKCS#11 library and sessions.
  • PKCS11Session: Represents a PKCS#11 session and handles session-specific operations.
  • PKCS11Crypto: Handles encryption and decryption operations.
  • PKCS11Signer: Manages digital signature creation and verification.
  • PKCS11Utils: Provides utility functions for various PKCS#11 operations.
  • exceptions: A package containing custom exceptions for precise error handling.
  • model: Contains data models used throughout the project.

Class Diagrams

classDiagram
    class PKCS11Manager {
        -Pkcs11 pkcs11
        -Path libraryPath
        -String pin
        +PKCS11Manager(Path libraryPath, String pin)
        +openSession(int slotId): PKCS11Session
        +getPKCS11Token(): Pkcs11SignatureToken
        +close()
    }
    class PKCS11Session {
        -Pkcs11 pkcs11
        -NativeLong session
        -String pin
        +PKCS11Session(Pkcs11 pkcs11, String pin, int slotId)
        +resetSession()
        +logout()
        +close()
    }
    class PKCS11Initializer {
        +initializePkcs11(Path libraryPath): Pkcs11
    }
    class PKCS11Crypto {
        -initCrypto(Pkcs11 pkcs11, NativeLong session, NativeLong privateKeyHandle)
        +encryptData(byte[] dataToEncrypt, X509Certificate certificate): byte[]
        +decryptData(Pkcs11 pkcs11, NativeLong session, NativeLong privateKeyHandle, byte[] encryptedData): byte[]
        -decrypt(Pkcs11 pkcs11, NativeLong session, byte[] encryptedData): byte[]
    }
    class PKCS11Signer {
        -initSigning(Pkcs11 pkcs11, NativeLong session, NativeLong privateKeyHandle)
        +signMessage(Pkcs11 pkcs11, NativeLong session, NativeLong privateKeyHandle, byte[] message): byte[]
        +verifySignature(byte[] message, byte[] signature, X509Certificate certificate): boolean
        -sign(Pkcs11 pkcs11, NativeLong session, byte[] message): byte[]
    }
    class PKCS11Utils {
        +findPrivateKeysAndCertificates(Pkcs11 pkcs11, NativeLong session): List<KeyCertificatePair>
        +listSupportedAlgorithms(Pkcs11 pkcs11, NativeLong session, int slotID): List<SupportedAlgorithm>
        -findAllCertificates(Pkcs11 pkcs11, NativeLong session): Map<String, NativeLong>
        -findAllPrivateKeys(Pkcs11 pkcs11, NativeLong session): Map<String, NativeLong>
        -getCKA_ID(Pkcs11 pkcs11, NativeLong session, NativeLong objectHandle): String
        -getCertificate(Pkcs11 pkcs11, NativeLong session, NativeLong certHandle): X509Certificate
        -bytesToHex(byte[] bytes): String
        -getMechanismList(Pkcs11 pkcs11, NativeLong slotID): NativeLong[]
        -getMechanismName(long mechanismCode): String
        -getAlgorithmType(CK_MECHANISM_INFO mechanismInfo): SupportedAlgorithm.AlgorithmType
    }
    class KeyCertificatePair {
        -NativeLong keyHandle
        -X509Certificate certificate
        -String ckaId
        -CertificateInfo certificateInfo
    }
    class CertificateInfo {
        -String subject
        -String issuer
        -BigInteger serialNumber
        -byte[] signature
        -Date notBefore
        -Date notAfter
        -String sigAlgName
        -String sigAlgOID
        -byte[] tbsCertificate
        -int version
        -PublicKey publicKey
        -boolean[] issuerUniqueID
        -boolean[] subjectUniqueID
        -boolean[] keyUsage
        -List<String> extendedKeyUsage
        -int basicConstraints
        -Collection<List<?>> subjectAlternativeNames
        -Collection<List<?>> issuerAlternativeNames
        -byte[] encoded
    }
    class SupportedAlgorithm {
        -String name
        -String code
        -AlgorithmType type
        +enum AlgorithmType
    }
    class PKCS11DeviceManager {
        -Pkcs11 pkcs11
        -Map<NativeLong, PKCS11Device> devices
        -Set<DeviceChangeListener> listeners
        -ScheduledExecutorService deviceMonitor
        +listDevices(): List<PKCS11Device>
        +listDevicesByState(DeviceState): List<PKCS11Device>
        +listDevicesByCapability(DeviceCapability): List<PKCS11Device>
        +getDevice(NativeLong): Optional<PKCS11Device>
        +registerDeviceChangeListener(DeviceChangeListener)
        +unregisterDeviceChangeListener(DeviceChangeListener)
    }
    
    class PKCS11Device {
        -NativeLong slotId
        -String label
        -String manufacturer
        -String model
        -String serialNumber
        -Set<DeviceCapability> capabilities
        -DeviceState state
        +getDetailedInfo(): Map<String, String>
        +updateState(): boolean
        +isReady(): boolean
    }
    
    class DeviceChangeListener {
        <<interface>>
        +onDeviceConnected(PKCS11Device)
        +onDeviceDisconnected(PKCS11Device)
        +onDeviceStateChanged(PKCS11Device, DeviceState)
        +onDeviceError(PKCS11Device, Exception)
    }

    PKCS11Manager --> PKCS11DeviceManager : uses
    PKCS11DeviceManager --> PKCS11Device : manages
    PKCS11DeviceManager --> DeviceChangeListener : notifies
    PKCS11Manager --> PKCS11Initializer : uses
    PKCS11Manager --> PKCS11Session : creates
    PKCS11Manager --> Pkcs11 : manages
    PKCS11Session --> Pkcs11 : uses
    PKCS11Crypto --> Pkcs11 : uses
    PKCS11Signer --> Pkcs11 : uses
    PKCS11Utils --> Pkcs11 : uses
    PKCS11Utils --> KeyCertificatePair : creates
    PKCS11Utils --> SupportedAlgorithm : creates
    KeyCertificatePair --> CertificateInfo : contains
    KeyCertificatePair --> X509Certificate : contains
Loading

Sequence Diagrams

Encryption Process

sequenceDiagram
    participant Client
    participant PKCS11Manager
    participant PKCS11Initializer
    participant PKCS11Session
    participant PKCS11Utils
    participant PKCS11Crypto
    participant Pkcs11Library

    Client->>PKCS11Manager: new PKCS11Manager(libraryPath, pin)
    PKCS11Manager->>PKCS11Initializer: initializePkcs11(libraryPath)
    PKCS11Initializer->>Pkcs11Library: C_Initialize()
    Pkcs11Library-->>PKCS11Initializer: return Pkcs11 object
    PKCS11Initializer-->>PKCS11Manager: return Pkcs11 object
    
    Client->>PKCS11Manager: openSession(slotId)
    PKCS11Manager->>PKCS11Session: new PKCS11Session(pkcs11, pin, slotId)
    PKCS11Session->>Pkcs11Library: C_OpenSession()
    PKCS11Session->>Pkcs11Library: C_Login()
    
    Client->>PKCS11Utils: findPrivateKeysAndCertificates(pkcs11, session)
    PKCS11Utils->>Pkcs11Library: C_FindObjectsInit()
    PKCS11Utils->>Pkcs11Library: C_FindObjects()
    PKCS11Utils->>Pkcs11Library: C_GetAttributeValue()
    PKCS11Utils-->>Client: return List<KeyCertificatePair>
    
    Client->>PKCS11Crypto: encryptData(dataToEncrypt, certificate)
    PKCS11Crypto->>PKCS11Crypto: Cipher.getInstance("RSA/ECB/PKCS1Padding")
    PKCS11Crypto->>PKCS11Crypto: cipher.init(Cipher.ENCRYPT_MODE, certificate.getPublicKey())
    PKCS11Crypto->>PKCS11Crypto: cipher.doFinal(dataToEncrypt)
    PKCS11Crypto-->>Client: return encryptedData

    Client->>PKCS11Session: close()
    PKCS11Session->>Pkcs11Library: C_Logout()
    PKCS11Session->>Pkcs11Library: C_CloseSession()
    
    Client->>PKCS11Manager: close()
    PKCS11Manager->>Pkcs11Library: C_Finalize()
Loading

Decryption Process

sequenceDiagram
    participant Client
    participant PKCS11Manager
    participant PKCS11Initializer
    participant PKCS11Session
    participant PKCS11Utils
    participant PKCS11Crypto
    participant Pkcs11Library

    Client->>PKCS11Manager: new PKCS11Manager(libraryPath, pin)
    PKCS11Manager->>PKCS11Initializer: initializePkcs11(libraryPath)
    PKCS11Initializer->>Pkcs11Library: C_Initialize()
    Pkcs11Library-->>PKCS11Initializer: return Pkcs11 object
    PKCS11Initializer-->>PKCS11Manager: return Pkcs11 object
    
    Client->>PKCS11Manager: openSession(slotId)
    PKCS11Manager->>PKCS11Session: new PKCS11Session(pkcs11, pin, slotId)
    PKCS11Session->>Pkcs11Library: C_OpenSession()
    PKCS11Session->>Pkcs11Library: C_Login()
    
    Client->>PKCS11Utils: findPrivateKeysAndCertificates(pkcs11, session)
    PKCS11Utils->>Pkcs11Library: C_FindObjectsInit()
    PKCS11Utils->>Pkcs11Library: C_FindObjects()
    PKCS11Utils->>Pkcs11Library: C_GetAttributeValue()
    PKCS11Utils-->>Client: return List<KeyCertificatePair>
    
    Client->>PKCS11Crypto: decryptData(pkcs11, session, privateKeyHandle, encryptedData)
    PKCS11Crypto->>Pkcs11Library: C_DecryptInit()
    PKCS11Crypto->>Pkcs11Library: C_Decrypt()
    Pkcs11Library-->>PKCS11Crypto: return decryptedData
    PKCS11Crypto-->>Client: return decryptedData

    Client->>PKCS11Session: close()
    PKCS11Session->>Pkcs11Library: C_Logout()
    PKCS11Session->>Pkcs11Library: C_CloseSession()
    
    Client->>PKCS11Manager: close()
    PKCS11Manager->>Pkcs11Library: C_Finalize()
Loading

Signing Process

sequenceDiagram
    participant Client
    participant PKCS11Manager
    participant PKCS11Initializer
    participant PKCS11Session
    participant PKCS11Utils
    participant PKCS11Signer
    participant Pkcs11Library

    Client->>PKCS11Manager: new PKCS11Manager(libraryPath, pin)
    PKCS11Manager->>PKCS11Initializer: initializePkcs11(libraryPath)
    PKCS11Initializer->>Pkcs11Library: C_Initialize()
    Pkcs11Library-->>PKCS11Initializer: return Pkcs11 object
    PKCS11Initializer-->>PKCS11Manager: return Pkcs11 object
    
    Client->>PKCS11Manager: openSession(slotId)
    PKCS11Manager->>PKCS11Session: new PKCS11Session(pkcs11, pin, slotId)
    PKCS11Session->>Pkcs11Library: C_OpenSession()
    PKCS11Session->>Pkcs11Library: C_Login()
    
    Client->>PKCS11Utils: findPrivateKeysAndCertificates(pkcs11, session)
    PKCS11Utils->>Pkcs11Library: C_FindObjectsInit()
    PKCS11Utils->>Pkcs11Library: C_FindObjects()
    PKCS11Utils->>Pkcs11Library: C_GetAttributeValue()
    PKCS11Utils-->>Client: return List<KeyCertificatePair>
    
    Client->>PKCS11Signer: signMessage(pkcs11, session, privateKeyHandle, message)
    PKCS11Signer->>PKCS11Signer: initSigning(pkcs11, session, privateKeyHandle)
    PKCS11Signer->>Pkcs11Library: C_SignInit()
    PKCS11Signer->>PKCS11Signer: sign(pkcs11, session, message)
    PKCS11Signer->>Pkcs11Library: C_Sign()
    Pkcs11Library-->>PKCS11Signer: return signature
    PKCS11Signer-->>Client: return signature

    Client->>PKCS11Session: close()
    PKCS11Session->>Pkcs11Library: C_Logout()
    PKCS11Session->>Pkcs11Library: C_CloseSession()
    
    Client->>PKCS11Manager: close()
    PKCS11Manager->>Pkcs11Library: C_Finalize()
Loading

Signature Verification Process

sequenceDiagram
    participant Client
    participant PKCS11Manager
    participant PKCS11Initializer
    participant PKCS11Session
    participant PKCS11Utils
    participant PKCS11Signer
    participant BouncyCastleProvider
    participant Signature

    Client->>PKCS11Manager: new PKCS11Manager(libraryPath, pin)
    PKCS11Manager->>PKCS11Initializer: initializePkcs11(libraryPath)
    PKCS11Initializer->>Pkcs11Library: C_Initialize()
    Pkcs11Library-->>PKCS11Initializer: return Pkcs11 object
    PKCS11Initializer-->>PKCS11Manager: return Pkcs11 object
    
    Client->>PKCS11Manager: openSession(slotId)
    PKCS11Manager->>PKCS11Session: new PKCS11Session(pkcs11, pin, slotId)
    PKCS11Session->>Pkcs11Library: C_OpenSession()
    PKCS11Session->>Pkcs11Library: C_Login()
    
    Client->>PKCS11Utils: findPrivateKeysAndCertificates(pkcs11, session)
    PKCS11Utils->>Pkcs11Library: C_FindObjectsInit()
    PKCS11Utils->>Pkcs11Library: C_FindObjects()
    PKCS11Utils->>Pkcs11Library: C_GetAttributeValue()
    PKCS11Utils-->>Client: return List<KeyCertificatePair>
    
    Client->>PKCS11Signer: verifySignature(message, signature, certificate)
    PKCS11Signer->>BouncyCastleProvider: new BouncyCastleProvider()
    PKCS11Signer->>Signature: getInstance("SHA256withRSA", BouncyCastleProvider)
    Signature-->>PKCS11Signer: return Signature object
    PKCS11Signer->>Signature: initVerify(certificate.getPublicKey())
    PKCS11Signer->>Signature: update(message)
    PKCS11Signer->>Signature: verify(signature)
    Signature-->>PKCS11Signer: return verification result
    PKCS11Signer-->>Client: return verification result

    Client->>PKCS11Session: close()
    PKCS11Session->>Pkcs11Library: C_Logout()
    PKCS11Session->>Pkcs11Library: C_CloseSession()
    
    Client->>PKCS11Manager: close()
    PKCS11Manager->>Pkcs11Library: C_Finalize()
Loading

These sequence diagrams illustrate the flow of operations for the core functionalities of the PKCS11 Java Wrapper:

  1. Encryption Process: Shows how data is encrypted using a certificate's public key.
  2. Decryption Process: Demonstrates the steps to decrypt data using a private key stored in the PKCS#11 token.
  3. Signing Process: Illustrates how a message is signed using a private key from the PKCS#11 token.
  4. Signature Verification Process: Shows how a signature is verified using the corresponding certificate's public key.

Each diagram highlights the interactions between different components of the system, including the client application, PKCS11 wrapper classes, and the underlying PKCS#11 library.

πŸ§ͺ Tested Environments

We have thoroughly tested the PKCS11 Java Wrapper in various environments to ensure its compatibility and performance. Below is a table of our tested configurations:

Operating System Processor Java Version OpenSC Version Status
Windows 11 x64 x64 LTS 21 (Eclipse Temurin) 0.25.1 βœ…
Windows 11 x64 x32 LTS 17 (Eclipse Temurin) 0.25.0 βœ…
Windows 11 x64 x64 LTS 21 (Eclipse Temurin) 0.24.0 βœ…
Windows 11 x64 x64 LTS 21 (Eclipse Temurin) 0.23.0-rc2 βœ…
macOS Sonoma 14.5 arm LTS 21 (Eclipse Temurin) 0.25.1 βœ…
Ubuntu 24.04 x64 LTS 21 (Eclipse Temurin) 0.25.0 βœ…

Windows 11 x64 and x32

  • Java: LTS 21 Eclipse Temurin / LTS 17 Eclipse Temurin
  • OpenSC: Versions: 0.25.1, 0.24.0, 0.23.0-rc2, 0.25.0
  • Status: Fully tested and operational

macOS Sonoma 14.5

  • Java: LTS 21 Eclipse Temurin
  • OpenSC: Version 0.25.1
  • Status: Fully tested and operational

We continuously strive to expand our testing to cover more environments and configurations. If you successfully run the PKCS11 Java Wrapper in a different environment, please let us know so we can update our compatibility list.

πŸ§ͺ Testing

The project includes a comprehensive test suite to ensure the reliability and correctness of all components. To run the tests, use the following Maven command:

mvn test

Our test suite covers various scenarios, including:

  • Initialization of PKCS#11 library
  • Session management
  • Key and certificate operations
  • Encryption and decryption
  • Digital signature creation and verification
  • Error handling and exception scenarios
  • Device detection and management
  • Device state monitoring
  • Hot-plug capability testing
  • Device capability filtering
  • Device change event handling
  • Multi-device operations

🀝 Contributing

We welcome contributions to the PKCS11 Java Wrapper Project! Please feel free to submit pull requests, create issues, or suggest new features.

  1. Fork the project
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

πŸ“„ License

This project is licensed under the GNU GENERAL PUBLIC LICENSE Version 3.0 - see the LICENSE.md file for details.

πŸ“ž Contact

Project Link: https://github.com/SimpleMethod/PKCS11-Java-Wrapper


Thank you for your interest in the PKCS11 Java Wrapper! We hope this tool proves valuable in your cryptographic endeavors. Happy coding! πŸš€πŸ”

About

A comprehensive Java library for interacting with PKCS#11 (Cryptoki) compatible hardware security modules (HSMs) and smart cards. This wrapper simplifies cryptographic operations while maintaining high security standards.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Languages