1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.github.tonywasher.joceanus.prometheus.security;
18
19 import io.github.tonywasher.joceanus.gordianknot.api.base.GordianException;
20 import io.github.tonywasher.joceanus.gordianknot.api.factory.GordianFactory;
21 import io.github.tonywasher.joceanus.gordianknot.api.factory.GordianFactory.GordianFactoryLock;
22 import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianKeyPair;
23 import io.github.tonywasher.joceanus.gordianknot.api.keyset.GordianBadCredentialsException;
24 import io.github.tonywasher.joceanus.gordianknot.api.keyset.GordianKeySet;
25 import io.github.tonywasher.joceanus.gordianknot.api.keyset.GordianKeySetFactory;
26 import io.github.tonywasher.joceanus.gordianknot.api.lock.GordianKeyPairLock;
27 import io.github.tonywasher.joceanus.gordianknot.api.lock.GordianKeySetLock;
28 import io.github.tonywasher.joceanus.gordianknot.api.lock.GordianLock;
29 import io.github.tonywasher.joceanus.gordianknot.api.lock.GordianLockFactory;
30 import io.github.tonywasher.joceanus.gordianknot.api.lock.GordianPasswordLockSpec;
31 import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
32 import io.github.tonywasher.joceanus.oceanus.convert.OceanusDataConverter;
33 import io.github.tonywasher.joceanus.oceanus.logger.OceanusLogManager;
34 import io.github.tonywasher.joceanus.oceanus.logger.OceanusLogger;
35 import io.github.tonywasher.joceanus.prometheus.exc.PrometheusDataException;
36 import io.github.tonywasher.joceanus.prometheus.exc.PrometheusSecurityException;
37
38 import java.nio.ByteBuffer;
39 import java.util.ArrayList;
40 import java.util.Arrays;
41 import java.util.List;
42 import java.util.Objects;
43
44
45
46
47 public class PrometheusSecurityPasswordCache {
48
49
50
51 private static final OceanusLogger LOGGER = OceanusLogManager.getLogger(PrometheusSecurityPasswordCache.class);
52
53
54
55
56 private static final String PASSWORD_FAIL = "Password attempt failed";
57
58
59
60
61 private final List<PrometheusLockCache<?>> theLocks;
62
63
64
65
66 private final List<ByteBuffer> thePasswords;
67
68
69
70
71 private final GordianFactory theFactory;
72
73
74
75
76 private final GordianKeySetFactory theKeySetFactory;
77
78
79
80
81 private final GordianLockFactory theLockFactory;
82
83
84
85
86 private final GordianPasswordLockSpec theLockSpec;
87
88
89
90
91 private final GordianKeySet theKeySet;
92
93
94
95
96
97
98
99
100 PrometheusSecurityPasswordCache(final PrometheusSecurityPasswordManager pManager,
101 final GordianPasswordLockSpec pLockSpec) throws OceanusException {
102
103 try {
104
105 theFactory = pManager.getSecurityFactory();
106 theKeySetFactory = theFactory.getKeySetFactory();
107 theLockFactory = theFactory.getLockFactory();
108 theLockSpec = pLockSpec;
109
110
111 theKeySet = theKeySetFactory.generateKeySet(pLockSpec.getKeySetSpec());
112
113
114 theLocks = new ArrayList<>();
115 thePasswords = new ArrayList<>();
116
117 } catch (GordianException e) {
118 throw new PrometheusSecurityException(e);
119 }
120 }
121
122
123
124
125
126
127
128
129 void addResolvedFactory(final GordianFactoryLock pFactory,
130 final char[] pPassword) throws OceanusException {
131 byte[] myPasswordBytes = null;
132 try {
133
134 myPasswordBytes = OceanusDataConverter.charsToByteArray(pPassword);
135 final byte[] myEncrypted = theKeySet.encryptBytes(myPasswordBytes);
136
137
138 final ByteBuffer myBuffer = ByteBuffer.wrap(myEncrypted);
139 theLocks.add(new PrometheusLockCache<>(pFactory, myBuffer));
140 thePasswords.add(myBuffer);
141
142
143 } catch (GordianException e) {
144 throw new PrometheusSecurityException(e);
145
146 } finally {
147
148 if (myPasswordBytes != null) {
149 Arrays.fill(myPasswordBytes, (byte) 0);
150 }
151 }
152 }
153
154
155
156
157
158
159
160
161 void addResolvedKeySet(final GordianKeySetLock pKeySet,
162 final char[] pPassword) throws OceanusException {
163 byte[] myPasswordBytes = null;
164 try {
165
166 myPasswordBytes = OceanusDataConverter.charsToByteArray(pPassword);
167 final byte[] myEncrypted = theKeySet.encryptBytes(myPasswordBytes);
168
169
170 final ByteBuffer myBuffer = ByteBuffer.wrap(myEncrypted);
171 theLocks.add(new PrometheusLockCache<>(pKeySet, myBuffer));
172 thePasswords.add(myBuffer);
173
174 } catch (GordianException e) {
175 throw new PrometheusSecurityException(e);
176
177 } finally {
178
179 if (myPasswordBytes != null) {
180 Arrays.fill(myPasswordBytes, (byte) 0);
181 }
182 }
183 }
184
185
186
187
188
189
190
191
192 void addResolvedKeyPair(final GordianKeyPairLock pKeyPair,
193 final char[] pPassword) throws OceanusException {
194 byte[] myPasswordBytes = null;
195 try {
196
197 myPasswordBytes = OceanusDataConverter.charsToByteArray(pPassword);
198 final byte[] myEncrypted = theKeySet.encryptBytes(myPasswordBytes);
199
200
201 final ByteBuffer myBuffer = ByteBuffer.wrap(myEncrypted);
202 theLocks.add(new PrometheusLockCache<>(pKeyPair, myBuffer));
203 thePasswords.add(myBuffer);
204
205 } catch (GordianException e) {
206 throw new PrometheusSecurityException(e);
207
208 } finally {
209
210 if (myPasswordBytes != null) {
211 Arrays.fill(myPasswordBytes, (byte) 0);
212 }
213 }
214 }
215
216
217
218
219
220
221
222 GordianFactoryLock lookUpResolvedFactoryLock(final byte[] pLockBytes) {
223
224 for (PrometheusLockCache<?> myCurr : theLocks) {
225
226 if (myCurr.getLock() instanceof GordianFactoryLock
227 && Arrays.equals(pLockBytes, myCurr.getLock().getLockBytes())) {
228 return (GordianFactoryLock) myCurr.getLock();
229 }
230 }
231
232
233 return null;
234 }
235
236
237
238
239
240
241
242 GordianKeySetLock lookUpResolvedKeySetLock(final byte[] pLockBytes) {
243
244 for (PrometheusLockCache<?> myCurr : theLocks) {
245
246 if (myCurr.getLock() instanceof GordianKeySetLock
247 && Arrays.equals(pLockBytes, myCurr.getLock().getLockBytes())) {
248 return (GordianKeySetLock) myCurr.getLock();
249 }
250 }
251
252
253 return null;
254 }
255
256
257
258
259
260
261
262
263 GordianKeyPairLock lookUpResolvedKeyPairLock(final byte[] pLockBytes,
264 final GordianKeyPair pKeyPair) {
265
266 for (PrometheusLockCache<?> myCurr : theLocks) {
267
268 if (myCurr.getLock() instanceof GordianKeyPairLock
269 && Arrays.equals(pLockBytes, myCurr.getLock().getLockBytes())
270 && pKeyPair.equals(((GordianKeyPairLock) myCurr.getLock()).getKeyPair())) {
271 return (GordianKeyPairLock) myCurr.getLock();
272 }
273 }
274
275
276 return null;
277 }
278
279
280
281
282
283
284
285
286 ByteBuffer lookUpResolvedPassword(final Object pReference) throws OceanusException {
287
288 if (pReference instanceof GordianLock) {
289
290 final GordianLock<?> myReference = (GordianLock<?>) pReference;
291 for (PrometheusLockCache<?> myCurr : theLocks) {
292
293 if (Objects.equals(myReference, myCurr.getLock())) {
294 return myCurr.getPassword();
295 }
296 }
297 }
298
299
300 throw new PrometheusDataException("Referenced Object not known");
301 }
302
303
304
305
306
307
308
309 GordianFactoryLock attemptKnownPasswordsForFactoryLock(final byte[] pLockBytes) {
310
311 for (ByteBuffer myCurr : thePasswords) {
312
313 final GordianFactoryLock myFactory = attemptPasswordForFactoryLock(pLockBytes, myCurr.array());
314
315
316 if (myFactory != null) {
317
318 theLocks.add(new PrometheusLockCache<>(myFactory, myCurr));
319 return myFactory;
320 }
321 }
322
323
324 return null;
325 }
326
327
328
329
330
331
332
333
334 private GordianFactoryLock attemptPasswordForFactoryLock(final byte[] pLockBytes,
335 final byte[] pPassword) {
336
337 byte[] myPasswordBytes = null;
338 char[] myPasswordChars = null;
339 try {
340
341 myPasswordBytes = theKeySet.decryptBytes(pPassword);
342 myPasswordChars = OceanusDataConverter.bytesToCharArray(myPasswordBytes);
343
344
345 return theFactory.resolveFactoryLock(pLockBytes, myPasswordChars);
346
347
348 } catch (GordianException
349 | OceanusException e) {
350 LOGGER.error(PASSWORD_FAIL, e);
351 return null;
352
353 } catch (GordianBadCredentialsException e) {
354 return null;
355
356 } finally {
357
358 if (myPasswordBytes != null) {
359 Arrays.fill(myPasswordBytes, (byte) 0);
360 }
361 if (myPasswordChars != null) {
362 Arrays.fill(myPasswordChars, (char) 0);
363 }
364 }
365 }
366
367
368
369
370
371
372
373 GordianKeySetLock attemptKnownPasswordsForKeySetLock(final byte[] pLockBytes) {
374
375 for (ByteBuffer myCurr : thePasswords) {
376
377 final GordianKeySetLock myKeySet = attemptPasswordForKeySetLock(pLockBytes, myCurr.array());
378
379
380 if (myKeySet != null) {
381
382 theLocks.add(new PrometheusLockCache<>(myKeySet, myCurr));
383 return myKeySet;
384 }
385 }
386
387
388 return null;
389 }
390
391
392
393
394
395
396
397
398 private GordianKeySetLock attemptPasswordForKeySetLock(final byte[] pLockBytes,
399 final byte[] pPassword) {
400
401 byte[] myPasswordBytes = null;
402 char[] myPasswordChars = null;
403 try {
404
405 myPasswordBytes = theKeySet.decryptBytes(pPassword);
406 myPasswordChars = OceanusDataConverter.bytesToCharArray(myPasswordBytes);
407
408
409 return theLockFactory.resolveKeySetLock(pLockBytes, myPasswordChars);
410
411
412 } catch (GordianException
413 | OceanusException e) {
414 LOGGER.error(PASSWORD_FAIL, e);
415 return null;
416
417 } catch (GordianBadCredentialsException e) {
418 return null;
419
420 } finally {
421
422 if (myPasswordBytes != null) {
423 Arrays.fill(myPasswordBytes, (byte) 0);
424 }
425 if (myPasswordChars != null) {
426 Arrays.fill(myPasswordChars, (char) 0);
427 }
428 }
429 }
430
431
432
433
434
435
436
437
438 GordianKeyPairLock attemptKnownPasswordsForKeyPairLock(final byte[] pLockBytes,
439 final GordianKeyPair pKeyPair) {
440
441 for (ByteBuffer myCurr : thePasswords) {
442
443 final GordianKeyPairLock myKeyPair = attemptPasswordForKeyPairLock(pLockBytes, pKeyPair, myCurr.array());
444
445
446 if (myKeyPair != null) {
447
448 theLocks.add(new PrometheusLockCache<>(myKeyPair, myCurr));
449 return myKeyPair;
450 }
451 }
452
453
454 return null;
455 }
456
457
458
459
460
461
462
463
464
465 private GordianKeyPairLock attemptPasswordForKeyPairLock(final byte[] pLockBytes,
466 final GordianKeyPair pKeyPair,
467 final byte[] pPassword) {
468
469 byte[] myPasswordBytes = null;
470 char[] myPasswordChars = null;
471 try {
472
473 myPasswordBytes = theKeySet.decryptBytes(pPassword);
474 myPasswordChars = OceanusDataConverter.bytesToCharArray(myPasswordBytes);
475
476
477 return theLockFactory.resolveKeyPairLock(pLockBytes, pKeyPair, myPasswordChars);
478
479
480 } catch (GordianException
481 | OceanusException e) {
482 LOGGER.error(PASSWORD_FAIL, e);
483 return null;
484
485 } catch (GordianBadCredentialsException e) {
486 return null;
487
488 } finally {
489
490 if (myPasswordBytes != null) {
491 Arrays.fill(myPasswordBytes, (byte) 0);
492 }
493 if (myPasswordChars != null) {
494 Arrays.fill(myPasswordChars, (char) 0);
495 }
496 }
497 }
498
499
500
501
502
503
504
505
506
507 GordianFactoryLock createSimilarFactoryLock(final GordianFactory pFactory,
508 final ByteBuffer pPassword) throws OceanusException {
509
510 byte[] myPasswordBytes = null;
511 char[] myPasswordChars = null;
512 try {
513
514 myPasswordBytes = theKeySet.decryptBytes(pPassword.array());
515 myPasswordChars = OceanusDataConverter.bytesToCharArray(myPasswordBytes);
516
517
518 final GordianFactoryLock myLock = theFactory.newFactoryLock(pFactory, theLockSpec, myPasswordChars);
519
520
521 theLocks.add(new PrometheusLockCache<>(myLock, pPassword));
522 return myLock;
523
524 } catch (GordianException e) {
525 throw new PrometheusSecurityException(e);
526
527 } finally {
528
529 if (myPasswordBytes != null) {
530 Arrays.fill(myPasswordBytes, (byte) 0);
531 }
532 if (myPasswordChars != null) {
533 Arrays.fill(myPasswordChars, (char) 0);
534 }
535 }
536 }
537
538
539
540
541
542
543
544
545
546 GordianKeySetLock createSimilarKeySetLock(final GordianKeySet pKeySet,
547 final ByteBuffer pPassword) throws OceanusException {
548
549 byte[] myPasswordBytes = null;
550 char[] myPasswordChars = null;
551 try {
552
553 myPasswordBytes = theKeySet.decryptBytes(pPassword.array());
554 myPasswordChars = OceanusDataConverter.bytesToCharArray(myPasswordBytes);
555
556
557 final GordianKeySetLock myLock = theLockFactory.newKeySetLock(pKeySet, theLockSpec, myPasswordChars);
558
559
560 theLocks.add(new PrometheusLockCache<>(myLock, pPassword));
561 return myLock;
562
563 } catch (GordianException e) {
564 throw new PrometheusSecurityException(e);
565
566 } finally {
567
568 if (myPasswordBytes != null) {
569 Arrays.fill(myPasswordBytes, (byte) 0);
570 }
571 if (myPasswordChars != null) {
572 Arrays.fill(myPasswordChars, (char) 0);
573 }
574 }
575 }
576
577
578
579
580
581
582
583
584
585 GordianKeyPairLock createSimilarKeyPairLock(final GordianKeyPair pKeyPair,
586 final ByteBuffer pPassword) throws OceanusException {
587
588 byte[] myPasswordBytes = null;
589 char[] myPasswordChars = null;
590 try {
591
592 myPasswordBytes = theKeySet.decryptBytes(pPassword.array());
593 myPasswordChars = OceanusDataConverter.bytesToCharArray(myPasswordBytes);
594
595
596 return theLockFactory.newKeyPairLock(theLockSpec, pKeyPair, myPasswordChars);
597
598 } catch (GordianException e) {
599 throw new PrometheusSecurityException(e);
600
601 } finally {
602
603 if (myPasswordBytes != null) {
604 Arrays.fill(myPasswordBytes, (byte) 0);
605 }
606 if (myPasswordChars != null) {
607 Arrays.fill(myPasswordChars, (char) 0);
608 }
609 }
610 }
611
612
613
614
615
616
617
618 static class PrometheusLockCache<T> {
619
620
621
622 private final GordianLock<T> theLock;
623
624
625
626
627 private final ByteBuffer thePassword;
628
629
630
631
632
633
634
635 PrometheusLockCache(final GordianLock<T> pLock,
636 final ByteBuffer pPassword) {
637 theLock = pLock;
638 thePassword = pPassword;
639 }
640
641
642
643
644
645
646 GordianLock<T> getLock() {
647 return theLock;
648 }
649
650
651
652
653
654
655 ByteBuffer getPassword() {
656 return thePassword;
657 }
658 }
659 }