demoiselle / signer

Repositório que contém os componentes para facilitar a implementação de assinatura digital nos padrões da ICP-BRASIL
https://www.frameworkdemoiselle.gov.br/v3/signer/
GNU Lesser General Public License v3.0
142 stars 73 forks source link

Detectar a presença do token #415

Open icemagno opened 1 month ago

icemagno commented 1 month ago

Algumas vezes, é útil saber simplesmente se algum token foi inserido ou removido da USB. Seria bom ter um listener para disparar eventos de inserção / remoção do token.

Eu tentei ler um keystore, mas ele pede senha quando tento fazer isso.

icemagno commented 1 month ago

Eu implementei uma classe para disparar eventos quando meu Token é conectado / desconectado da porta USB usando a biblioteca JavaDoesUSB ( https://github.com/manuelbl/JavaDoesUSB ). Funcionou para mim e eu tentei deixar de uma forma mais genérica possível, mas obviamente serão necessários mais testes.

Essa biblioteca EXIGE Java >= 21

Segue a classe que eu desenvolvi:

icemagno commented 1 month ago
package br.com.j1scorpii.usbdevice;

import java.util.HashMap;
import java.util.Map;

import org.json.JSONObject;

import net.codecrete.usb.Usb;
import net.codecrete.usb.UsbAlternateInterface;
import net.codecrete.usb.UsbDevice;
import net.codecrete.usb.UsbInterface;

public class DeviceManager {
    private IDeviceEventObserver observer;
    private boolean devicePresent = false;
    private Map<Integer,JSONObject> devices = new HashMap<Integer,JSONObject>();

    public static enum DeviceEventType{
        CONNECTED,
        DISCONNECTED
    }

    public boolean isDevicePresent() {
        return devicePresent;
    }

    public DeviceManager( IDeviceEventObserver observer ) {
        this.observer = observer;
    }

    public void monitorAll() {
        monitorClass( -1 );
    }

    public void monitorClass( int classCode ) {
        try {
            for ( var device : Usb.getDevices() ) checkDevice(device, DeviceEventType.CONNECTED, classCode );

            Usb.setOnDeviceConnected( device -> {
                checkDevice( device, DeviceEventType.CONNECTED, classCode ); 
            });

            Usb.setOnDeviceDisconnected( device -> {
                checkDevice( device, DeviceEventType.DISCONNECTED, classCode );
            });

        } catch( IllegalStateException t ) {
            // PLEASE BE QUIET !!
        }
    }

    private void checkDevice(UsbDevice device, DeviceEventType event, int classCodeFilter ) {
        int vendorId = device.getVendorId();                // 1059H / 4185D Giesecke & Devrient GmbH
        int productId = device.getProductId();              // 000bH /   23D StarSign Bio Token 3.0
        String manufacturer = device.getManufacturer();     // Giesecke & Devrient GmbH

        String product = "";
        try { product = device.getProduct().toUpperCase().trim().replaceAll(" ", "_"); } catch ( Exception e ) {}

        UsbInterface intf = device.getInterface(0);
        UsbAlternateInterface alt = intf.getCurrentAlternate();     
        int classCode = alt.getClassCode();

        // 4185 23 11 Giesecke & Devrient GmbH STARSIGN_CUT
        // System.out.println( vendorId + " " + productId + " " + classCode + " " + manufacturer + " " + product );
        // describe( device );
        JSONObject deviceJson = new JSONObject()
                .put("vendorId",vendorId)
                .put("productId",productId)
                .put("classCode",classCode)
                .put("manufacturer",manufacturer)
                .put("product",product);

        if ( event == DeviceEventType.CONNECTED ) this.devices.put(classCode, deviceJson);
        if ( event == DeviceEventType.DISCONNECTED ) this.devices.remove(classCode, deviceJson);

        if ( classCodeFilter == -1 ) observer.notifyEvent( event, deviceJson ); 
        else 
        if ( classCode == classCodeFilter ) { // 11 = Chip/SmartCard
            this.devicePresent = ( event == DeviceEventType.CONNECTED );
            observer.notifyEvent( event, deviceJson );
        }

    }

    public Map<Integer, JSONObject> getDevices() {
        return devices;
    }

}
icemagno commented 1 month ago

Para usar:

Implemente sua classe como a interface IDeviceEventObserver

public interface IDeviceEventObserver {
    void notifyEvent( DeviceEventType eventType, JSONObject deviceJson );
}

Chame o monitor de dispositivos:

   DeviceManager deviceManager = new DeviceManager( this );
   deviceManager.monitorAll();

   ou

   deviceManager.monitor(  classe  );    // Onde 11 = "Chip/SmartCard"

Resultado ( monitora a classe 11 de Token/Smartcard ):

Evt: CONNECTED Presente?: true
{
     "classCode": 11,
     "product": "",
     "productId": 23,
     "vendorId": 4185,
     "manufacturer": "Giesecke & Devrient GmbH"
}
Evt: DISCONNECTED Presente?: false
{
     "classCode": 11,
     "product": "",
     "productId": 23,
     "vendorId": 4185,
     "manufacturer": "Giesecke & Devrient GmbH"
}
icemagno commented 1 month ago

Monitora tudo:

Evt: CONNECTED 
{
     "classCode": 3,
     "product": "DELL_MS116_USB_OPTICAL_MOUSE",
     "productId": 12314,
     "vendorId": 16700,
     "manufacturer": "PixArt"
}
Evt: CONNECTED 
{
     "classCode": 3,
     "product": "DELL_KB216_WIRED_KEYBOARD",
     "productId": 8467,
     "vendorId": 16700,
     "manufacturer": "Љ"
}
Evt: CONNECTED 
{
     "classCode": 1,
     "product": "LOGI_USB_HEADSET",
     "productId": 2661,
     "vendorId": 1133,
     "manufacturer": "Logitech"
}