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