1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.api.asn1.util;
21
22
23 import java.io.IOException;
24 import java.io.OutputStream;
25 import java.math.BigInteger;
26 import java.util.Arrays;
27
28 import org.apache.directory.api.asn1.DecoderException;
29 import org.apache.directory.api.i18n.I18n;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 public final class Oid
76 {
77
78 private byte[] oidBytes;
79
80
81 private String oidString;
82
83 private static final BigInteger JOINT_ISO_ITU_T = new BigInteger( "80" );
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135 private enum OidFSAState
136 {
137 START,
138 STATE_A,
139 STATE_B,
140 STATE_C,
141 STATE_D,
142 STATE_E,
143 STATE_F,
144 STATE_G,
145 STATE_H,
146 STATE_I,
147 STATE_J,
148 STATE_K,
149 STATE_L,
150 STATE_M,
151 }
152
153
154
155
156
157
158
159
160 private Oid( String oidString, byte[] oidBytes )
161 {
162 this.oidString = oidString;
163 this.oidBytes = new byte[oidBytes.length];
164 System.arraycopy( oidBytes, 0, this.oidBytes, 0, oidBytes.length );
165 }
166
167
168
169
170
171 @Override
172 public boolean equals( Object other )
173 {
174 return ( other instanceof Oid )
175 && oidString.equals( ( ( Oid ) other ).oidString );
176 }
177
178
179
180
181
182
183
184
185
186 public static Oid fromBytes( byte[] oidBytes ) throws DecoderException
187 {
188 if ( ( oidBytes == null ) || ( oidBytes.length < 1 ) )
189 {
190 throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, Arrays.toString( oidBytes ) ) );
191 }
192
193 StringBuilder builder = new StringBuilder();
194 long value = 0;
195 int valStart = 0;
196 int valLength = 0;
197 boolean firstArc = true;
198
199 for ( int i = 0; i < oidBytes.length; i++ )
200 {
201 value |= oidBytes[i] & 0x7F;
202
203 if ( oidBytes[i] < 0 )
204 {
205
206 value = value << 7;
207 valLength++;
208 }
209 else
210 {
211 valLength++;
212
213 if ( valLength > 8 )
214 {
215
216
217 int nbBytes = valLength * 7 / 8;
218
219 if ( valLength % 7 != 0 )
220 {
221 nbBytes++;
222 }
223
224 byte[] result = new byte[nbBytes];
225
226
227 int pos = nbBytes - 1;
228 int valEnd = valStart + valLength - 1;
229 int j = 0;
230
231 while ( j < valLength - 8 )
232 {
233 result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 1] << 7 ) | ( oidBytes[valEnd - j] & 0x7F ) );
234 result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 2] << 6 ) | ( ( oidBytes[valEnd - j - 1] & 0x7E ) >> 1 ) );
235 result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 3] << 5 ) | ( ( oidBytes[valEnd - j - 2] & 0x7C ) >> 2 ) );
236 result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 4] << 4 ) | ( ( oidBytes[valEnd - j - 3] & 0x78 ) >> 3 ) );
237 result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 5] << 3 ) | ( ( oidBytes[valEnd - j - 4] & 0x70 ) >> 4 ) );
238 result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 6] << 2 ) | ( ( oidBytes[valEnd - j - 5] & 0x60 ) >> 5 ) );
239 result[pos--] = ( byte ) ( ( oidBytes[valEnd - j - 7] << 1 ) | ( ( oidBytes[valEnd - j - 6] & 0x40 ) >> 6 ) );
240 j += 8;
241 }
242
243 switch ( valLength - j )
244 {
245 case 7 :
246 result[pos--] = ( byte ) ( ( oidBytes[5] << 7 ) | ( oidBytes[6] & 0x7F ) );
247 result[pos--] = ( byte ) ( ( oidBytes[4] << 6 ) | ( ( oidBytes[5] & 0x7E ) >> 1 ) );
248 result[pos--] = ( byte ) ( ( oidBytes[3] << 5 ) | ( ( oidBytes[4] & 0x7C ) >> 2 ) );
249 result[pos--] = ( byte ) ( ( oidBytes[2] << 4 ) | ( ( oidBytes[3] & 0x78 ) >> 3 ) );
250 result[pos--] = ( byte ) ( ( oidBytes[1] << 3 ) | ( ( oidBytes[2] & 0x70 ) >> 4 ) );
251 result[pos--] = ( byte ) ( ( oidBytes[0] << 2 ) | ( ( oidBytes[1] & 0x60 ) >> 5 ) );
252 result[pos] = ( byte ) ( ( oidBytes[0] & 0x40 ) >> 6 );
253 break;
254
255 case 6 :
256 result[pos--] = ( byte ) ( ( oidBytes[4] << 7 ) | ( oidBytes[5] & 0x7F ) );
257 result[pos--] = ( byte ) ( ( oidBytes[3] << 6 ) | ( ( oidBytes[4] & 0x7E ) >> 1 ) );
258 result[pos--] = ( byte ) ( ( oidBytes[2] << 5 ) | ( ( oidBytes[3] & 0x7C ) >> 2 ) );
259 result[pos--] = ( byte ) ( ( oidBytes[1] << 4 ) | ( ( oidBytes[2] & 0x78 ) >> 3 ) );
260 result[pos--] = ( byte ) ( ( oidBytes[0] << 3 ) | ( ( oidBytes[1] & 0x70 ) >> 4 ) );
261 result[pos] = ( byte ) ( ( oidBytes[0] & 0x60 ) >> 5 );
262 break;
263
264 case 5 :
265 result[pos--] = ( byte ) ( ( oidBytes[3] << 7 ) | ( oidBytes[4] & 0x7F ) );
266 result[pos--] = ( byte ) ( ( oidBytes[2] << 6 ) | ( ( oidBytes[3] & 0x7E ) >> 1 ) );
267 result[pos--] = ( byte ) ( ( oidBytes[1] << 5 ) | ( ( oidBytes[2] & 0x7C ) >> 2 ) );
268 result[pos--] = ( byte ) ( ( oidBytes[0] << 4 ) | ( ( oidBytes[1] & 0x78 ) >> 3 ) );
269 result[pos] = ( byte ) ( ( oidBytes[0] & 0x70 ) >> 4 );
270 break;
271
272 case 4 :
273 result[pos--] = ( byte ) ( ( oidBytes[2] << 7 ) | ( oidBytes[3] & 0x7F ) );
274 result[pos--] = ( byte ) ( ( oidBytes[1] << 6 ) | ( ( oidBytes[2] & 0x7E ) >> 1 ) );
275 result[pos--] = ( byte ) ( ( oidBytes[0] << 5 ) | ( ( oidBytes[1] & 0x7C ) >> 2 ) );
276 result[pos] = ( byte ) ( ( oidBytes[0] & 0x78 ) >> 3 );
277 break;
278
279 case 3 :
280 result[pos--] = ( byte ) ( ( oidBytes[1] << 7 ) | ( oidBytes[2] & 0x7F ) );
281 result[pos--] = ( byte ) ( ( oidBytes[0] << 6 ) | ( ( oidBytes[1] & 0x7E ) >> 1 ) );
282 result[pos] = ( byte ) ( ( oidBytes[0] & 0x7C ) >> 2 );
283 break;
284
285 case 2 :
286 result[pos--] = ( byte ) ( ( oidBytes[0] << 7 ) | ( oidBytes[1] & 0x7F ) );
287 result[pos] = ( byte ) ( ( oidBytes[0] & 0x7E ) >> 1 );
288 break;
289
290 case 1 :
291 result[pos] = ( byte ) ( oidBytes[0] & 0x7F );
292 break;
293
294 default :
295
296 break;
297 }
298
299 BigInteger bigInteger;
300
301 if ( ( result[0] & 0x80 ) == 0x80 )
302 {
303 byte[] newResult = new byte[result.length + 1];
304 System.arraycopy( result, 0, newResult, 1, result.length );
305 result = newResult;
306 }
307
308 bigInteger = new BigInteger( result );
309
310 if ( firstArc )
311 {
312
313 bigInteger = bigInteger.subtract( JOINT_ISO_ITU_T );
314 builder.append( '2' );
315 }
316
317 builder.append( '.' ).append( bigInteger.toString() );
318 }
319 else
320 {
321
322 if ( firstArc )
323 {
324
325 if ( value >= 80 )
326 {
327
328 builder.append( '2' );
329 value = value - 80;
330 }
331 else
332 {
333
334 long one = value / 40;
335 long two = value % 40;
336
337 if ( ( one < 0 ) || ( one > 2 ) || ( two < 0 ) || ( ( one < 2 ) && ( two > 39 ) ) )
338 {
339 throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID,
340 Arrays.toString( oidBytes ) ) );
341 }
342
343 if ( one < 2 )
344 {
345 builder.append( one );
346 value = two;
347 }
348 }
349
350 firstArc = false;
351 }
352
353
354 builder.append( '.' ).append( value );
355 }
356
357 valStart = i;
358 valLength = 0;
359 value = 0;
360 }
361 }
362
363 return new Oid( builder.toString(), oidBytes );
364 }
365
366
367
368
369
370
371
372
373
374 private static OidFSAState processStateStart( String oid, byte[] buffer, int pos ) throws DecoderException
375 {
376 char c = oid.charAt( pos );
377
378 switch ( c )
379 {
380 case '0' :
381 case '1' :
382 buffer[0] = ( byte ) ( ( c - '0' ) * 40 );
383 return OidFSAState.STATE_A;
384
385 case '2' :
386 return OidFSAState.STATE_F;
387
388 default :
389
390 throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "Should start with 0, 1 or 2" ) );
391 }
392 }
393
394
395
396
397
398
399
400
401 private static OidFSAState processStateA( String oid, int pos ) throws DecoderException
402 {
403 if ( oid.charAt( pos ) != '.' )
404 {
405
406 throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a '.' is expected" ) );
407 }
408
409 return OidFSAState.STATE_B;
410 }
411
412
413
414
415
416
417
418
419
420
421 private static OidFSAState processStateB( String oid, byte[] buffer, int pos ) throws DecoderException
422 {
423 char c = oid.charAt( pos );
424
425 switch ( c )
426 {
427 case '0' :
428 return OidFSAState.STATE_D;
429
430 case '1' :
431 case '2' :
432 case '3' :
433
434 buffer[1] = ( byte ) ( c - '0' );
435
436 return OidFSAState.STATE_C;
437
438 case '4' :
439 case '5' :
440 case '6' :
441 case '7' :
442 case '8' :
443 case '9' :
444 buffer[0] += ( byte ) ( c - '0' );
445 return OidFSAState.STATE_E;
446
447 default :
448
449 throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
450 }
451 }
452
453
454
455
456
457
458
459
460
461 private static OidFSAState processStateC( String oid, byte[] buffer, int pos ) throws DecoderException
462 {
463 char c = oid.charAt( pos );
464
465 switch ( c )
466 {
467 case '0' :
468 case '1' :
469 case '2' :
470 case '3' :
471 case '4' :
472 case '5' :
473 case '6' :
474 case '7' :
475 case '8' :
476 case '9' :
477 buffer[0] += ( byte ) ( buffer[1] * 10 + ( c - '0' ) );
478 buffer[1] = 0;
479 return OidFSAState.STATE_E;
480
481 case '.' :
482 buffer[0] += buffer[1];
483 buffer[1] = 0;
484 return OidFSAState.STATE_K;
485
486 default :
487
488 throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
489 }
490 }
491
492
493
494
495
496
497
498
499
500 private static OidFSAState processStateDE( String oid, byte[] buffer, int pos ) throws DecoderException
501 {
502 char c = oid.charAt( pos );
503
504 if ( c != '.' )
505 {
506
507 throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a dot is expected" ) );
508 }
509
510
511 buffer[0] = ( byte ) ( buffer[0] | buffer[1] );
512 buffer[1] = 0;
513
514 return OidFSAState.STATE_K;
515 }
516
517
518
519
520
521
522
523
524 private static OidFSAState processStateF( String oid, int pos ) throws DecoderException
525 {
526 if ( oid.charAt( pos ) != '.' )
527 {
528
529 throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a '.' is expected" ) );
530 }
531
532 return OidFSAState.STATE_G;
533 }
534
535
536
537
538
539
540
541
542
543 private static OidFSAState processStateG( String oid, byte[] buffer, int pos ) throws DecoderException
544 {
545 char c = oid.charAt( pos );
546
547 switch ( c )
548 {
549 case '0' :
550 buffer[0] = ( byte ) 80;
551 return OidFSAState.STATE_I;
552
553 case '1' :
554 case '2' :
555 case '3' :
556 case '4' :
557 case '5' :
558 case '6' :
559 case '7' :
560 case '8' :
561 case '9' :
562
563 buffer[0] = ( byte ) ( c - '0' );
564 return OidFSAState.STATE_H;
565
566 default :
567
568 throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
569 }
570 }
571
572
573
574
575
576
577
578
579
580 private static OidFSAState processStateH( String oid, byte[] buffer, int pos ) throws DecoderException
581 {
582 char c = oid.charAt( pos );
583
584 switch ( c )
585 {
586 case '0' :
587 case '1' :
588 case '2' :
589 case '3' :
590 case '4' :
591 case '5' :
592 case '6' :
593 case '7' :
594 case '8' :
595 case '9' :
596
597 buffer[1] = ( byte ) ( c - '0' );
598 return OidFSAState.STATE_J;
599
600 case '.' :
601
602 buffer[0] = ( byte ) ( 80 + buffer[0] );
603
604 return OidFSAState.STATE_K;
605
606 default :
607
608 throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
609 }
610 }
611
612
613
614
615
616
617
618
619 private static OidFSAState processStateI( String oid, byte[] buffer, int pos ) throws DecoderException
620 {
621 char c = oid.charAt( pos );
622
623 if ( c == '.' )
624 {
625
626 buffer[0] = ( byte ) ( 80 + buffer[1] );
627
628 return OidFSAState.STATE_K;
629 }
630 else
631 {
632
633 throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
634 }
635 }
636
637
638
639
640
641
642
643
644
645 private static OidFSAState processStateJ( String oid, byte[] buffer, int bufferPos, int pos ) throws DecoderException
646 {
647 char c = oid.charAt( pos );
648
649 switch ( c )
650 {
651 case '.' :
652 return OidFSAState.STATE_K;
653
654 case '0' :
655 case '1' :
656 case '2' :
657 case '3' :
658 case '4' :
659 case '5' :
660 case '6' :
661 case '7' :
662 case '8' :
663 case '9' :
664
665 buffer[bufferPos] = ( byte ) ( c - '0' );
666 return OidFSAState.STATE_J;
667
668 default :
669
670 throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
671 }
672 }
673
674
675
676
677
678
679
680
681
682 private static OidFSAState processStateK( String oid, byte[] buffer, int bufferPos, int pos ) throws DecoderException
683 {
684 char c = oid.charAt( pos );
685
686 switch ( c )
687 {
688 case '0' :
689 buffer[bufferPos] = 0x00;
690 return OidFSAState.STATE_M;
691
692 case '1' :
693 case '2' :
694 case '3' :
695 case '4' :
696 case '5' :
697 case '6' :
698 case '7' :
699 case '8' :
700 case '9' :
701
702 return OidFSAState.STATE_L;
703
704 default :
705
706 throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
707 }
708 }
709
710
711
712
713
714
715
716
717
718 private static OidFSAState processStateL( String oid, byte[] buffer, int bufferPos, int pos ) throws DecoderException
719 {
720 char c = oid.charAt( pos );
721
722 switch ( c )
723 {
724 case '.' :
725 return OidFSAState.STATE_K;
726
727 case '0' :
728 case '1' :
729 case '2' :
730 case '3' :
731 case '4' :
732 case '5' :
733 case '6' :
734 case '7' :
735 case '8' :
736 case '9' :
737
738 buffer[bufferPos] = ( byte ) ( c - '0' );
739
740 return OidFSAState.STATE_L;
741
742 default :
743
744 throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit or a dot is expected" ) );
745 }
746 }
747
748
749
750
751
752
753
754
755 private static OidFSAState processStateM( String oid, int pos ) throws DecoderException
756 {
757 char c = oid.charAt( pos );
758
759 if ( c == '.' )
760 {
761 return OidFSAState.STATE_K;
762 }
763 else
764 {
765
766 throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a '.' is expected" ) );
767 }
768 }
769
770
771
772
773
774
775 private static int convert( String oid, byte[] buffer, int start, int nbDigits, int posBuffer, boolean isJointIsoItuT )
776 {
777 if ( nbDigits < 3 )
778 {
779
780
781 if ( isJointIsoItuT )
782 {
783
784 buffer[0] = ( byte ) ( 80 + ( oid.charAt( 2 ) - '0' ) * 10 + ( oid.charAt( 3 ) - '0' ) );
785
786 if ( buffer[0] < 0 )
787 {
788
789 buffer[1] = ( byte ) ( buffer[0] & 0x007F );
790 buffer[0] = ( byte ) 0x81;
791
792 return 2;
793 }
794 else
795 {
796 return 1;
797 }
798 }
799 else
800 {
801 if ( nbDigits == 1 )
802 {
803 buffer[posBuffer] = ( byte ) ( oid.charAt( start ) - '0' );
804 }
805 else
806 {
807 buffer[posBuffer] = ( byte ) ( ( oid.charAt( start ) - '0' ) * 10 + ( oid.charAt( start + 1 ) - '0' ) );
808
809 }
810 return 1;
811 }
812
813 }
814 else if ( nbDigits < 19 )
815 {
816
817
818 String number = oid.substring( start, start + nbDigits );
819
820 long value = Long.parseLong( number );
821
822 if ( isJointIsoItuT )
823 {
824 value += 80L;
825 }
826
827
828 if ( ( value & 0xFFFFFFFFFFFFFF80L ) == 0 )
829 {
830
831 buffer[posBuffer] = ( byte ) ( value );
832
833 return 1;
834 }
835
836 if ( ( value & 0xFFFFFFFFFFFFC000L ) == 0 )
837 {
838
839 buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
840 buffer[posBuffer + 1] = ( byte ) ( value & 0x000000000000007FL );
841
842 return 2;
843 }
844
845 if ( ( value & 0xFFFFFFFFFFE00000L ) == 0 )
846 {
847
848 buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
849 buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
850 buffer[posBuffer + 2] = ( byte ) ( value & 0x000000000000007FL );
851
852 return 3;
853 }
854
855 if ( ( value & 0xFFFFFFFFF0000000L ) == 0 )
856 {
857
858 buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
859 buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
860 buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
861 buffer[posBuffer + 3] = ( byte ) ( value & 0x000000000000007FL );
862
863 return 4;
864 }
865
866 if ( ( value & 0xFFFFFFF800000000L ) == 0 )
867 {
868
869 buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x00000007F0000000L ) >> 28 ) | 0x80 );
870 buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
871 buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
872 buffer[posBuffer + 3] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
873 buffer[posBuffer + 4] = ( byte ) ( value & 0x000000000000007FL );
874
875 return 5;
876 }
877
878 if ( ( value & 0xFFFFFC0000000000L ) == 0 )
879 {
880
881 buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x000003F800000000L ) >> 35 ) | 0x80 );
882 buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x00000007F0000000L ) >> 28 ) | 0x80 );
883 buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
884 buffer[posBuffer + 3] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
885 buffer[posBuffer + 4] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
886 buffer[posBuffer + 5] = ( byte ) ( value & 0x000000000000007FL );
887
888 return 6;
889 }
890
891 if ( ( value & 0xFFFE000000000000L ) == 0 )
892 {
893
894 buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x0001FC0000000000L ) >> 42 ) | 0x80 );
895 buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x000003F800000000L ) >> 35 ) | 0x80 );
896 buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x00000007F0000000L ) >> 28 ) | 0x80 );
897 buffer[posBuffer + 3] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
898 buffer[posBuffer + 4] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
899 buffer[posBuffer + 5] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
900 buffer[posBuffer + 6] = ( byte ) ( value & 0x000000000000007FL );
901
902 return 7;
903 }
904
905 if ( ( value & 0xFF00000000000000L ) == 0 )
906 {
907
908 buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x00FE000000000000L ) >> 49 ) | 0x80 );
909 buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x0001FC0000000000L ) >> 42 ) | 0x80 );
910 buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x000003F800000000L ) >> 35 ) | 0x80 );
911 buffer[posBuffer + 3] = ( byte ) ( ( byte ) ( ( value & 0x00000007F0000000L ) >> 28 ) | 0x80 );
912 buffer[posBuffer + 4] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
913 buffer[posBuffer + 5] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
914 buffer[posBuffer + 6] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
915 buffer[posBuffer + 7] = ( byte ) ( value & 0x000000000000007FL );
916
917 return 8;
918 }
919 else
920 {
921
922 buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x7F00000000000000L ) >> 56 ) | 0x80 );
923 buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x00FE000000000000L ) >> 49 ) | 0x80 );
924 buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x0001FC0000000000L ) >> 42 ) | 0x80 );
925 buffer[posBuffer + 3] = ( byte ) ( ( byte ) ( ( value & 0x000003F800000000L ) >> 35 ) | 0x80 );
926 buffer[posBuffer + 4] = ( byte ) ( ( byte ) ( ( value & 0x00000007F0000000L ) >> 28 ) | 0x80 );
927 buffer[posBuffer + 5] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
928 buffer[posBuffer + 6] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
929 buffer[posBuffer + 7] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
930 buffer[posBuffer + 8] = ( byte ) ( value & 0x000000000000007FL );
931
932 return 9;
933 }
934 }
935 else
936 {
937
938
939 String number = oid.substring( start, start + nbDigits );
940 BigInteger bigInteger = new BigInteger( number );
941
942 if ( isJointIsoItuT )
943 {
944 bigInteger = bigInteger.add( JOINT_ISO_ITU_T );
945 posBuffer = 0;
946 }
947
948 byte[] bytes = bigInteger.toByteArray();
949
950
951
952 int nbNeededBytes = ( bytes.length * 8 ) / 7;
953
954 switch ( ( bytes.length - 1 ) % 7 )
955 {
956 case 0 :
957 if ( ( bytes[0] & 0x0080 ) != 0 )
958 {
959 nbNeededBytes++;
960 }
961
962 break;
963
964 case 1 :
965 if ( ( bytes[0] & 0x00C0 ) != 0 )
966 {
967 nbNeededBytes++;
968 }
969
970 break;
971
972 case 2 :
973 if ( ( bytes[0] & 0x00E0 ) != 0 )
974 {
975 nbNeededBytes++;
976 }
977
978 break;
979
980 case 3 :
981 if ( ( bytes[0] & 0x00F0 ) != 0 )
982 {
983 nbNeededBytes++;
984 }
985
986 break;
987
988 case 4 :
989 if ( ( bytes[0] & 0x00F8 ) != 0 )
990 {
991 nbNeededBytes++;
992 }
993
994 break;
995
996 case 5 :
997 if ( ( bytes[0] & 0x00FC ) != 0 )
998 {
999 nbNeededBytes++;
1000 }
1001
1002 break;
1003
1004 case 6 :
1005 if ( ( bytes[0] & 0x00FE ) != 0 )
1006 {
1007 nbNeededBytes++;
1008 }
1009
1010 break;
1011
1012 default :
1013
1014 break;
1015 }
1016
1017 byte[] converted = new byte[nbNeededBytes];
1018
1019 int posConverted = nbNeededBytes - 1;
1020 int posBytes = bytes.length - 1;
1021 int counter = 0;
1022 byte reminder = 0;
1023
1024 while ( posBytes >= 0 )
1025 {
1026 byte newByte = ( byte ) ( ( bytes[posBytes] & 0x00FF ) << counter );
1027 converted[posConverted] = ( byte ) ( reminder | newByte | 0x0080 );
1028 reminder = ( byte ) ( ( bytes[posBytes] & 0x00FF ) >> ( 7 - counter ) );
1029 counter = ( counter + 1 ) % 8;
1030 posConverted--;
1031
1032 if ( counter != 0 )
1033 {
1034 posBytes--;
1035 }
1036 else
1037 {
1038 reminder = 0;
1039 }
1040 }
1041
1042 converted[nbNeededBytes - 1] &= 0x7F;
1043
1044
1045 System.arraycopy( converted, 0, buffer, posBuffer, nbNeededBytes );
1046
1047 return nbNeededBytes;
1048 }
1049 }
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059 public static Oid fromString( String oidString ) throws DecoderException
1060 {
1061 if ( ( oidString == null ) || oidString.isEmpty() )
1062 {
1063 throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "empty" ) );
1064 }
1065
1066
1067 byte[] buffer = new byte[oidString.length()];
1068
1069 OidFSAState state = OidFSAState.START;
1070
1071
1072 int arcNbChars = 0;
1073
1074
1075 int bufPos = 0;
1076
1077
1078 int startArc = 0;
1079
1080
1081 int nbBytes;
1082
1083 for ( int i = 0; i < oidString.length(); i++ )
1084 {
1085 switch ( state )
1086 {
1087 case START :
1088
1089
1090 state = processStateStart( oidString, buffer, i );
1091 break;
1092
1093 case STATE_A :
1094
1095 state = processStateA( oidString, i );
1096
1097
1098 break;
1099
1100 case STATE_B :
1101
1102
1103
1104 state = processStateB( oidString, buffer, i );
1105
1106 break;
1107
1108 case STATE_C :
1109
1110
1111 state = processStateC( oidString, buffer, i );
1112
1113
1114 bufPos = 1;
1115
1116 break;
1117
1118 case STATE_D :
1119
1120
1121
1122 case STATE_E :
1123
1124 state = processStateDE( oidString, buffer, i );
1125
1126
1127 bufPos = 1;
1128
1129 break;
1130
1131 case STATE_F :
1132
1133 state = processStateF( oidString, i );
1134
1135 break;
1136
1137 case STATE_G :
1138
1139
1140 state = processStateG( oidString, buffer, i );
1141 arcNbChars = 1;
1142 startArc = i;
1143
1144 break;
1145
1146 case STATE_H :
1147
1148
1149 state = processStateH( oidString, buffer, i );
1150
1151 if ( state == OidFSAState.STATE_J )
1152 {
1153
1154 arcNbChars = 2;
1155 bufPos = 0;
1156 }
1157
1158 break;
1159
1160 case STATE_I :
1161
1162 state = processStateI( oidString, buffer, i );
1163
1164
1165 bufPos = 1;
1166
1167 break;
1168
1169 case STATE_J :
1170
1171
1172 state = processStateJ( oidString, buffer, arcNbChars + bufPos, i );
1173
1174 if ( state == OidFSAState.STATE_J )
1175 {
1176
1177 arcNbChars++;
1178 }
1179 else
1180 {
1181
1182 bufPos += convert( oidString, buffer, bufPos, arcNbChars, 0, true );
1183 }
1184
1185 break;
1186
1187 case STATE_K :
1188 startArc = i;
1189 state = processStateK( oidString, buffer, bufPos, i );
1190
1191 if ( state == OidFSAState.STATE_M )
1192 {
1193 bufPos++;
1194 }
1195 else
1196 {
1197 arcNbChars = 1;
1198 }
1199
1200 break;
1201
1202 case STATE_L :
1203 state = processStateL( oidString, buffer, arcNbChars + bufPos, i );
1204
1205 if ( state == OidFSAState.STATE_L )
1206 {
1207 arcNbChars++;
1208 break;
1209 }
1210 else
1211 {
1212
1213 bufPos += convert( oidString, buffer, startArc, arcNbChars, bufPos, false );
1214 }
1215
1216 break;
1217
1218 case STATE_M :
1219 state = processStateM( oidString, i );
1220 break;
1221
1222 default :
1223
1224 break;
1225 }
1226 }
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238 switch ( state )
1239 {
1240 case STATE_C :
1241
1242
1243
1244 case STATE_D :
1245
1246
1247
1248 case STATE_E :
1249
1250
1251
1252 case STATE_H :
1253
1254
1255
1256 case STATE_I :
1257
1258 byte[] bytes = new byte[1];
1259 bytes[0] = ( byte ) ( buffer[0] | buffer[1] );
1260
1261 return new Oid( oidString, bytes );
1262
1263 case STATE_J :
1264
1265 nbBytes = convert( oidString, buffer, 2, arcNbChars, 0, true );
1266 bytes = new byte[nbBytes];
1267 System.arraycopy( buffer, 0, bytes, 0, nbBytes );
1268
1269 return new Oid( oidString, bytes );
1270
1271 case STATE_L :
1272 bufPos += convert( oidString, buffer, startArc, arcNbChars, bufPos, false );
1273 bytes = new byte[bufPos];
1274 System.arraycopy( buffer, 0, bytes, 0, bufPos );
1275
1276 return new Oid( oidString, bytes );
1277
1278 case STATE_M :
1279 bytes = new byte[bufPos];
1280 System.arraycopy( buffer, 0, bytes, 0, bufPos );
1281
1282 return new Oid( oidString, bytes );
1283
1284 default :
1285
1286 throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "Wrong OID" ) );
1287 }
1288 }
1289
1290
1291
1292
1293
1294
1295
1296 public int getEncodedLength()
1297 {
1298 return oidBytes.length;
1299 }
1300
1301
1302
1303
1304
1305 @Override
1306 public int hashCode()
1307 {
1308 return oidString.hashCode();
1309 }
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322 public static boolean isOid( String oidString )
1323 {
1324 try
1325 {
1326 Oid.fromString( oidString );
1327
1328 return true;
1329 }
1330 catch ( DecoderException e )
1331 {
1332 return false;
1333 }
1334 }
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347 public byte[] toBytes()
1348 {
1349 return Arrays.copyOf( oidBytes, oidBytes.length );
1350 }
1351
1352
1353
1354
1355
1356
1357
1358 @Override
1359 public String toString()
1360 {
1361 return oidString;
1362 }
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372 public void writeBytesTo( java.nio.ByteBuffer buffer )
1373 {
1374 buffer.put( oidBytes );
1375 }
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386 public void writeBytesTo( OutputStream outputStream ) throws IOException
1387 {
1388 outputStream.write( oidBytes );
1389 }
1390 }