11package pl .mlodawski .security .example ;
22
33import pl .mlodawski .security .pkcs11 .*;
4- import pl .mlodawski .security .pkcs11 .model .SupportedAlgorithm ;
5- import pl .mlodawski .security .pkcs11 .model .KeyCertificatePair ;
6- import pl .mlodawski .security .pkcs11 .model .CertificateInfo ;
4+ import pl .mlodawski .security .pkcs11 .model .*;
75
86import java .nio .file .Path ;
97import java .nio .file .Paths ;
108import java .util .List ;
119import java .util .Base64 ;
10+ import java .util .Map ;
1211import java .util .Scanner ;
1312
1413class PKCS11 {
15-
1614 private final Path PKCS11_WRAPPER_PATH ;
17- private final String PIN ;
18- PKCS11Utils utils = new PKCS11Utils ();
15+ private String PIN ;
16+ private final PKCS11Utils utils = new PKCS11Utils ();
17+ private PKCS11Device selectedDevice ;
1918
20- public PKCS11 (Path pkcs11WrapperPath , String pin ) {
19+ public PKCS11 (Path pkcs11WrapperPath ) {
2120 this .PKCS11_WRAPPER_PATH = pkcs11WrapperPath ;
22- this .PIN = pin ;
2321 }
2422
2523 public void run () {
26- PKCS11Manager manager = new PKCS11Manager (PKCS11_WRAPPER_PATH , PIN );
24+ try (PKCS11Manager manager = new PKCS11Manager (PKCS11_WRAPPER_PATH )) {
25+ manager .registerDeviceChangeListener (new DeviceChangeListener () {
26+ @ Override
27+ public void onDeviceConnected (PKCS11Device device ) {
28+ System .out .println ("\n New device connected: " + device .getLabel ());
29+ }
30+
31+ @ Override
32+ public void onDeviceDisconnected (PKCS11Device device ) {
33+ System .out .println ("\n Device disconnected: " + device .getLabel ());
34+ if (device .equals (selectedDevice )) {
35+ selectedDevice = null ;
36+ System .out .println ("Selected device was disconnected. Please select a new device." );
37+ }
38+ }
39+
40+ @ Override
41+ public void onDeviceStateChanged (PKCS11Device device , DeviceState oldState ) {
42+ System .out .printf ("\n Device %s state changed from %s to %s%n" ,
43+ device .getLabel (), oldState , device .getState ());
44+ }
45+
46+ @ Override
47+ public void onDeviceError (PKCS11Device device , Exception error ) {
48+ System .out .printf ("\n Error occurred with device %s: %s%n" ,
49+ device .getLabel (), error .getMessage ());
50+ }
51+ });
2752
28- try (PKCS11Session session = manager .openSession (0 )) {
2953 while (true ) {
3054 try {
31- displayMenu ();
32- int choice = getUserChoice ();
33-
34- switch (choice ) {
35- case 1 :
36- listCertificates (manager , session );
37- break ;
38- case 2 :
39- signMessage (manager , session );
40- break ;
41- case 3 :
42- encryptDecryptData (manager , session );
43- break ;
44- case 4 :
45- listSupportedAlgorithms (manager , session );
46- break ;
47- case 5 :
48- System .out .println ("Exiting..." );
49- return ;
50- default :
51- System .out .println ("Invalid choice. Please try again." );
55+ if (selectedDevice == null || !selectedDevice .isReady ()) {
56+ if (!selectDevice (manager )) {
57+ System .out .println ("No devices available. Please connect a device and try again." );
58+ Thread .sleep (2000 );
59+ continue ;
60+ }
61+ if (!getPINFromUser ()) {
62+ continue ;
63+ }
64+ }
65+
66+ try (PKCS11Session session = manager .openSession (selectedDevice , PIN )) {
67+ while (selectedDevice != null && selectedDevice .isReady ()) {
68+ displayMenu ();
69+ int choice = getUserChoice ();
70+
71+ switch (choice ) {
72+ case 1 :
73+ listCertificates (manager , session );
74+ break ;
75+ case 2 :
76+ signMessage (manager , session );
77+ break ;
78+ case 3 :
79+ encryptDecryptData (manager , session );
80+ break ;
81+ case 4 :
82+ listSupportedAlgorithms (manager , session );
83+ break ;
84+ case 5 :
85+ selectedDevice = null ;
86+ return ;
87+ case 6 :
88+ session .close ();
89+ selectedDevice = null ;
90+ PIN = null ;
91+ if (!handleDeviceChange (manager )) {
92+ System .out .println ("Returning to main menu..." );
93+ }
94+ break ;
95+ default :
96+ System .out .println ("Invalid choice. Please try again." );
97+ }
98+
99+ if (choice == 6 ) {
100+ break ;
101+ }
102+ }
103+ } catch (Exception e ) {
104+ System .out .println ("Session error: " + e .getMessage ());
105+ selectedDevice = null ;
106+ PIN = null ; // Czyścimy PIN w przypadku błędu sesji
52107 }
53108 } catch (Exception e ) {
54109 System .out .println ("An error occurred: " + e .getMessage ());
55- } finally {
56- session .resetSession ();
110+ Thread .sleep (1000 );
57111 }
58112 }
59113 } catch (Exception e ) {
60- throw new RuntimeException (e );
114+ throw new RuntimeException ("Fatal error: " + e .getMessage (), e );
115+ }
116+ }
117+
118+
119+ private boolean handleDeviceChange (PKCS11Manager manager ) {
120+ int maxRetries = 3 ;
121+ int retryCount = 0 ;
122+
123+ while (retryCount < maxRetries ) {
124+ try {
125+ manager .prepareForDeviceChange ();
126+ System .out .println ("Device selection refreshed. Please select a new device." );
127+
128+ if (!selectDevice (manager )) {
129+ retryCount ++;
130+ continue ;
131+ }
132+
133+ // Dodajemy wymuszenie podania PIN-u po zmianie urządzenia
134+ if (!getPINFromUser ()) {
135+ retryCount ++;
136+ continue ;
137+ }
138+
139+ return true ;
140+ } catch (Exception e ) {
141+ System .err .println ("Error during device change" + e );
142+ retryCount ++;
143+ if (retryCount < maxRetries ) {
144+ System .out .println ("Error occurred, retrying... (" + (maxRetries - retryCount ) + " attempts remaining)" );
145+ try {
146+ Thread .sleep (1000 );
147+ } catch (InterruptedException ie ) {
148+ Thread .currentThread ().interrupt ();
149+ return false ;
150+ }
151+ }
152+ }
61153 }
154+
155+ System .out .println ("Failed to change device after " + maxRetries + " attempts." );
156+ return false ;
157+ }
158+
159+ private boolean selectDevice (PKCS11Manager manager ) {
160+ List <PKCS11Device > devices = manager .listDevices ();
161+ if (devices .isEmpty ()) {
162+ return false ;
163+ }
164+
165+ System .out .println ("\n --- Available Devices ---" );
166+ for (int i = 0 ; i < devices .size (); i ++) {
167+ PKCS11Device device = devices .get (i );
168+ System .out .printf ("%d: %s (Manufacturer: %s, Model: %s, Serial: %s)%n" ,
169+ i + 1 ,
170+ device .getLabel (),
171+ device .getManufacturer (),
172+ device .getModel (),
173+ device .getSerialNumber ());
174+
175+ Map <String , String > info = device .getDetailedInfo ();
176+ System .out .printf (" State: %s%n" , device .getState ());
177+ System .out .printf (" Rest of the information about key: %s" , info .toString ());
178+ System .out .println ();
179+ }
180+
181+ System .out .print ("Select device (1-" + devices .size () + "): " );
182+ int choice = getUserChoice ();
183+
184+ if (choice < 1 || choice > devices .size ()) {
185+ System .out .println ("Invalid device selection." );
186+ return false ;
187+ }
188+
189+ selectedDevice = devices .get (choice - 1 );
190+ if (!selectedDevice .isReady ()) {
191+ System .out .println ("Selected device is not ready. State: " + selectedDevice .getState ());
192+ selectedDevice = null ;
193+ return false ;
194+ }
195+
196+ return true ;
197+ }
198+
199+ private boolean getPINFromUser () {
200+ if (selectedDevice == null ) {
201+ return false ;
202+ }
203+
204+ Map <String , Long > pinRequirements = selectedDevice .getPinLengthRequirements ();
205+ System .out .print ("Enter PIN for " + selectedDevice .getLabel () + ": " );
206+ Scanner scanner = new Scanner (System .in );
207+ PIN = scanner .nextLine ();
208+
209+ if (PIN .length () < pinRequirements .get ("minLength" ) ||
210+ PIN .length () > pinRequirements .get ("maxLength" )) {
211+ System .out .printf ("Invalid PIN length. Must be between %d and %d characters.%n" ,
212+ pinRequirements .get ("minLength" ),
213+ pinRequirements .get ("maxLength" ));
214+ PIN = null ;
215+ return false ;
216+ }
217+
218+ return true ;
62219 }
63220
64221 private void displayMenu () {
65222 System .out .println ("\n --- PKCS#11 Operations Menu ---" );
223+ System .out .println ("Current device: " + selectedDevice .getLabel ());
66224 System .out .println ("1. List Available Certificates" );
67225 System .out .println ("2. Sign a Message" );
68226 System .out .println ("3. Encrypt and Decrypt Data" );
69227 System .out .println ("4. List Supported Algorithms" );
70228 System .out .println ("5. Exit" );
229+ System .out .println ("6. Change Device" );
71230 System .out .print ("Enter your choice: " );
72231 }
73232
233+
74234 private int getUserChoice () {
75235 Scanner scanner = new Scanner (System .in );
76236 return scanner .nextInt ();
@@ -157,10 +317,24 @@ private void encryptDecryptData(PKCS11Manager manager, PKCS11Session session) {
157317 }
158318
159319 private void listSupportedAlgorithms (PKCS11Manager manager , PKCS11Session session ) {
160- List <SupportedAlgorithm > algorithms = utils .listSupportedAlgorithms (manager .getPkcs11 (), session .getSession (), 0 );
161- System .out .println ("\n Supported algorithms:" );
162- for (SupportedAlgorithm algo : algorithms ) {
163- System .out .println (algo );
320+ try {
321+ List <SupportedAlgorithm > algorithms = utils .listSupportedAlgorithms (
322+ manager .getPkcs11 (),
323+ session .getSession (),
324+ selectedDevice .getSlotId ().intValue ()
325+ );
326+
327+ if (algorithms .isEmpty ()) {
328+ System .out .println ("\n No supported algorithms found for this device." );
329+ return ;
330+ }
331+
332+ System .out .println ("\n Supported algorithms:" );
333+ for (SupportedAlgorithm algo : algorithms ) {
334+ System .out .println (algo );
335+ }
336+ } catch (Exception e ) {
337+ System .out .println ("Error listing algorithms: " + e .getMessage ());
164338 }
165339 }
166340}
@@ -169,8 +343,7 @@ public class PKCS11Example {
169343 public static void main (String [] args ) {
170344 String userDir = System .getProperty ("user.dir" );
171345 PKCS11 example = new PKCS11 (
172- Paths .get (userDir , "lib" , "opensc-pkcs11.dll" ),
173- "123456"
346+ Paths .get (userDir , "lib" , "opensc-pkcs11.dll" )
174347 );
175348 example .run ();
176349 }
0 commit comments