1
1
package pl .mlodawski .security .example ;
2
2
3
3
import 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 .*;
7
5
8
6
import java .nio .file .Path ;
9
7
import java .nio .file .Paths ;
10
8
import java .util .List ;
11
9
import java .util .Base64 ;
10
+ import java .util .Map ;
12
11
import java .util .Scanner ;
13
12
14
13
class PKCS11 {
15
-
16
14
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 ;
19
18
20
- public PKCS11 (Path pkcs11WrapperPath , String pin ) {
19
+ public PKCS11 (Path pkcs11WrapperPath ) {
21
20
this .PKCS11_WRAPPER_PATH = pkcs11WrapperPath ;
22
- this .PIN = pin ;
23
21
}
24
22
25
23
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
+ });
27
52
28
- try (PKCS11Session session = manager .openSession (0 )) {
29
53
while (true ) {
30
54
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
52
107
}
53
108
} catch (Exception e ) {
54
109
System .out .println ("An error occurred: " + e .getMessage ());
55
- } finally {
56
- session .resetSession ();
110
+ Thread .sleep (1000 );
57
111
}
58
112
}
59
113
} 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
+ }
61
153
}
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 ;
62
219
}
63
220
64
221
private void displayMenu () {
65
222
System .out .println ("\n --- PKCS#11 Operations Menu ---" );
223
+ System .out .println ("Current device: " + selectedDevice .getLabel ());
66
224
System .out .println ("1. List Available Certificates" );
67
225
System .out .println ("2. Sign a Message" );
68
226
System .out .println ("3. Encrypt and Decrypt Data" );
69
227
System .out .println ("4. List Supported Algorithms" );
70
228
System .out .println ("5. Exit" );
229
+ System .out .println ("6. Change Device" );
71
230
System .out .print ("Enter your choice: " );
72
231
}
73
232
233
+
74
234
private int getUserChoice () {
75
235
Scanner scanner = new Scanner (System .in );
76
236
return scanner .nextInt ();
@@ -157,10 +317,24 @@ private void encryptDecryptData(PKCS11Manager manager, PKCS11Session session) {
157
317
}
158
318
159
319
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 ());
164
338
}
165
339
}
166
340
}
@@ -169,8 +343,7 @@ public class PKCS11Example {
169
343
public static void main (String [] args ) {
170
344
String userDir = System .getProperty ("user.dir" );
171
345
PKCS11 example = new PKCS11 (
172
- Paths .get (userDir , "lib" , "opensc-pkcs11.dll" ),
173
- "123456"
346
+ Paths .get (userDir , "lib" , "opensc-pkcs11.dll" )
174
347
);
175
348
example .run ();
176
349
}
0 commit comments