java smartcard pcsc

Accediendo a javax.smartcardio desde Linux 64 bits



pcsc (7)

Estoy intentando cargar los terminales de tarjetas inteligentes utilizando la API javax.smartcardio con el siguiente código:

public CardTerminal getReadyCardTerminal() throws CardException { TerminalFactory factory = TerminalFactory.getDefault(); CardTerminals terminals = factory.terminals(); List<CardTerminal> list = terminals.list(State.CARD_PRESENT); while (list.isEmpty()) { terminals.waitForChange(1000); list = terminals.list(State.CARD_PRESENT); } CardTerminal cardTerminal = list.get(0); return cardTerminal; }

... y siempre obtengo la siguiente excepción:

java.lang.IllegalStateException: no terminals at javax.smartcardio.TerminalFactory$NoneCardTerminals.waitForChange(TerminalFactory.java:145)

En Windows Vista / 7 todo funciona bien, pero no puedo hacer que funcione en Linux. Estoy usando Ubuntu 12.04 64 bits.

Instalé el servicio pcscd usando el siguiente comando:

sudo apt-get install libccid pcscd libpcsclite-dev libpcsclite1 sudo service pcscd start

Y el comando pcsc_scan imprime esto:

PC/SC device scanner V 1.4.18 (c) 2001-2011, Ludovic Rousseau <[email protected]> Compiled with PC/SC lite version: 1.7.4 Using reader plug''n play mechanism Scanning present readers... 0: OMNIKEY CardMan 3x21 00 00 Tue Sep 11 15:44:49 2012 Reader 0: OMNIKEY CardMan 3x21 00 00 Card state: Card inserted, ATR: <some hexa codes> ...

Así que todo se ve bien, pero el smartcardio simplemente no funciona. Estoy probando con Oracle y OpenJDK 1.7.0_05, 32 y 64 bits.

El código funciona bien con OpenJDK (pero no con Oracle JDK, no sé realmente por qué) en un entorno de Ubuntu de 32 bits. Así que creo que es un problema con el puente de 64 bits de Java a la biblioteca PC / SC.

¿Algunas ideas?

Gracias.


Adición a la solución con el suministro de la ruta como un parámetro como este:

java -Dsun.security.smartcardio.library=/usr/lib64/libpcsclite.so.1

Si no desea proporcionar esto cada vez que llame a la JVM, configúrelo en las variables de entorno _JAVA_OPTIONS y / o JAVA_OPTS:

export _JAVA_OPTIONS="-Dsun.security.smartcardio.library=/usr/lib64/libpcsclite.so.1" export JAVA_OPTS="-Dsun.security.smartcardio.library=/usr/lib64/libpcsclite.so.1"

Dado que esta es una solución para los errores que afectan a todo el sistema, tiene sentido, en mi humilde opinión, aplicar esta solución también en todo el sistema.

JAVA_OPTS tiene un alcance local y debe ser evaluado por scripts que ejecutan su código; Se supone que _JAVA_OPTIONS se evalúa automáticamente por el JRE.


Complementando la respuesta de @AshanPerera, como a veces la búsqueda cada vez puede ser lenta, puede buscarla la primera vez, almacenar la ubicación en un archivo y leerla a partir de entonces:

try { String filename = "libpcsclite.location"; File propertyFile = new File(filename); if(propertyFile.createNewFile()) { String commandWithArguments[] = { "find", "/usr", "/lib", "-name","libpcsclite.so.1" }; Process searchProcess = Runtime.getRuntime().exec(commandWithArguments); BufferedReader searchReader = new BufferedReader(new InputStreamReader(searchProcess.getInputStream())); String propertyValue; while ( (propertyValue = searchReader.readLine()) != null && !propertyValue.equals("")) { if (propertyValue.contains("libpcsclite.so.1")) { BufferedWriter propertyWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(propertyFile))); propertyWriter.write(propertyValue); propertyWriter.close(); System.setProperty("sun.security.smartcardio.library",propertyValue); break; } } searchProcess.waitFor(); } else { BufferedReader propertyReader = new BufferedReader(new InputStreamReader(new FileInputStream(propertyFile))); String propertyValue = propertyReader.readLine(); System.setProperty("sun.security.smartcardio.library",propertyValue); } } catch (Exception e) { e.printStackTrace(); }


