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