001/* 002 * Copyright 2007-2018 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2008-2018 Ping Identity Corporation 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021package com.unboundid.asn1; 022 023 024 025import java.io.InputStream; 026import java.io.IOException; 027import java.io.OutputStream; 028import java.io.Serializable; 029import java.util.Arrays; 030 031import com.unboundid.util.ByteStringBuffer; 032import com.unboundid.util.NotExtensible; 033import com.unboundid.util.NotMutable; 034import com.unboundid.util.ThreadSafety; 035import com.unboundid.util.ThreadSafetyLevel; 036 037import static com.unboundid.asn1.ASN1Constants.*; 038import static com.unboundid.asn1.ASN1Messages.*; 039import static com.unboundid.util.Debug.*; 040import static com.unboundid.util.StaticUtils.*; 041 042 043 044/** 045 * This class defines a generic ASN.1 BER element, which has a type and value. 046 * It provides a framework for encoding and decoding BER elements, both as 047 * generic elements and more specific subtypes. 048 */ 049@NotExtensible() 050@NotMutable() 051@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 052public class ASN1Element 053 implements Serializable 054{ 055 /** 056 * The serial version UID for this serializable class. 057 */ 058 private static final long serialVersionUID = -1871166128693521335L; 059 060 061 062 // The BER type for this element. 063 private final byte type; 064 065 // The encoded value for this element. 066 private final byte[] value; 067 068 // The cached hashCode for this element. 069 private int hashCode = -1; 070 071 // The number of bytes contained in the value. 072 private final int valueLength; 073 074 // The offset within the value array at which the value begins. 075 private final int valueOffset; 076 077 078 079 /** 080 * Creates a new ASN.1 BER element with the specified type and no value. 081 * 082 * @param type The BER type for this element. 083 */ 084 public ASN1Element(final byte type) 085 { 086 this.type = type; 087 value = NO_VALUE; 088 valueOffset = 0; 089 valueLength = 0; 090 } 091 092 093 094 /** 095 * Creates a new ASN1 BER element with the specified type and value. 096 * 097 * @param type The BER type for this element. 098 * @param value The encoded value for this element. 099 */ 100 public ASN1Element(final byte type, final byte[] value) 101 { 102 this.type = type; 103 104 if (value == null) 105 { 106 this.value = NO_VALUE; 107 } 108 else 109 { 110 this.value = value; 111 } 112 113 valueOffset = 0; 114 valueLength = this.value.length; 115 } 116 117 118 119 /** 120 * Creates a new ASN1 BER element with the specified type and value. 121 * 122 * @param type The BER type for this element. 123 * @param value The array containing the encoded value for this element. 124 * It must not be {@code null}. 125 * @param offset The offset within the array at which the value begins. 126 * @param length The number of bytes contained in the value. 127 */ 128 public ASN1Element(final byte type, final byte[] value, final int offset, 129 final int length) 130 { 131 this.type = type; 132 this.value = value; 133 134 valueOffset = offset; 135 valueLength = length; 136 } 137 138 139 140 /** 141 * Retrieves the BER type for this element. 142 * 143 * @return The BER type for this element. 144 */ 145 public final byte getType() 146 { 147 return type; 148 } 149 150 151 152 /** 153 * Retrieves a value that corresponds to the type class for this element. The 154 * value returned will be one of 155 * {@link ASN1Constants#TYPE_MASK_UNIVERSAL_CLASS}, 156 * {@link ASN1Constants#TYPE_MASK_APPLICATION_CLASS}, 157 * {@link ASN1Constants#TYPE_MASK_CONTEXT_SPECIFIC_CLASS}, or 158 * {@link ASN1Constants#TYPE_MASK_PRIVATE_CLASS}. 159 * 160 * @return A value that corresponds to the type class for this element. 161 */ 162 public byte getTypeClass() 163 { 164 return (byte) (type & 0xC0); 165 } 166 167 168 169 /** 170 * Indicates whether the type indicates that this element is constructed. A 171 * constructed element is one whose value is comprised of the encoded 172 * representation of zero or more ASN.1 elements. If the type does not 173 * indicate that the element is constructed, then the element is considered 174 * primitive. 175 * 176 * @return {@code true} if the type indicates that the element is 177 * constructed, or {@code false} if the type indicates that the 178 * element is primitive. 179 */ 180 public boolean isConstructed() 181 { 182 return ((type & ASN1Constants.TYPE_MASK_PC_CONSTRUCTED) != 0x00); 183 } 184 185 186 187 /** 188 * Retrieves the array containing the value. The returned array may be 189 * larger than the actual value, so it must be used in conjunction with the 190 * values returned by the {@link #getValueOffset} and {@link #getValueLength} 191 * methods. 192 * 193 * @return The array containing the value. 194 */ 195 byte[] getValueArray() 196 { 197 return value; 198 } 199 200 201 202 /** 203 * Retrieves the position in the value array at which the value actually 204 * begins. 205 * 206 * @return The position in the value array at which the value actually 207 * begins. 208 */ 209 int getValueOffset() 210 { 211 return valueOffset; 212 } 213 214 215 216 /** 217 * Retrieves the number of bytes contained in the value. 218 * 219 * @return The number of bytes contained in the value. 220 */ 221 public int getValueLength() 222 { 223 return valueLength; 224 } 225 226 227 228 /** 229 * Retrieves the encoded value for this element. 230 * 231 * @return The encoded value for this element. 232 */ 233 public byte[] getValue() 234 { 235 if ((valueOffset == 0) && (valueLength == value.length)) 236 { 237 return value; 238 } 239 else 240 { 241 final byte[] returnValue = new byte[valueLength]; 242 System.arraycopy(value, valueOffset, returnValue, 0, valueLength); 243 return returnValue; 244 } 245 } 246 247 248 249 /** 250 * Encodes this ASN.1 element to a byte array. 251 * 252 * @return A byte array containing the encoded representation of this ASN.1 253 * element. 254 */ 255 public final byte[] encode() 256 { 257 final byte[] valueArray = getValueArray(); 258 final int length = getValueLength(); 259 final int offset = getValueOffset(); 260 261 if (length == 0) 262 { 263 return new byte[] { type, 0x00 }; 264 } 265 266 final byte[] lengthBytes = encodeLength(length); 267 final byte[] elementBytes = new byte[1 + lengthBytes.length + length]; 268 269 elementBytes[0] = type; 270 System.arraycopy(lengthBytes, 0, elementBytes, 1, lengthBytes.length); 271 System.arraycopy(valueArray, offset, elementBytes, 1+lengthBytes.length, 272 length); 273 274 return elementBytes; 275 } 276 277 278 279 /** 280 * Encodes the provided length to the given buffer. 281 * 282 * @param length The length to be encoded. 283 * @param buffer The buffer to which the length should be appended. 284 */ 285 static void encodeLengthTo(final int length, final ByteStringBuffer buffer) 286 { 287 if ((length & 0x7F) == length) 288 { 289 buffer.append((byte) length); 290 } 291 else if ((length & 0xFF) == length) 292 { 293 buffer.append((byte) 0x81); 294 buffer.append((byte) (length & 0xFF)); 295 } 296 else if ((length & 0xFFFF) == length) 297 { 298 buffer.append((byte) 0x82); 299 buffer.append((byte) ((length >> 8) & 0xFF)); 300 buffer.append((byte) (length & 0xFF)); 301 } 302 else if ((length & 0xFFFFFF) == length) 303 { 304 buffer.append((byte) 0x83); 305 buffer.append((byte) ((length >> 16) & 0xFF)); 306 buffer.append((byte) ((length >> 8) & 0xFF)); 307 buffer.append((byte) (length & 0xFF)); 308 } 309 else 310 { 311 buffer.append((byte) 0x84); 312 buffer.append((byte) ((length >> 24) & 0xFF)); 313 buffer.append((byte) ((length >> 16) & 0xFF)); 314 buffer.append((byte) ((length >> 8) & 0xFF)); 315 buffer.append((byte) (length & 0xFF)); 316 } 317 } 318 319 320 321 /** 322 * Appends an encoded representation of this ASN.1 element to the provided 323 * buffer. 324 * 325 * @param buffer The buffer to which the encoded representation should be 326 * appended. 327 */ 328 public void encodeTo(final ByteStringBuffer buffer) 329 { 330 final byte[] valueArray = getValueArray(); 331 final int length = getValueLength(); 332 final int offset = getValueOffset(); 333 334 buffer.append(type); 335 if (length == 0) 336 { 337 buffer.append((byte) 0x00); 338 } 339 else 340 { 341 encodeLengthTo(length, buffer); 342 buffer.append(valueArray, offset, length); 343 } 344 } 345 346 347 348 /** 349 * Encodes the provided length to a byte array. 350 * 351 * @param length The length to be encoded. 352 * 353 * @return A byte array containing the encoded length. 354 */ 355 public static byte[] encodeLength(final int length) 356 { 357 switch (length) 358 { 359 case 0: return LENGTH_0; 360 case 1: return LENGTH_1; 361 case 2: return LENGTH_2; 362 case 3: return LENGTH_3; 363 case 4: return LENGTH_4; 364 case 5: return LENGTH_5; 365 case 6: return LENGTH_6; 366 case 7: return LENGTH_7; 367 case 8: return LENGTH_8; 368 case 9: return LENGTH_9; 369 case 10: return LENGTH_10; 370 case 11: return LENGTH_11; 371 case 12: return LENGTH_12; 372 case 13: return LENGTH_13; 373 case 14: return LENGTH_14; 374 case 15: return LENGTH_15; 375 case 16: return LENGTH_16; 376 case 17: return LENGTH_17; 377 case 18: return LENGTH_18; 378 case 19: return LENGTH_19; 379 case 20: return LENGTH_20; 380 case 21: return LENGTH_21; 381 case 22: return LENGTH_22; 382 case 23: return LENGTH_23; 383 case 24: return LENGTH_24; 384 case 25: return LENGTH_25; 385 case 26: return LENGTH_26; 386 case 27: return LENGTH_27; 387 case 28: return LENGTH_28; 388 case 29: return LENGTH_29; 389 case 30: return LENGTH_30; 390 case 31: return LENGTH_31; 391 case 32: return LENGTH_32; 392 case 33: return LENGTH_33; 393 case 34: return LENGTH_34; 394 case 35: return LENGTH_35; 395 case 36: return LENGTH_36; 396 case 37: return LENGTH_37; 397 case 38: return LENGTH_38; 398 case 39: return LENGTH_39; 399 case 40: return LENGTH_40; 400 case 41: return LENGTH_41; 401 case 42: return LENGTH_42; 402 case 43: return LENGTH_43; 403 case 44: return LENGTH_44; 404 case 45: return LENGTH_45; 405 case 46: return LENGTH_46; 406 case 47: return LENGTH_47; 407 case 48: return LENGTH_48; 408 case 49: return LENGTH_49; 409 case 50: return LENGTH_50; 410 case 51: return LENGTH_51; 411 case 52: return LENGTH_52; 412 case 53: return LENGTH_53; 413 case 54: return LENGTH_54; 414 case 55: return LENGTH_55; 415 case 56: return LENGTH_56; 416 case 57: return LENGTH_57; 417 case 58: return LENGTH_58; 418 case 59: return LENGTH_59; 419 case 60: return LENGTH_60; 420 case 61: return LENGTH_61; 421 case 62: return LENGTH_62; 422 case 63: return LENGTH_63; 423 case 64: return LENGTH_64; 424 case 65: return LENGTH_65; 425 case 66: return LENGTH_66; 426 case 67: return LENGTH_67; 427 case 68: return LENGTH_68; 428 case 69: return LENGTH_69; 429 case 70: return LENGTH_70; 430 case 71: return LENGTH_71; 431 case 72: return LENGTH_72; 432 case 73: return LENGTH_73; 433 case 74: return LENGTH_74; 434 case 75: return LENGTH_75; 435 case 76: return LENGTH_76; 436 case 77: return LENGTH_77; 437 case 78: return LENGTH_78; 438 case 79: return LENGTH_79; 439 case 80: return LENGTH_80; 440 case 81: return LENGTH_81; 441 case 82: return LENGTH_82; 442 case 83: return LENGTH_83; 443 case 84: return LENGTH_84; 444 case 85: return LENGTH_85; 445 case 86: return LENGTH_86; 446 case 87: return LENGTH_87; 447 case 88: return LENGTH_88; 448 case 89: return LENGTH_89; 449 case 90: return LENGTH_90; 450 case 91: return LENGTH_91; 451 case 92: return LENGTH_92; 452 case 93: return LENGTH_93; 453 case 94: return LENGTH_94; 454 case 95: return LENGTH_95; 455 case 96: return LENGTH_96; 456 case 97: return LENGTH_97; 457 case 98: return LENGTH_98; 458 case 99: return LENGTH_99; 459 case 100: return LENGTH_100; 460 case 101: return LENGTH_101; 461 case 102: return LENGTH_102; 462 case 103: return LENGTH_103; 463 case 104: return LENGTH_104; 464 case 105: return LENGTH_105; 465 case 106: return LENGTH_106; 466 case 107: return LENGTH_107; 467 case 108: return LENGTH_108; 468 case 109: return LENGTH_109; 469 case 110: return LENGTH_110; 470 case 111: return LENGTH_111; 471 case 112: return LENGTH_112; 472 case 113: return LENGTH_113; 473 case 114: return LENGTH_114; 474 case 115: return LENGTH_115; 475 case 116: return LENGTH_116; 476 case 117: return LENGTH_117; 477 case 118: return LENGTH_118; 478 case 119: return LENGTH_119; 479 case 120: return LENGTH_120; 480 case 121: return LENGTH_121; 481 case 122: return LENGTH_122; 482 case 123: return LENGTH_123; 483 case 124: return LENGTH_124; 484 case 125: return LENGTH_125; 485 case 126: return LENGTH_126; 486 case 127: return LENGTH_127; 487 } 488 489 if ((length & 0x000000FF) == length) 490 { 491 return new byte[] 492 { 493 (byte) 0x81, 494 (byte) (length & 0xFF) 495 }; 496 } 497 else if ((length & 0x0000FFFF) == length) 498 { 499 return new byte[] 500 { 501 (byte) 0x82, 502 (byte) ((length >> 8) & 0xFF), 503 (byte) (length & 0xFF) 504 }; 505 } 506 else if ((length & 0x00FFFFFF) == length) 507 { 508 return new byte[] 509 { 510 (byte) 0x83, 511 (byte) ((length >> 16) & 0xFF), 512 (byte) ((length >> 8) & 0xFF), 513 (byte) (length & 0xFF) 514 }; 515 } 516 else 517 { 518 return new byte[] 519 { 520 (byte) 0x84, 521 (byte) ((length >> 24) & 0xFF), 522 (byte) ((length >> 16) & 0xFF), 523 (byte) ((length >> 8) & 0xFF), 524 (byte) (length & 0xFF) 525 }; 526 } 527 } 528 529 530 531 /** 532 * Decodes the content in the provided byte array as an ASN.1 element. 533 * 534 * @param elementBytes The byte array containing the data to decode. 535 * 536 * @return The decoded ASN.1 BER element. 537 * 538 * @throws ASN1Exception If the provided byte array does not represent a 539 * valid ASN.1 element. 540 */ 541 public static ASN1Element decode(final byte[] elementBytes) 542 throws ASN1Exception 543 { 544 try 545 { 546 int valueStartPos = 2; 547 int length = (elementBytes[1] & 0x7F); 548 if (length != elementBytes[1]) 549 { 550 final int numLengthBytes = length; 551 552 length = 0; 553 for (int i=0; i < numLengthBytes; i++) 554 { 555 length <<= 8; 556 length |= (elementBytes[valueStartPos++] & 0xFF); 557 } 558 } 559 560 if ((elementBytes.length - valueStartPos) != length) 561 { 562 throw new ASN1Exception(ERR_ELEMENT_LENGTH_MISMATCH.get(length, 563 (elementBytes.length - valueStartPos))); 564 } 565 566 final byte[] value = new byte[length]; 567 System.arraycopy(elementBytes, valueStartPos, value, 0, length); 568 return new ASN1Element(elementBytes[0], value); 569 } 570 catch (final ASN1Exception ae) 571 { 572 debugException(ae); 573 throw ae; 574 } 575 catch (final Exception e) 576 { 577 debugException(e); 578 throw new ASN1Exception(ERR_ELEMENT_DECODE_EXCEPTION.get(e), e); 579 } 580 } 581 582 583 584 /** 585 * Decodes this ASN.1 element as a bit string element. 586 * 587 * @return The decoded bit string element. 588 * 589 * @throws ASN1Exception If this element cannot be decoded as a bit string 590 * element. 591 */ 592 public final ASN1BitString decodeAsBitString() 593 throws ASN1Exception 594 { 595 return ASN1BitString.decodeAsBitString(this); 596 } 597 598 599 600 /** 601 * Decodes this ASN.1 element as a Boolean element. 602 * 603 * @return The decoded Boolean element. 604 * 605 * @throws ASN1Exception If this element cannot be decoded as a Boolean 606 * element. 607 */ 608 public final ASN1Boolean decodeAsBoolean() 609 throws ASN1Exception 610 { 611 return ASN1Boolean.decodeAsBoolean(this); 612 } 613 614 615 616 /** 617 * Decodes this ASN.1 element as an enumerated element. 618 * 619 * @return The decoded enumerated element. 620 * 621 * @throws ASN1Exception If this element cannot be decoded as an enumerated 622 * element. 623 */ 624 public final ASN1Enumerated decodeAsEnumerated() 625 throws ASN1Exception 626 { 627 return ASN1Enumerated.decodeAsEnumerated(this); 628 } 629 630 631 632 /** 633 * Decodes this ASN.1 element as a generalized time element. 634 * 635 * @return The decoded generalized time element. 636 * 637 * @throws ASN1Exception If this element cannot be decoded as a generalized 638 * time element. 639 */ 640 public final ASN1GeneralizedTime decodeAsGeneralizedTime() 641 throws ASN1Exception 642 { 643 return ASN1GeneralizedTime.decodeAsGeneralizedTime(this); 644 } 645 646 647 648 /** 649 * Decodes this ASN.1 element as an IA5 string element. 650 * 651 * @return The decoded IA5 string element. 652 * 653 * @throws ASN1Exception If this element cannot be decoded as a IA5 string 654 * element. 655 */ 656 public final ASN1IA5String decodeAsIA5String() 657 throws ASN1Exception 658 { 659 return ASN1IA5String.decodeAsIA5String(this); 660 } 661 662 663 664 /** 665 * Decodes this ASN.1 element as an integer element. 666 * 667 * @return The decoded integer element. 668 * 669 * @throws ASN1Exception If this element cannot be decoded as an integer 670 * element. 671 */ 672 public final ASN1Integer decodeAsInteger() 673 throws ASN1Exception 674 { 675 return ASN1Integer.decodeAsInteger(this); 676 } 677 678 679 680 /** 681 * Decodes this ASN.1 element as a long element. 682 * 683 * @return The decoded long element. 684 * 685 * @throws ASN1Exception If this element cannot be decoded as a long 686 * element. 687 */ 688 public final ASN1Long decodeAsLong() 689 throws ASN1Exception 690 { 691 return ASN1Long.decodeAsLong(this); 692 } 693 694 695 696 /** 697 * Decodes this ASN.1 element as a big integer element. 698 * 699 * @return The decoded big integer element. 700 * 701 * @throws ASN1Exception If this element cannot be decoded as a big integer 702 * element. 703 */ 704 public final ASN1BigInteger decodeAsBigInteger() 705 throws ASN1Exception 706 { 707 return ASN1BigInteger.decodeAsBigInteger(this); 708 } 709 710 711 712 /** 713 * Decodes this ASN.1 element as a null element. 714 * 715 * @return The decoded null element. 716 * 717 * @throws ASN1Exception If this element cannot be decoded as a null 718 * element. 719 */ 720 public final ASN1Null decodeAsNull() 721 throws ASN1Exception 722 { 723 return ASN1Null.decodeAsNull(this); 724 } 725 726 727 728 /** 729 * Decodes this ASN.1 element as a numeric string element. 730 * 731 * @return The decoded numeric string element. 732 * 733 * @throws ASN1Exception If this element cannot be decoded as a numeric 734 * string element. 735 */ 736 public final ASN1NumericString decodeAsNumericString() 737 throws ASN1Exception 738 { 739 return ASN1NumericString.decodeAsNumericString(this); 740 } 741 742 743 744 /** 745 * Decodes this ASN.1 element as an object identifier element. 746 * 747 * @return The decoded object identifier element. 748 * 749 * @throws ASN1Exception If this element cannot be decoded as an object 750 * identifier element. 751 */ 752 public final ASN1ObjectIdentifier decodeAsObjectIdentifier() 753 throws ASN1Exception 754 { 755 return ASN1ObjectIdentifier.decodeAsObjectIdentifier(this); 756 } 757 758 759 760 /** 761 * Decodes this ASN.1 element as an octet string element. 762 * 763 * @return The decoded octet string element. 764 */ 765 public final ASN1OctetString decodeAsOctetString() 766 { 767 return ASN1OctetString.decodeAsOctetString(this); 768 } 769 770 771 772 /** 773 * Decodes this ASN.1 element as a printable string element. 774 * 775 * @return The decoded printable string element. 776 * 777 * @throws ASN1Exception If this element cannot be decoded as a printable 778 * string element. 779 */ 780 public final ASN1PrintableString decodeAsPrintableString() 781 throws ASN1Exception 782 { 783 return ASN1PrintableString.decodeAsPrintableString(this); 784 } 785 786 787 788 /** 789 * Decodes this ASN.1 element as a sequence element. 790 * 791 * @return The decoded sequence element. 792 * 793 * @throws ASN1Exception If this element cannot be decoded as a sequence 794 * element. 795 */ 796 public final ASN1Sequence decodeAsSequence() 797 throws ASN1Exception 798 { 799 return ASN1Sequence.decodeAsSequence(this); 800 } 801 802 803 804 /** 805 * Decodes this ASN.1 element as a set element. 806 * 807 * @return The decoded set element. 808 * 809 * @throws ASN1Exception If this element cannot be decoded as a set 810 * element. 811 */ 812 public final ASN1Set decodeAsSet() 813 throws ASN1Exception 814 { 815 return ASN1Set.decodeAsSet(this); 816 } 817 818 819 820 /** 821 * Decodes this ASN.1 element as a UTC time element. 822 * 823 * @return The decoded UTC time element. 824 * 825 * @throws ASN1Exception If this element cannot be decoded as a UTC time 826 * element. 827 */ 828 public final ASN1UTCTime decodeAsUTCTime() 829 throws ASN1Exception 830 { 831 return ASN1UTCTime.decodeAsUTCTime(this); 832 } 833 834 835 836 /** 837 * Decodes this ASN.1 element as a UTF-8 string element. 838 * 839 * @return The decoded UTF_8 string element. 840 * 841 * @throws ASN1Exception If this element cannot be decoded as a UTF-8 842 * string element. 843 */ 844 public final ASN1UTF8String decodeAsUTF8String() 845 throws ASN1Exception 846 { 847 return ASN1UTF8String.decodeAsUTF8String(this); 848 } 849 850 851 852 /** 853 * Reads an ASN.1 element from the provided input stream. 854 * 855 * @param inputStream The input stream from which to read the element. 856 * 857 * @return The element read from the input stream, or {@code null} if the end 858 * of the input stream is reached without reading any data. 859 * 860 * @throws IOException If a problem occurs while attempting to read from the 861 * input stream. 862 * 863 * @throws ASN1Exception If a problem occurs while attempting to decode the 864 * element. 865 */ 866 public static ASN1Element readFrom(final InputStream inputStream) 867 throws IOException, ASN1Exception 868 { 869 return readFrom(inputStream, -1); 870 } 871 872 873 874 /** 875 * Reads an ASN.1 element from the provided input stream. 876 * 877 * @param inputStream The input stream from which to read the element. 878 * @param maxSize The maximum value size in bytes that will be allowed. 879 * A value less than or equal to zero indicates that no 880 * maximum size should be enforced. An attempt to read 881 * an element with a value larger than this will cause an 882 * {@code ASN1Exception} to be thrown. 883 * 884 * @return The element read from the input stream, or {@code null} if the end 885 * of the input stream is reached without reading any data. 886 * 887 * @throws IOException If a problem occurs while attempting to read from the 888 * input stream. 889 * 890 * @throws ASN1Exception If a problem occurs while attempting to decode the 891 * element. 892 */ 893 public static ASN1Element readFrom(final InputStream inputStream, 894 final int maxSize) 895 throws IOException, ASN1Exception 896 { 897 final int typeInt = inputStream.read(); 898 if (typeInt < 0) 899 { 900 return null; 901 } 902 903 final byte type = (byte) typeInt; 904 905 int length = inputStream.read(); 906 if (length < 0) 907 { 908 throw new ASN1Exception(ERR_READ_END_BEFORE_FIRST_LENGTH.get()); 909 } 910 else if (length > 127) 911 { 912 final int numLengthBytes = length & 0x7F; 913 length = 0; 914 if ((numLengthBytes < 1) || (numLengthBytes > 4)) 915 { 916 throw new ASN1Exception(ERR_READ_LENGTH_TOO_LONG.get(numLengthBytes)); 917 } 918 919 for (int i=0; i < numLengthBytes; i++) 920 { 921 final int lengthInt = inputStream.read(); 922 if (lengthInt < 0) 923 { 924 throw new ASN1Exception(ERR_READ_END_BEFORE_LENGTH_END.get()); 925 } 926 927 length <<= 8; 928 length |= (lengthInt & 0xFF); 929 } 930 } 931 932 if ((length < 0) || ((maxSize > 0) && (length > maxSize))) 933 { 934 throw new ASN1Exception(ERR_READ_LENGTH_EXCEEDS_MAX.get(length, maxSize)); 935 } 936 937 int totalBytesRead = 0; 938 int bytesRemaining = length; 939 final byte[] value = new byte[length]; 940 while (totalBytesRead < length) 941 { 942 final int bytesRead = 943 inputStream.read(value, totalBytesRead, bytesRemaining); 944 if (bytesRead < 0) 945 { 946 throw new ASN1Exception(ERR_READ_END_BEFORE_VALUE_END.get()); 947 } 948 949 totalBytesRead += bytesRead; 950 bytesRemaining -= bytesRead; 951 } 952 953 final ASN1Element e = new ASN1Element(type, value); 954 debugASN1Read(e); 955 return e; 956 } 957 958 959 960 /** 961 * Writes an encoded representation of this ASN.1 element to the provided 962 * output stream. 963 * 964 * @param outputStream The output stream to which the element should be 965 * written. 966 * 967 * @return The total number of bytes written to the output stream. 968 * 969 * @throws IOException If a problem occurs while attempting to write to the 970 * provided output stream. 971 * 972 * @see ASN1Writer#writeElement(ASN1Element,OutputStream) 973 */ 974 public final int writeTo(final OutputStream outputStream) 975 throws IOException 976 { 977 debugASN1Write(this); 978 979 final ByteStringBuffer buffer = new ByteStringBuffer(); 980 encodeTo(buffer); 981 buffer.write(outputStream); 982 return buffer.length(); 983 } 984 985 986 987 /** 988 * Retrieves a hash code for this ASN.1 BER element. 989 * 990 * @return A hash code for this ASN.1 BER element. 991 */ 992 @Override() 993 public final int hashCode() 994 { 995 if (hashCode == -1) 996 { 997 int hash = 0; 998 for (final byte b : getValue()) 999 { 1000 hash = hash * 31 + b; 1001 } 1002 hashCode = hash; 1003 } 1004 1005 return hashCode; 1006 } 1007 1008 1009 1010 /** 1011 * Indicates whether the provided object is equal to this ASN.1 BER element. 1012 * The object will only be considered equal to this ASN.1 element if it is a 1013 * non-null ASN.1 element with the same type and value as this element. 1014 * 1015 * @param o The object for which to make the determination. 1016 * 1017 * @return {@code true} if the provided object is considered equal to this 1018 * ASN.1 element, or {@code false} if not. 1019 */ 1020 @Override() 1021 public final boolean equals(final Object o) 1022 { 1023 if (o == null) 1024 { 1025 return false; 1026 } 1027 1028 if (o == this) 1029 { 1030 return true; 1031 } 1032 1033 try 1034 { 1035 final ASN1Element e = (ASN1Element) o; 1036 return ((type == e.getType()) && Arrays.equals(getValue(), e.getValue())); 1037 } 1038 catch (final Exception e) 1039 { 1040 debugException(e); 1041 return false; 1042 } 1043 } 1044 1045 1046 1047 /** 1048 * Indicates whether the provided ASN.1 element is equal to this element, 1049 * ignoring any potential difference in the BER type. 1050 * 1051 * @param element The ASN.1 BER element for which to make the determination. 1052 * 1053 * @return {@code true} if the provided ASN.1 element is considered equal to 1054 * this element (ignoring type differences), or {@code false} if not. 1055 */ 1056 public final boolean equalsIgnoreType(final ASN1Element element) 1057 { 1058 if (element == null) 1059 { 1060 return false; 1061 } 1062 1063 if (element == this) 1064 { 1065 return true; 1066 } 1067 1068 return Arrays.equals(getValue(), element.getValue()); 1069 } 1070 1071 1072 1073 /** 1074 * Retrieves a string representation of the value for ASN.1 element. 1075 * 1076 * @return A string representation of the value for this ASN.1 element. 1077 */ 1078 @Override() 1079 public final String toString() 1080 { 1081 final StringBuilder buffer = new StringBuilder(); 1082 toString(buffer); 1083 return buffer.toString(); 1084 } 1085 1086 1087 1088 /** 1089 * Appends a string representation of the value for this ASN.1 element to the 1090 * provided buffer. 1091 * 1092 * @param buffer The buffer to which to append the information. 1093 */ 1094 public void toString(final StringBuilder buffer) 1095 { 1096 final byte[] v = getValue(); 1097 buffer.append("ASN1Element(type="); 1098 toHex(type, buffer); 1099 buffer.append(", valueLength="); 1100 buffer.append(v.length); 1101 buffer.append(", valueBytes='"); 1102 toHex(v, buffer); 1103 buffer.append("')"); 1104 } 1105}