Creo que encontré una solución para esto, ya que tuve un problema similar. En un informe de errores de ubuntu dice que la biblioteca javax.smartcardio busca la biblioteca PC / SC en el directorio incorrecto.

Al especificar la ruta de acceso a la biblioteca de PC / SC en mi máquina, como lo menciona el informe de errores, lo tengo funcionando.

Las rutas en el informe de errores son incorrectas para mí, estoy en fedora de 64 bits, donde la biblioteca pc / sc se instala en /usr/lib64/libpcsclite.so.1

Así que la solución para mí es especificar la ruta de la biblioteca a Java de esta manera:

java -Dsun.security.smartcardio.library=/usr/lib64/libpcsclite.so.1

Dependiendo de su distribución de Linux, la ubicación de libpcsclite.so.1 realidad podría diferir, también podría estar en /lib/x86_64-linux-gnu/libpcsclite.so.1 (es decir, Kubuntu 15.04). En ese caso, llámalo así:

java -Dsun.security.smartcardio.library=/lib/x86_64-linux-gnu/libpcsclite.so.1


Debe indicar la ruta a libpcsclite.so.1 cuando llame a su programa de la siguiente manera

java -Dsun.security.smartcardio.library=/path/to/libpcsclite.so.1

Si no conoce la ruta a la biblioteca, use el siguiente comando

find /usr/lib -name libpcsclite.so.1

Esto usualmente te muestra el camino en tu máquina. Lo usé tanto en Ubuntu 10 (32 bits) como en Ubuntu 15 (32 bits y 64 bits)

Si eres un vago como yo, lo que puedes hacer es incluir esta parte del código en tu programa antes de usar la biblioteca javax.smartcardio.

try { String comm[] = { "find", "/usr", "/lib", "-name", "libpcsclite.so.1" }; Process p = Runtime.getRuntime().exec(comm); BufferedReader reader = new BufferedReader( new InputStreamReader(p.getInputStream())); while ((line = reader.readLine()) != null && !line.equals("")) { if (line.contains("libpcsclite.so.1")) { System.setProperty("sun.security.smartcardio.library",line); break; } } p.waitFor(); } catch (Exception e) { e.printStackTrace(); }

Ahora puede ejecutar su código de la forma habitual sin incluir la ruta a libpcsclite.so.1


Estoy usando frambuesa con la versión debian arm

Encuentra la ubicación de libpcsclite primero con:

$ ldd -r /usr/bin/pcsc_scan

y luego use la ubicación libpcsclite con:

java -Dsun.security.smartcardio.library=/usr/lib/arm-linux-gnueabihf/libpcsclite.so.1


Otro enfoque (mi favorito) es hacer algunos enlaces simbólicos.

Tiene la ventaja de que funciona en todo el sistema (sin argumentos jvm, ni variables de entorno).

Para mi (querida) Debian Jessie AMD64:

ln -s /usr/lib/x86_64-linux-gnu/libpcsclite.so libpcsclite.so ln -s /usr/lib/x86_64-linux-gnu/libpcsclite.so.1 libpcsclite.so.1 ln -s /usr/lib/x86_64-linux-gnu/libpcsclite.so.1.0.0 libpcsclite.so.1.0.0

Nota: Esto probablemente requerirá acceso de superusuario .


Para cualquier otra persona que esté luchando con esto en Ubuntu 14 con una máquina de 64 bits. Encontré que el archivo .so está ubicado en el siguiente directorio

/usr/lib/x86_64-linux-gnu/libpcsclite.so

Así que ejecutar mi aplicación con la configuración de abajo me funcionó

-Dsun.security.smartcardio.library = / usr / lib / x86_64-linux-gnu / libpcsclite.so