1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package uk.co.westhawk.snmp.util;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 import java.security.MessageDigest;
53 import java.security.NoSuchAlgorithmException;
54 import java.util.*;
55
56 import uk.co.westhawk.snmp.stack.*;
57
58 import org.bouncycastle.crypto.digests.*;
59 import org.bouncycastle.crypto.params.*;
60 import org.bouncycastle.crypto.engines.*;
61
62 import static uk.co.westhawk.snmp.stack.SnmpContextv3Face.MD5_PROTOCOL;
63 import static uk.co.westhawk.snmp.stack.SnmpContextv3Face.SHA1_PROTOCOL;
64 import static uk.co.westhawk.snmp.stack.SnmpContextv3Face.SHA224_PROTOCOL;
65 import static uk.co.westhawk.snmp.stack.SnmpContextv3Face.SHA256_PROTOCOL;
66 import static uk.co.westhawk.snmp.stack.SnmpContextv3Face.SHA384_PROTOCOL;
67 import static uk.co.westhawk.snmp.stack.SnmpContextv3Face.SHA512_PROTOCOL;
68 import static uk.co.westhawk.snmp.stack.SnmpContextv3Face.AES_ENCRYPT;
69 import static uk.co.westhawk.snmp.stack.SnmpContextv3Face.AES192_ENCRYPT;
70 import static uk.co.westhawk.snmp.stack.SnmpContextv3Face.AES256_ENCRYPT;
71 import static uk.co.westhawk.snmp.stack.SnmpContextv3Basis.AES128_KEY_LENGTH;
72 import static uk.co.westhawk.snmp.stack.SnmpContextv3Basis.AES192_KEY_LENGTH;
73 import static uk.co.westhawk.snmp.stack.SnmpContextv3Basis.AES256_KEY_LENGTH;
74
75
76
77
78
79
80
81
82 public class SnmpUtilities extends Object {
83
84
85
86 private static final String SHA256_ALGORITHM = "SHA-256";
87
88
89
90 private static final String SHA512_ALGORITHM = "SHA-512";
91
92
93
94 private static final String SHA224_ALGORITHM = "SHA-224";
95
96
97
98 private static final String SHA384_ALGORITHM = "SHA-384";
99
100 private static final String version_id = "@(#)$Id: SnmpUtilities.java,v 1.27 2009/03/05 12:57:57 birgita Exp $ Copyright Westhawk Ltd";
101
102 final static int ONEMEG = 1048576;
103 final static int SALT_LENGTH = 8;
104
105 private static int salt_count = -1;
106 private static long asalt;
107
108
109 static byte[] dummySha1FingerPrint = new byte[12];
110
111
112 static byte[] dummySHA256FingerPrint = new byte[24];
113
114
115 static byte[] dummySHA512FingerPrint = new byte[48];
116
117
118 static byte[] dummySHA224FingerPrint = new byte[16];
119
120
121 static byte[] dummySHA384FingerPrint = new byte[32];
122
123 private static final Map<Integer, byte[]> DUMMY_FINGERPRINT_MAP = new HashMap<>();
124 static {
125 DUMMY_FINGERPRINT_MAP.put(SnmpContextv3Basis.SHA256_PROTOCOL, dummySHA256FingerPrint);
126 DUMMY_FINGERPRINT_MAP.put(SnmpContextv3Basis.SHA1_PROTOCOL, dummySha1FingerPrint);
127 DUMMY_FINGERPRINT_MAP.put(SnmpContextv3Basis.MD5_PROTOCOL, dummySha1FingerPrint);
128 DUMMY_FINGERPRINT_MAP.put(SnmpContextv3Basis.SHA512_PROTOCOL, dummySHA512FingerPrint);
129 DUMMY_FINGERPRINT_MAP.put(SnmpContextv3Basis.SHA224_PROTOCOL, dummySHA224FingerPrint);
130 DUMMY_FINGERPRINT_MAP.put(SnmpContextv3Basis.SHA384_PROTOCOL, dummySHA384FingerPrint);
131 }
132
133
134
135
136
137
138
139 public static String getSnmpVersionString(int version) {
140 String versionString;
141
142 switch (version) {
143 case SnmpConstants.SNMP_VERSION_1:
144 versionString = "SNMPv1";
145 break;
146 case SnmpConstants.SNMP_VERSION_2c:
147 versionString = "SNMPv2c";
148 break;
149 case SnmpConstants.SNMP_VERSION_3:
150 versionString = "SNMPv3";
151 break;
152 default:
153 versionString = "Unsupported version no " + version;
154 }
155 return versionString;
156 }
157
158
159
160
161
162
163
164
165
166
167
168 public static byte[] toBytes(String hexStr) {
169 byte mask = (byte) 0x7F;
170 byte[] bytes = new byte[0];
171
172 if (hexStr != null) {
173 hexStr = hexStr.toUpperCase();
174 int len = hexStr.length();
175 bytes = new byte[(len / 2)];
176 int sPos = 0;
177 int bPos = 0;
178 while (sPos < len) {
179 char a = hexStr.charAt(sPos);
180 char b = hexStr.charAt(sPos + 1);
181
182 int v1 = Character.digit(a, 16);
183 int v2 = Character.digit(b, 16);
184 int v3 = (int) (v1 * 16 + v2);
185 bytes[bPos] = (byte) v3;
186
187 sPos += 2;
188 bPos++;
189 }
190 }
191 return bytes;
192 }
193
194
195
196
197
198
199
200
201
202
203
204 public static byte longToByte(long l) throws IllegalArgumentException {
205 byte ret = 0;
206 if ((l < 0) || (l > 255)) {
207 throw new IllegalArgumentException("Valid byte values are between 0 and 255."
208 + "Got " + l);
209 }
210 ret = (byte) (l);
211 return ret;
212 }
213
214
215
216
217
218
219
220
221
222
223
224
225 public static byte[] longToByte(long[] l) throws IllegalArgumentException {
226 int len = l.length;
227 byte[] ret = new byte[len];
228 for (int i = 0; i < len; i++) {
229 ret[i] = longToByte(l[i]);
230 }
231 return ret;
232 }
233
234
235
236
237
238
239
240 public static void dumpBytes(String headerStr, byte[] bytes) {
241 StringBuffer buf = new StringBuffer(bytes.length);
242 buf.append("\n");
243 buf.append(headerStr).append("\n");
244 buf.append("bytes.length: ").append(bytes.length).append("\n");
245 int len = bytes.length;
246 int i = 0;
247 for (i = 0; i < len; i++) {
248 buf.append(toHex(bytes[i]) + " ");
249 if (0 == ((i + 1) % 8)) {
250 buf.append("\n");
251 }
252 }
253 buf.append("\n");
254 System.out.println(buf.toString());
255 }
256
257
258
259
260
261
262
263
264
265
266 public static String toHexString(byte[] bytes) {
267 String str = "";
268 if (bytes != null) {
269 int len = bytes.length;
270 for (int i = 0; i < len; i++) {
271 str += toHex(bytes[i]);
272 }
273 }
274 return str;
275 }
276
277
278
279
280
281
282
283 public static String toHex(int val) {
284 int val1, val2;
285
286 val1 = (val >> 4) & 0x0F;
287 val2 = (val & 0x0F);
288
289 return ("" + HEX_DIGIT[val1] + HEX_DIGIT[val2]);
290 }
291
292 final static char[] HEX_DIGIT = { '0', '1', '2', '3', '4', '5', '6', '7',
293 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
294
295
296
297
298
299
300
301
302 public static boolean areBytesEqual(byte[] array1, byte[] array2) {
303 boolean same = true;
304 int len1 = array1.length;
305 if (len1 == array2.length) {
306 int i = 0;
307 while (i < len1 && same) {
308 same = (array1[i] == array2[i]);
309 i++;
310 }
311 } else {
312 same = false;
313 }
314 return same;
315 }
316
317
318
319
320
321
322
323
324
325
326
327
328 public static byte[] getLocalizedKeyMD5(byte[] passwKey, String engineId) {
329 byte[] ret = null;
330 MD5Digest mdc = new MD5Digest();
331 mdc.reset();
332
333 byte[] beid = toBytes(engineId);
334 if ((beid != null) && (passwKey != null)) {
335
336 mdc.update(passwKey, 0, passwKey.length);
337 mdc.update(beid, 0, beid.length);
338 mdc.update(passwKey, 0, passwKey.length);
339 ret = new byte[mdc.getDigestSize()];
340 mdc.doFinal(ret, 0);
341 }
342 return ret;
343 }
344
345
346
347
348
349
350
351
352
353 public static byte[] getLocalizedKeySHA1(byte[] passwKey, String engineId) {
354 byte[] ret = null;
355 SHA1Digest mdc = new SHA1Digest();
356 mdc.reset();
357
358 byte[] beid = toBytes(engineId);
359 if ((beid != null) && (passwKey != null)) {
360
361 mdc.update(passwKey, 0, passwKey.length);
362 mdc.update(beid, 0, beid.length);
363 mdc.update(passwKey, 0, passwKey.length);
364 ret = new byte[mdc.getDigestSize()];
365 mdc.doFinal(ret, 0);
366 }
367 return ret;
368 }
369
370
371
372
373
374
375
376
377
378
379
380
381 public static byte[] passwordToKeySHA1(String password) {
382 SHA1Digest sha;
383 byte[] ret = null;
384 sha = new SHA1Digest();
385 byte[] passwordBuf = new byte[64];
386 int pl = password.length();
387 byte[] pass = new byte[pl];
388
389
390 for (int i = 0; i < pl; i++) {
391 pass[i] = (byte) (0xFF & password.charAt(i));
392 }
393
394 int count = 0;
395 int passwordIndex = 0;
396 Date then = (AsnObject.debug > 1) ? new Date() : null;
397
398 synchronized (sha) {
399 while (count < ONEMEG) {
400 int cp = 0;
401 int i = 0;
402 while (i < 64) {
403 int pim = passwordIndex % pl;
404 int len = 64 - cp;
405 int pr = pl - pim;
406 if (len > pr) {
407 len = pr;
408 }
409 System.arraycopy(pass, pim, passwordBuf, cp, len);
410 i += len;
411 cp += len;
412 passwordIndex += len;
413 }
414
415
416 sha.update(passwordBuf, 0, passwordBuf.length);
417 count += 64;
418 }
419
420 ret = new byte[sha.getDigestSize()];
421 sha.doFinal(ret, 0);
422 }
423
424 if (AsnObject.debug > 1) {
425 Date now = new Date();
426 long diff = now.getTime() - then.getTime();
427 System.out.println("(Complex) pass to key takes " + diff / 1000.0);
428 }
429
430 return ret;
431 }
432
433
434
435
436
437
438
439
440
441
442
443
444 public static byte[] passwordToKeyMD5(String password) {
445 MD5Digest mdc;
446 byte[] ret = null;
447 mdc = new MD5Digest();
448 byte[] passwordBuf = new byte[64];
449 int pl = password.length();
450 byte[] pass = new byte[pl];
451
452
453 for (int i = 0; i < pl; i++) {
454 pass[i] = (byte) (0xFF & password.charAt(i));
455 }
456
457 int count = 0;
458 int passwordIndex = 0;
459 Date then = (AsnObject.debug > 1) ? new Date() : null;
460 synchronized (mdc) {
461 while (count < ONEMEG) {
462 int cp = 0;
463 int i = 0;
464 while (i < 64) {
465 int pim = passwordIndex % pl;
466 int len = 64 - cp;
467 int pr = pl - pim;
468 if (len > pr) {
469 len = pr;
470 }
471 System.arraycopy(pass, pim, passwordBuf, cp, len);
472 i += len;
473 cp += len;
474 passwordIndex += len;
475 }
476 mdc.update(passwordBuf, 0, passwordBuf.length);
477 count += 64;
478 }
479
480 ret = new byte[mdc.getDigestSize()];
481 mdc.doFinal(ret, 0);
482 }
483
484 if (AsnObject.debug > 1) {
485 Date now = new Date();
486 long diff = now.getTime() - then.getTime();
487 System.out.println("(Complex) pass to key takes " + diff / 1000.0);
488 }
489
490 return ret;
491 }
492
493
494
495
496
497
498
499
500 public final static byte[] getFingerPrintMD5(byte[] key, byte[] message) {
501 if ((AsnObject.debug > 5) && (key.length != 16)) {
502 System.out.println("MD5 key length wrong");
503 }
504 return getFingerPrint(key, message, false);
505 }
506
507
508
509
510
511
512
513
514 public final static byte[] getFingerPrintSHA1(byte[] key, byte[] message) {
515 if ((AsnObject.debug > 5) && (key.length != 20)) {
516 System.out.println("SHA1 key length wrong");
517 }
518 return getFingerPrint(key, message, true);
519 }
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536 public final static byte[] getSaltDES(int snmpEngineBoots) {
537 if (salt_count == -1) {
538
539 Random rand = new Random();
540 salt_count = rand.nextInt();
541 }
542 byte[] salt = new byte[SALT_LENGTH];
543 setBytesFromInt(salt, snmpEngineBoots, 0);
544 setBytesFromInt(salt, salt_count, SALT_LENGTH / 2);
545 salt_count++;
546 return salt;
547 }
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569 public static byte[] getSaltAES() {
570 if (asalt == 0) {
571 java.security.SecureRandom rand = new java.security.SecureRandom();
572 asalt = rand.nextLong();
573 } else {
574 asalt++;
575 }
576 byte[] tsalt = new byte[8];
577 setBytesFromLong(tsalt, asalt, 0);
578 return tsalt;
579 }
580
581
582
583
584
585
586
587
588
589
590 public final static byte[] getDESKey(byte[] secretPrivacyKey)
591 throws PduException {
592 byte[] desKey = new byte[8];
593 if (secretPrivacyKey.length < 16) {
594 throw new PduException("SnmpUtilities.getDESKey():"
595 + " secretPrivacyKey is < 16");
596 }
597 System.arraycopy(secretPrivacyKey, 0, desKey, 0, 8);
598 return desKey;
599 }
600
601
602
603
604
605
606
607
608
609 public static final byte[] getAESKey(byte[] secretPrivacyKey, int protocolVersion)
610 throws PduException {
611 int len = secretPrivacyKey.length;
612
613 final byte[] aesKey;
614 if (protocolVersion == AES_ENCRYPT) {
615 if (len < AES128_KEY_LENGTH) {
616 throw new PduException("SnmpUtilities.getAESKey():" + " secretPrivacyKey is < 16 for AES_ENCRYPT");
617 }
618 aesKey = new byte[AES128_KEY_LENGTH];
619 } else if (protocolVersion == AES192_ENCRYPT) {
620 if (len < AES192_KEY_LENGTH) {
621 throw new PduException("SnmpUtilities.getAESKey():" + " secretPrivacyKey is < 24 for AES192_ENCRYPT");
622 }
623 aesKey = new byte[AES192_KEY_LENGTH];
624 } else if (protocolVersion == AES256_ENCRYPT) {
625 if (len < AES256_KEY_LENGTH) {
626 throw new PduException(
627 "SnmpUtilities.getAESKey():" + " secretPrivacyKey is < 32 for AES256_ENCRYPT");
628 }
629 aesKey = new byte[AES256_KEY_LENGTH];
630 } else {
631 throw new PduException("Unsupported AES protocol version: " + protocolVersion);
632 }
633
634 System.arraycopy(secretPrivacyKey, 0, aesKey, 0, aesKey.length);
635 return aesKey;
636 }
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651 public final static byte[] getDESInitialValue(byte[] secretPrivacyKey,
652 byte[] salt) throws PduException {
653 byte[] initV = new byte[8];
654 if (secretPrivacyKey.length < 16) {
655 throw new PduException("SnmpUtilities.getInitialValue():"
656 + " secretPrivacyKey is < 16");
657 }
658
659 int spk = 8;
660 for (int i = 0; i < initV.length; i++) {
661 initV[i] = (byte) (secretPrivacyKey[spk] ^ salt[i]);
662 spk++;
663 }
664 return initV;
665 }
666
667
668
669
670
671
672
673
674
675
676
677 public static byte[] getAESInitialValue(int engineBoots, int engineTime, byte[] salt) {
678 byte ret[] = new byte[16];
679
680
681
682 setBytesFromInt(ret, engineBoots, 0);
683
684
685
686 setBytesFromInt(ret, engineTime, 4);
687
688
689
690 ret[8] = salt[0];
691 ret[9] = salt[1];
692 ret[10] = salt[2];
693 ret[11] = salt[3];
694 ret[12] = salt[4];
695 ret[13] = salt[5];
696 ret[14] = salt[6];
697 ret[15] = salt[7];
698 return ret;
699 }
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752 public static byte[] AESencrypt(byte[] plaintext,
753 byte[] secretPrivacyKey,
754 int engineBoots,
755 int engineTime,
756 byte[] salt,
757 int protocolVersion)
758 throws EncodingException {
759 byte[] aesKey = null;
760 byte[] iv = null;
761 try {
762 aesKey = getAESKey(secretPrivacyKey, protocolVersion);
763 iv = getAESInitialValue(engineBoots, engineTime, salt);
764 } catch (PduException exc) {
765 throw new EncodingException(exc.getMessage());
766 }
767
768 AESEngine aes = new AESEngine();
769 KeyParameter param = new KeyParameter(aesKey);
770 aes.init(true, param);
771
772
773 int newL = plaintext.length;
774 int bcount = newL / 16;
775 byte[] result = new byte[newL];
776 byte[] in = new byte[16];
777 byte[] out = new byte[16];
778 int posIn = 0;
779 int posResult = 0;
780
781 System.arraycopy(iv, 0, in, 0, 16);
782 for (int b = 0; b < bcount; b++) {
783 aes.processBlock(in, 0, out, 0);
784 for (int i = 0; i < 16; i++) {
785 in[i] = result[posResult] = (byte) (out[i] ^ plaintext[posIn]);
786 posResult++;
787 posIn++;
788 }
789 }
790
791 if (posIn < newL) {
792 aes.processBlock(in, 0, out, 0);
793 for (int i = 0; posIn < newL; i++) {
794 result[posResult] = (byte) (out[i] ^ plaintext[posIn]);
795 posResult++;
796 posIn++;
797 }
798 }
799 return result;
800 }
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817 public final static byte[] DESencrypt(byte[] plain, byte[] secretPrivacyKey,
818 byte[] salt) throws EncodingException {
819 byte[] desKey = null;
820 byte[] iv = null;
821 try {
822 desKey = getDESKey(secretPrivacyKey);
823 iv = getDESInitialValue(secretPrivacyKey, salt);
824 } catch (PduException exc) {
825 throw new EncodingException(exc.getMessage());
826 }
827
828
829 int l = plain.length;
830 int div = l / 8;
831 int mod = l % 8;
832 if (mod > 0) {
833 div++;
834 }
835 int newL = div * 8;
836 byte[] paddedOrig = new byte[newL];
837 System.arraycopy(plain, 0, paddedOrig, 0, l);
838 for (int i = l; i < newL; i++) {
839 paddedOrig[i] = (byte) 0x0;
840 }
841
842 DESEngine des = new DESEngine();
843 DESParameters param = new DESParameters(desKey);
844 des.init(true, param);
845
846 byte[] result = new byte[newL];
847 byte[] in = new byte[8];
848 byte[] cipherText = iv;
849 int posIn = 0;
850 int posResult = 0;
851 for (int b = 0; b < div; b++) {
852 for (int i = 0; i < 8; i++) {
853 in[i] = (byte) (paddedOrig[posIn] ^ cipherText[i]);
854 posIn++;
855 }
856 des.processBlock(in, 0, cipherText, 0);
857 System.arraycopy(cipherText, 0, result, posResult, cipherText.length);
858 posResult += cipherText.length;
859 }
860 return result;
861 }
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887 public final static byte[] DESdecrypt(byte[] encryptedText, byte[] salt,
888 byte[] secretPrivacyKey) throws DecodingException {
889 int l = encryptedText.length;
890 int div = l / 8;
891 int mod = l % 8;
892 if (mod != 0) {
893 throw new DecodingException("SnmpUtilities.decrypt():"
894 + " The encrypted scoped PDU should be a multiple of 8 bytes");
895 }
896
897 byte[] desKey = null;
898 byte[] iv = null;
899 try {
900 desKey = getDESKey(secretPrivacyKey);
901 iv = getDESInitialValue(secretPrivacyKey, salt);
902 } catch (PduException exc) {
903 throw new DecodingException(exc.getMessage());
904 }
905
906 DESEngine des = new DESEngine();
907 DESParameters param = new DESParameters(desKey);
908 des.init(false, param);
909
910 byte[] plain = new byte[l];
911 byte[] in = new byte[8];
912 byte[] out = new byte[8];
913 byte[] cipherText = iv;
914 int posPlain = 0;
915 int posEncr = 0;
916 for (int b = 0; b < div; b++) {
917 System.arraycopy(encryptedText, posEncr, in, 0, in.length);
918 posEncr += in.length;
919 des.processBlock(in, 0, out, 0);
920 for (int i = 0; i < 8; i++) {
921 plain[posPlain] = (byte) (out[i] ^ cipherText[i]);
922 posPlain++;
923 }
924 System.arraycopy(in, 0, cipherText, 0, in.length);
925 }
926 return plain;
927 }
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956 public final static byte[] AESdecrypt(byte[] ciphertext,
957 byte[] secretPrivacyKey,
958 int engineBoots,
959 int engineTime,
960 byte[] salt,
961 int protocolVersion)
962 throws DecodingException {
963 byte[] aesKey = null;
964 byte[] iv = null;
965 try {
966 aesKey = getAESKey(secretPrivacyKey, protocolVersion);
967 iv = getAESInitialValue(engineBoots, engineTime, salt);
968 } catch (PduException exc) {
969 throw new DecodingException(exc.getMessage());
970 }
971
972 AESEngine aes = new AESEngine();
973 KeyParameter param = new KeyParameter(aesKey);
974 aes.init(true, param);
975
976
977 int newL = ciphertext.length;
978 int bcount = newL / 16;
979 byte[] result = new byte[newL];
980 byte[] in = new byte[16];
981 byte[] out = new byte[16];
982 int posIn = 0;
983 int posResult = 0;
984
985 System.arraycopy(iv, 0, in, 0, 16);
986 for (int b = 0; b < bcount; b++) {
987 aes.processBlock(in, 0, out, 0);
988 for (int i = 0; i < 16; i++) {
989 result[posResult] = (byte) (out[i] ^ ciphertext[posIn]);
990 in[i] = ciphertext[posIn];
991 posResult++;
992 posIn++;
993 }
994 }
995
996 if (posIn < newL) {
997 aes.processBlock(in, 0, out, 0);
998 for (int i = 0; posIn < newL; i++) {
999 result[posResult] = (byte) (out[i] ^ ciphertext[posIn]);
1000 posResult++;
1001 posIn++;
1002 }
1003 }
1004 return result;
1005 }
1006
1007
1008 static byte[] getFingerPrint(byte[] key, byte[] message, boolean doSha) {
1009
1010 byte[] k1 = new byte[64];
1011 byte[] k2 = new byte[64];
1012
1013 byte z1 = (byte) (0 ^ 0x36);
1014 byte z2 = (byte) (0 ^ 0x5c);
1015 int kl = key.length;
1016 int i = 0;
1017 while (i < kl) {
1018 k1[i] = (byte) (ifb(key[i]) ^ 0x36);
1019 k2[i] = (byte) (ifb(key[i]) ^ 0x5c);
1020 i++;
1021 }
1022 while (i < 64) {
1023 k1[i] = z1;
1024 k2[i] = z2;
1025 i++;
1026 }
1027
1028 byte[] interm = null;
1029 GeneralDigest mdc = doSha ? ((GeneralDigest) new SHA1Digest()) : ((GeneralDigest) new MD5Digest());
1030 mdc.reset();
1031 mdc.update(k1, 0, k1.length);
1032 mdc.update(message, 0, message.length);
1033 interm = new byte[mdc.getDigestSize()];
1034 mdc.doFinal(interm, 0);
1035
1036
1037 byte[] rettmp = null;
1038 GeneralDigest mdc2 = doSha ? ((GeneralDigest) new SHA1Digest()) : ((GeneralDigest) new MD5Digest());
1039 mdc2.reset();
1040 mdc2.update(k2, 0, k2.length);
1041 mdc2.update(interm, 0, interm.length);
1042 rettmp = new byte[mdc2.getDigestSize()];
1043 mdc2.doFinal(rettmp, 0);
1044
1045
1046 byte[] ret = null;
1047 if (rettmp != null) {
1048 ret = new byte[12];
1049 System.arraycopy(rettmp, 0, ret, 0, 12);
1050 }
1051 return ret;
1052 }
1053
1054 final static int ifb(byte b) {
1055 return intFromByteWithoutStupidJavaSignExtension(b);
1056 }
1057
1058 final static int intFromByteWithoutStupidJavaSignExtension(byte val) {
1059 int ret = (0x7F) & val;
1060 if (val < 0) {
1061 ret += 128;
1062 }
1063 return ret;
1064 }
1065
1066 final static void setBytesFromInt(byte[] ret, int value, int offs) {
1067 int v = value;
1068 int j = offs;
1069 ret[j++] = (byte) ((v >>> 24) & 0xFF);
1070 ret[j++] = (byte) ((v >>> 16) & 0xFF);
1071 ret[j++] = (byte) ((v >>> 8) & 0xFF);
1072 ret[j++] = (byte) ((v >>> 0) & 0xFF);
1073 }
1074
1075 final static void setBytesFromLong(byte[] ret, long value, int offs) {
1076 long v = value;
1077 int j = offs;
1078 ret[j++] = (byte) ((v >>> 56) & 0xFF);
1079 ret[j++] = (byte) ((v >>> 48) & 0xFF);
1080 ret[j++] = (byte) ((v >>> 40) & 0xFF);
1081 ret[j++] = (byte) ((v >>> 32) & 0xFF);
1082 ret[j++] = (byte) ((v >>> 24) & 0xFF);
1083 ret[j++] = (byte) ((v >>> 16) & 0xFF);
1084 ret[j++] = (byte) ((v >>> 8) & 0xFF);
1085 ret[j++] = (byte) ((v >>> 0) & 0xFF);
1086 }
1087
1088
1089
1090
1091
1092
1093
1094
1095 public static byte[] passwordToKeySHA256(String userPrivacyPassword) {
1096 byte[] ret;
1097 byte[] passwordBuf = new byte[64];
1098 int pl = userPrivacyPassword.length();
1099 byte[] pass = new byte[pl];
1100
1101
1102 for (int i = 0; i < pl; i++) {
1103 pass[i] = (byte) (0xFF & userPrivacyPassword.charAt(i));
1104 }
1105
1106 int count = 0;
1107 int passwordIndex = 0;
1108
1109 try {
1110 MessageDigest sha = MessageDigest.getInstance(SHA256_ALGORITHM);
1111
1112
1113 while (count < ONEMEG) {
1114 int cp = 0;
1115 int i = 0;
1116 while (i < 64) {
1117 int pim = passwordIndex % pl;
1118 int len = 64 - cp;
1119 int pr = pl - pim;
1120 if (len > pr) {
1121 len = pr;
1122 }
1123 System.arraycopy(pass, pim, passwordBuf, cp, len);
1124 i += len;
1125 cp += len;
1126 passwordIndex += len;
1127 }
1128 sha.update(passwordBuf, 0, passwordBuf.length);
1129 count += 64;
1130 }
1131
1132
1133 ret = sha.digest();
1134 } catch (NoSuchAlgorithmException e) {
1135 throw new IllegalStateException("SHA-256 not supported, failed to generate key", e);
1136 }
1137
1138 return ret;
1139 }
1140
1141
1142
1143
1144
1145
1146
1147
1148 public static byte[] passwordToKeySHA384(String userPrivacyPassword) {
1149 byte[] ret;
1150 byte[] passwordBuf = new byte[128];
1151 int pl = userPrivacyPassword.length();
1152 byte[] pass = new byte[pl];
1153
1154
1155 for (int i = 0; i < pl; i++) {
1156 pass[i] = (byte) (0xFF & userPrivacyPassword.charAt(i));
1157 }
1158
1159 int count = 0;
1160 int passwordIndex = 0;
1161
1162 try {
1163 MessageDigest sha = MessageDigest.getInstance(SHA384_ALGORITHM);
1164
1165
1166 while (count < ONEMEG) {
1167 int cp = 0;
1168 int i = 0;
1169 while (i < 128) {
1170 int pim = passwordIndex % pl;
1171 int len = 128 - cp;
1172 int pr = pl - pim;
1173 if (len > pr) {
1174 len = pr;
1175 }
1176 System.arraycopy(pass, pim, passwordBuf, cp, len);
1177 i += len;
1178 cp += len;
1179 passwordIndex += len;
1180 }
1181 sha.update(passwordBuf, 0, passwordBuf.length);
1182 count += 128;
1183 }
1184
1185
1186 ret = sha.digest();
1187 } catch (NoSuchAlgorithmException e) {
1188 throw new IllegalStateException("SHA-384 not supported, failed to generate key", e);
1189 }
1190
1191 return ret;
1192 }
1193
1194
1195
1196
1197
1198
1199
1200
1201 public static byte[] passwordToKeySHA224(String userPrivacyPassword) {
1202 byte[] ret;
1203 byte[] passwordBuf = new byte[64];
1204 int pl = userPrivacyPassword.length();
1205 byte[] pass = new byte[pl];
1206
1207
1208 for (int i = 0; i < pl; i++) {
1209 pass[i] = (byte) (0xFF & userPrivacyPassword.charAt(i));
1210 }
1211
1212 int count = 0;
1213 int passwordIndex = 0;
1214
1215 try {
1216 MessageDigest sha = MessageDigest.getInstance(SHA224_ALGORITHM);
1217
1218
1219 while (count < ONEMEG) {
1220 int cp = 0;
1221 int i = 0;
1222 while (i < 64) {
1223 int pim = passwordIndex % pl;
1224 int len = 64 - cp;
1225 int pr = pl - pim;
1226 if (len > pr) {
1227 len = pr;
1228 }
1229 System.arraycopy(pass, pim, passwordBuf, cp, len);
1230 i += len;
1231 cp += len;
1232 passwordIndex += len;
1233 }
1234 sha.update(passwordBuf, 0, passwordBuf.length);
1235 count += 64;
1236 }
1237
1238
1239 ret = sha.digest();
1240 } catch (NoSuchAlgorithmException e) {
1241 throw new IllegalStateException("SHA-224 not supported, failed to generate key", e);
1242 }
1243
1244 return ret;
1245 }
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255 public static byte[] passwordToKeySHA512(String userPrivacyPassword) {
1256 byte[] ret;
1257 byte[] passwordBuf = new byte[64];
1258 int pl = userPrivacyPassword.length();
1259 byte[] pass = new byte[pl];
1260
1261
1262 for (int i = 0; i < pl; i++) {
1263 pass[i] = (byte) (0xFF & userPrivacyPassword.charAt(i));
1264 }
1265
1266 int count = 0;
1267 int passwordIndex = 0;
1268
1269 try {
1270 MessageDigest sha = MessageDigest.getInstance(SHA512_ALGORITHM);
1271
1272
1273 while (count < 1024 * 1024) {
1274 int cp = 0;
1275 int i = 0;
1276 while (i < 64) {
1277 int pim = passwordIndex % pl;
1278 int len = 64 - cp;
1279 int pr = pl - pim;
1280 if (len > pr) {
1281 len = pr;
1282 }
1283 System.arraycopy(pass, pim, passwordBuf, cp, len);
1284 i += len;
1285 cp += len;
1286 passwordIndex += len;
1287 }
1288 sha.update(passwordBuf, 0, passwordBuf.length);
1289 count += 64;
1290 }
1291
1292
1293 ret = sha.digest();
1294 } catch (NoSuchAlgorithmException e) {
1295 throw new IllegalStateException("SHA-512 not supported, failed to generate key", e);
1296 }
1297
1298 return ret;
1299 }
1300
1301
1302
1303
1304
1305
1306
1307
1308 public static byte[] getLocalizedKeySHA256(final byte[] passwKey, final String snmpEngineId) {
1309 byte[] ret = null;
1310 byte[] beid = toBytes(snmpEngineId);
1311
1312 if (passwKey == null) {
1313 return null;
1314 }
1315
1316 try {
1317 final MessageDigest sha = MessageDigest.getInstance(SHA256_ALGORITHM);
1318 sha.update(passwKey, 0, passwKey.length);
1319 sha.update(beid, 0, beid.length);
1320 sha.update(passwKey, 0, passwKey.length);
1321 ret = sha.digest();
1322 } catch (NoSuchAlgorithmException e) {
1323 throw new IllegalStateException("SHA-256 not supported, failed to generate localized key", e);
1324 }
1325
1326 return ret;
1327 }
1328
1329
1330
1331
1332
1333
1334
1335
1336 public static byte[] getLocalizedKeySHA384(final byte[] passwKey, final String snmpEngineId) {
1337 byte[] ret = null;
1338 byte[] beid = toBytes(snmpEngineId);
1339
1340 if (passwKey == null) {
1341 return null;
1342 }
1343
1344 try {
1345 final MessageDigest sha = MessageDigest.getInstance(SHA384_ALGORITHM);
1346 sha.update(passwKey, 0, passwKey.length);
1347 sha.update(beid, 0, beid.length);
1348 sha.update(passwKey, 0, passwKey.length);
1349 ret = sha.digest();
1350 } catch (NoSuchAlgorithmException e) {
1351 throw new IllegalStateException("SHA-384 not supported, failed to generate localized key", e);
1352 }
1353
1354 return ret;
1355 }
1356
1357
1358
1359
1360
1361
1362
1363
1364 public static byte[] getLocalizedKeySHA224(final byte[] passwKey, final String snmpEngineId) {
1365 byte[] ret = null;
1366 byte[] beid = toBytes(snmpEngineId);
1367
1368 if (passwKey == null) {
1369 return null;
1370 }
1371
1372 try {
1373 final MessageDigest sha = MessageDigest.getInstance(SHA224_ALGORITHM);
1374 sha.update(passwKey, 0, passwKey.length);
1375 sha.update(beid, 0, beid.length);
1376 sha.update(passwKey, 0, passwKey.length);
1377 ret = sha.digest();
1378 } catch (NoSuchAlgorithmException e) {
1379 throw new IllegalStateException("SHA-224 not supported, failed to generate localized key", e);
1380 }
1381
1382 return ret;
1383 }
1384
1385
1386
1387
1388
1389
1390
1391
1392 public static byte[] getFingerPrintSHA256(final byte[] key, final byte[] message) {
1393 if ((AsnObject.debug > 5) && (key.length != 32)) {
1394 System.out.println("SHA256 key length wrong");
1395 }
1396 try {
1397 return doFingerPrintSHA256(key, message);
1398 } catch (NoSuchAlgorithmException e) {
1399 throw new IllegalStateException("SHA-256 not supported, failed to generate fingerprint", e);
1400 }
1401 }
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411 public static byte[] getLocalizedKeySHA512(final byte[] passwKey, final String snmpEngineId) {
1412 byte[] ret = null;
1413 byte[] beid = toBytes(snmpEngineId);
1414
1415 if (passwKey == null) {
1416 return null;
1417 }
1418
1419 try {
1420 final MessageDigest sha = MessageDigest.getInstance(SHA512_ALGORITHM);
1421 sha.update(passwKey, 0, passwKey.length);
1422 sha.update(beid, 0, beid.length);
1423 sha.update(passwKey, 0, passwKey.length);
1424 ret = sha.digest();
1425 } catch (NoSuchAlgorithmException e) {
1426 throw new IllegalStateException("SHA-512 not supported, failed to generate localized key", e);
1427 }
1428
1429 return ret;
1430 }
1431
1432
1433
1434
1435
1436
1437
1438
1439 public static byte[] getFingerPrintSHA512(final byte[] key, final byte[] message) {
1440 if ((AsnObject.debug > 5) && (key.length != 64)) {
1441 System.out.println("SHA-512 key length wrong");
1442 }
1443 try {
1444 return doFingerPrintSHA512(key, message);
1445 } catch (NoSuchAlgorithmException e) {
1446 throw new IllegalStateException("SHA-512 not supported, failed to generate fingerprint", e);
1447 }
1448 }
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458 public static byte[] getFingerPrintSHA224(final byte[] key, final byte[] message) {
1459 if ((AsnObject.debug > 5) && (key.length != 28)) {
1460 System.out.println("SHA-224 key length wrong");
1461 }
1462 try {
1463 return doFingerPrintSHA224(key, message);
1464 } catch (NoSuchAlgorithmException e) {
1465 throw new IllegalStateException("SHA-224 not supported, failed to generate fingerprint", e);
1466 }
1467 }
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478 private static byte[] doFingerPrintSHA224(final byte[] key, final byte[] message) throws NoSuchAlgorithmException {
1479
1480 byte[] k1 = new byte[64];
1481 byte[] k2 = new byte[64];
1482
1483
1484 for (int i = 0; i < 64; i++) {
1485 byte theByte = (i < key.length) ? key[i] : 0;
1486 k1[i] = (byte) ((theByte & 0xFF) ^ 0x36);
1487 k2[i] = (byte) ((theByte & 0xFF) ^ 0x5C);
1488 }
1489
1490
1491 MessageDigest digest1 = MessageDigest.getInstance(SHA224_ALGORITHM);
1492 digest1.update(k1);
1493 digest1.update(message);
1494 byte[] innerHash = digest1.digest();
1495
1496
1497 MessageDigest digest2 = MessageDigest.getInstance(SHA224_ALGORITHM);
1498 digest2.update(k2);
1499 digest2.update(innerHash);
1500 byte[] fullHmac = digest2.digest();
1501
1502
1503 byte[] ret = new byte[16];
1504 System.arraycopy(fullHmac, 0, ret, 0, 16);
1505 return ret;
1506 }
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516 private static byte[] doFingerPrintSHA256(final byte[] key, final byte[] message) throws NoSuchAlgorithmException {
1517
1518 byte[] k1 = new byte[64];
1519 byte[] k2 = new byte[64];
1520
1521
1522 for (int i = 0; i < 64; i++) {
1523 byte theByte = (i < key.length) ? key[i] : 0;
1524 k1[i] = (byte) ((theByte & 0xFF) ^ 0x36);
1525 k2[i] = (byte) ((theByte & 0xFF) ^ 0x5C);
1526 }
1527
1528
1529 MessageDigest digest1 = MessageDigest.getInstance(SHA256_ALGORITHM);
1530 digest1.update(k1);
1531 digest1.update(message);
1532 byte[] innerHash = digest1.digest();
1533
1534
1535 MessageDigest digest2 = MessageDigest.getInstance(SHA256_ALGORITHM);
1536 digest2.update(k2);
1537 digest2.update(innerHash);
1538 byte[] fullHmac = digest2.digest();
1539
1540
1541 byte[] ret = new byte[24];
1542 System.arraycopy(fullHmac, 0, ret, 0, 24);
1543 return ret;
1544 }
1545
1546
1547
1548
1549
1550
1551
1552
1553 public static byte[] getFingerPrintSHA384(final byte[] key, final byte[] message) {
1554 if ((AsnObject.debug > 5) && (key.length != 48)) {
1555 System.out.println("SHA384 key length wrong");
1556 }
1557 try {
1558 return doFingerPrintSHA384(key, message);
1559 } catch (NoSuchAlgorithmException e) {
1560 throw new IllegalStateException("SHA-384 not supported, failed to generate fingerprint", e);
1561 }
1562 }
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572 private static byte[] doFingerPrintSHA384(final byte[] key, final byte[] message) throws NoSuchAlgorithmException {
1573
1574 byte[] k1 = new byte[128];
1575 byte[] k2 = new byte[128];
1576
1577
1578 for (int i = 0; i < 128; i++) {
1579 byte theByte = (i < key.length) ? key[i] : 0;
1580 k1[i] = (byte) ((theByte & 0xFF) ^ 0x36);
1581 k2[i] = (byte) ((theByte & 0xFF) ^ 0x5C);
1582 }
1583
1584
1585 MessageDigest digest1 = MessageDigest.getInstance(SHA384_ALGORITHM);
1586 digest1.update(k1);
1587 digest1.update(message);
1588 byte[] innerHash = digest1.digest();
1589
1590
1591 MessageDigest digest2 = MessageDigest.getInstance(SHA384_ALGORITHM);
1592 digest2.update(k2);
1593 digest2.update(innerHash);
1594 byte[] fullHmac = digest2.digest();
1595
1596
1597 byte[] ret = new byte[32];
1598 System.arraycopy(fullHmac, 0, ret, 0, 32);
1599 return ret;
1600 }
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610 private static byte[] doFingerPrintSHA512(final byte[] key, final byte[] message) throws NoSuchAlgorithmException {
1611
1612 byte[] k1 = new byte[128];
1613 byte[] k2 = new byte[128];
1614
1615
1616 for (int i = 0; i < 128; i++) {
1617 byte theByte = (i < key.length) ? key[i] : 0;
1618 k1[i] = (byte) ((theByte & 0xFF) ^ 0x36);
1619 k2[i] = (byte) ((theByte & 0xFF) ^ 0x5C);
1620 }
1621
1622
1623 MessageDigest digest1 = MessageDigest.getInstance(SHA512_ALGORITHM);
1624 digest1.update(k1);
1625 digest1.update(message);
1626 byte[] innerHash = digest1.digest();
1627
1628
1629 MessageDigest digest2 = MessageDigest.getInstance(SHA512_ALGORITHM);
1630 digest2.update(k2);
1631 digest2.update(innerHash);
1632 byte[] fullHmac = digest2.digest();
1633
1634
1635 byte[] ret = new byte[48];
1636 System.arraycopy(fullHmac, 0, ret, 0, 48);
1637 return ret;
1638 }
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649 public static byte[] initFingerprint(final int authenticationProtocol) {
1650
1651 return DUMMY_FINGERPRINT_MAP.getOrDefault(authenticationProtocol, new byte[0]);
1652 }
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665 public static void copyFingerprintToSnmpMessage(
1666 int authenticationProtocol,
1667 byte[] computedFingerprint,
1668 byte[] message,
1669 int fpPos) {
1670 int lengthToCopy = 0;
1671 switch (authenticationProtocol) {
1672 case SHA256_PROTOCOL:
1673 lengthToCopy = dummySHA256FingerPrint.length;
1674 break;
1675 case SHA1_PROTOCOL:
1676 case MD5_PROTOCOL:
1677 lengthToCopy = dummySha1FingerPrint.length;
1678 break;
1679 case SHA512_PROTOCOL:
1680 lengthToCopy = dummySHA512FingerPrint.length;
1681 break;
1682 case SHA224_PROTOCOL:
1683 lengthToCopy = dummySHA224FingerPrint.length;
1684 break;
1685 case SHA384_PROTOCOL:
1686 lengthToCopy = dummySHA384FingerPrint.length;
1687 break;
1688 default:
1689
1690 break;
1691 }
1692 if (lengthToCopy > 0) {
1693 System.arraycopy(computedFingerprint, 0, message, fpPos, lengthToCopy);
1694 }
1695 }
1696 }