001 /* 002 * Copyright 2008-2015 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005 /* 006 * Copyright (C) 2008-2015 UnboundID Corp. 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 */ 021 package com.unboundid.asn1; 022 023 024 025 026 import static com.unboundid.asn1.ASN1Constants.*; 027 import static com.unboundid.asn1.ASN1Messages.*; 028 import static com.unboundid.util.Debug.*; 029 030 031 032 /** 033 * This class provides an ASN.1 long element. It is exactly the same as an 034 * ASN.1 integer, but it uses a 64-bit representation for the decoded value 035 * rather than a 32-bit representation. 036 */ 037 public final class ASN1Long 038 extends ASN1Element 039 { 040 /** 041 * The serial version UID for this serializable class. 042 */ 043 private static final long serialVersionUID = -3445506299288414013L; 044 045 046 047 // The long value for this element. 048 private final long longValue; 049 050 051 052 /** 053 * Creates a new ASN.1 long element with the default BER type and the 054 * provided long value. 055 * 056 * @param longValue The long value to use for this element. 057 */ 058 public ASN1Long(final long longValue) 059 { 060 super(UNIVERSAL_INTEGER_TYPE, encodeLongValue(longValue)); 061 062 this.longValue = longValue; 063 } 064 065 066 067 /** 068 * Creates a new ASN.1 long element with the specified BER type and the 069 * provided long value. 070 * 071 * @param type The BER type to use for this element. 072 * @param longValue The long value to use for this element. 073 */ 074 public ASN1Long(final byte type, final long longValue) 075 { 076 super(type, encodeLongValue(longValue)); 077 078 this.longValue = longValue; 079 } 080 081 082 083 /** 084 * Creates a new ASN.1 long element with the specified BER type and the 085 * provided long and pre-encoded values. 086 * 087 * @param type The BER type to use for this element. 088 * @param longValue The long value to use for this element. 089 * @param value The pre-encoded value to use for this element. 090 */ 091 private ASN1Long(final byte type, final long longValue, final byte[] value) 092 { 093 super(type, value); 094 095 this.longValue = longValue; 096 } 097 098 099 100 /** 101 * Encodes the provided long value to a byte array suitable for use as the 102 * value of a long element. 103 * 104 * @param longValue The long value to be encoded. 105 * 106 * @return A byte array containing the encoded value. 107 */ 108 static byte[] encodeLongValue(final long longValue) 109 { 110 if (longValue < 0) 111 { 112 if ((longValue & 0xFFFFFFFFFFFFFF80L) == 0xFFFFFFFFFFFFFF80L) 113 { 114 return new byte[] 115 { 116 (byte) (longValue & 0xFFL) 117 }; 118 } 119 else if ((longValue & 0xFFFFFFFFFFFF8000L) == 0xFFFFFFFFFFFF8000L) 120 { 121 return new byte[] 122 { 123 (byte) ((longValue >> 8) & 0xFFL), 124 (byte) (longValue & 0xFFL) 125 }; 126 } 127 else if ((longValue & 0xFFFFFFFFFF800000L) == 0xFFFFFFFFFF800000L) 128 { 129 return new byte[] 130 { 131 (byte) ((longValue >> 16) & 0xFFL), 132 (byte) ((longValue >> 8) & 0xFFL), 133 (byte) (longValue & 0xFFL) 134 }; 135 } 136 else if ((longValue & 0xFFFFFFFF80000000L) == 0xFFFFFFFF80000000L) 137 { 138 return new byte[] 139 { 140 (byte) ((longValue >> 24) & 0xFFL), 141 (byte) ((longValue >> 16) & 0xFFL), 142 (byte) ((longValue >> 8) & 0xFFL), 143 (byte) (longValue & 0xFFL) 144 }; 145 } 146 else if ((longValue & 0xFFFFFF8000000000L) == 0xFFFFFF8000000000L) 147 { 148 return new byte[] 149 { 150 (byte) ((longValue >> 32) & 0xFFL), 151 (byte) ((longValue >> 24) & 0xFFL), 152 (byte) ((longValue >> 16) & 0xFFL), 153 (byte) ((longValue >> 8) & 0xFFL), 154 (byte) (longValue & 0xFFL) 155 }; 156 } 157 else if ((longValue & 0xFFFF800000000000L) == 0xFFFF800000000000L) 158 { 159 return new byte[] 160 { 161 (byte) ((longValue >> 40) & 0xFFL), 162 (byte) ((longValue >> 32) & 0xFFL), 163 (byte) ((longValue >> 24) & 0xFFL), 164 (byte) ((longValue >> 16) & 0xFFL), 165 (byte) ((longValue >> 8) & 0xFFL), 166 (byte) (longValue & 0xFFL) 167 }; 168 } 169 else if ((longValue & 0xFF80000000000000L) == 0xFF80000000000000L) 170 { 171 return new byte[] 172 { 173 (byte) ((longValue >> 48) & 0xFFL), 174 (byte) ((longValue >> 40) & 0xFFL), 175 (byte) ((longValue >> 32) & 0xFFL), 176 (byte) ((longValue >> 24) & 0xFFL), 177 (byte) ((longValue >> 16) & 0xFFL), 178 (byte) ((longValue >> 8) & 0xFFL), 179 (byte) (longValue & 0xFFL) 180 }; 181 } 182 else 183 { 184 return new byte[] 185 { 186 (byte) ((longValue >> 56) & 0xFFL), 187 (byte) ((longValue >> 48) & 0xFFL), 188 (byte) ((longValue >> 40) & 0xFFL), 189 (byte) ((longValue >> 32) & 0xFFL), 190 (byte) ((longValue >> 24) & 0xFFL), 191 (byte) ((longValue >> 16) & 0xFFL), 192 (byte) ((longValue >> 8) & 0xFFL), 193 (byte) (longValue & 0xFFL) 194 }; 195 } 196 } 197 else 198 { 199 if ((longValue & 0x000000000000007FL) == longValue) 200 { 201 return new byte[] 202 { 203 (byte) (longValue & 0x7FL) 204 }; 205 } 206 else if ((longValue & 0x0000000000007FFFL) == longValue) 207 { 208 return new byte[] 209 { 210 (byte) ((longValue >> 8) & 0x7FL), 211 (byte) (longValue & 0xFFL) 212 }; 213 } 214 else if ((longValue & 0x00000000007FFFFFL) == longValue) 215 { 216 return new byte[] 217 { 218 (byte) ((longValue >> 16) & 0x7FL), 219 (byte) ((longValue >> 8) & 0xFFL), 220 (byte) (longValue & 0xFFL) 221 }; 222 } 223 else if ((longValue & 0x000000007FFFFFFFL) == longValue) 224 { 225 return new byte[] 226 { 227 (byte) ((longValue >> 24) & 0x7FL), 228 (byte) ((longValue >> 16) & 0xFFL), 229 (byte) ((longValue >> 8) & 0xFFL), 230 (byte) (longValue & 0xFFL) 231 }; 232 } 233 else if ((longValue & 0x0000007FFFFFFFFFL) == longValue) 234 { 235 return new byte[] 236 { 237 (byte) ((longValue >> 32) & 0x7FL), 238 (byte) ((longValue >> 24) & 0xFFL), 239 (byte) ((longValue >> 16) & 0xFFL), 240 (byte) ((longValue >> 8) & 0xFFL), 241 (byte) (longValue & 0xFFL) 242 }; 243 } 244 else if ((longValue & 0x00007FFFFFFFFFFFL) == longValue) 245 { 246 return new byte[] 247 { 248 (byte) ((longValue >> 40) & 0x7FL), 249 (byte) ((longValue >> 32) & 0xFFL), 250 (byte) ((longValue >> 24) & 0xFFL), 251 (byte) ((longValue >> 16) & 0xFFL), 252 (byte) ((longValue >> 8) & 0xFFL), 253 (byte) (longValue & 0xFFL) 254 }; 255 } 256 else if ((longValue & 0x007FFFFFFFFFFFFFL) == longValue) 257 { 258 return new byte[] 259 { 260 (byte) ((longValue >> 48) & 0x7FL), 261 (byte) ((longValue >> 40) & 0xFFL), 262 (byte) ((longValue >> 32) & 0xFFL), 263 (byte) ((longValue >> 24) & 0xFFL), 264 (byte) ((longValue >> 16) & 0xFFL), 265 (byte) ((longValue >> 8) & 0xFFL), 266 (byte) (longValue & 0xFFL) 267 }; 268 } 269 else 270 { 271 return new byte[] 272 { 273 (byte) ((longValue >> 56) & 0x7FL), 274 (byte) ((longValue >> 48) & 0xFFL), 275 (byte) ((longValue >> 40) & 0xFFL), 276 (byte) ((longValue >> 32) & 0xFFL), 277 (byte) ((longValue >> 24) & 0xFFL), 278 (byte) ((longValue >> 16) & 0xFFL), 279 (byte) ((longValue >> 8) & 0xFFL), 280 (byte) (longValue & 0xFFL) 281 }; 282 } 283 } 284 } 285 286 287 288 /** 289 * Retrieves the long value for this element. 290 * 291 * @return The long value for this element. 292 */ 293 public long longValue() 294 { 295 return longValue; 296 } 297 298 299 300 /** 301 * Decodes the contents of the provided byte array as a long element. 302 * 303 * @param elementBytes The byte array to decode as an ASN.1 long element. 304 * 305 * @return The decoded ASN.1 long element. 306 * 307 * @throws ASN1Exception If the provided array cannot be decoded as a long 308 * element. 309 */ 310 public static ASN1Long decodeAsLong(final byte[] elementBytes) 311 throws ASN1Exception 312 { 313 try 314 { 315 int valueStartPos = 2; 316 int length = (elementBytes[1] & 0x7F); 317 if (length != elementBytes[1]) 318 { 319 final int numLengthBytes = length; 320 321 length = 0; 322 for (int i=0; i < numLengthBytes; i++) 323 { 324 length <<= 8; 325 length |= (elementBytes[valueStartPos++] & 0xFF); 326 } 327 } 328 329 if ((elementBytes.length - valueStartPos) != length) 330 { 331 throw new ASN1Exception(ERR_ELEMENT_LENGTH_MISMATCH.get(length, 332 (elementBytes.length - valueStartPos))); 333 } 334 335 final byte[] value = new byte[length]; 336 System.arraycopy(elementBytes, valueStartPos, value, 0, length); 337 338 long longValue; 339 switch (value.length) 340 { 341 case 1: 342 longValue = (value[0] & 0xFFL); 343 if ((value[0] & 0x80L) != 0x00L) 344 { 345 longValue |= 0xFFFFFFFFFFFFFF00L; 346 } 347 break; 348 349 case 2: 350 longValue = ((value[0] & 0xFFL) << 8) | (value[1] & 0xFFL); 351 if ((value[0] & 0x80L) != 0x00L) 352 { 353 longValue |= 0xFFFFFFFFFFFF0000L; 354 } 355 break; 356 357 case 3: 358 longValue = ((value[0] & 0xFFL) << 16) | ((value[1] & 0xFFL) << 8) | 359 (value[2] & 0xFFL); 360 if ((value[0] & 0x80L) != 0x00L) 361 { 362 longValue |= 0xFFFFFFFFFF000000L; 363 } 364 break; 365 366 case 4: 367 longValue = ((value[0] & 0xFFL) << 24) | ((value[1] & 0xFFL) << 16) | 368 ((value[2] & 0xFFL) << 8) | (value[3] & 0xFFL); 369 if ((value[0] & 0x80L) != 0x00L) 370 { 371 longValue |= 0xFFFFFFFF00000000L; 372 } 373 break; 374 375 case 5: 376 longValue = ((value[0] & 0xFFL) << 32) | ((value[1] & 0xFFL) << 24) | 377 ((value[2] & 0xFFL) << 16) | ((value[3] & 0xFFL) << 8) | 378 (value[4] & 0xFFL); 379 if ((value[0] & 0x80L) != 0x00L) 380 { 381 longValue |= 0xFFFFFF0000000000L; 382 } 383 break; 384 385 case 6: 386 longValue = ((value[0] & 0xFFL) << 40) | ((value[1] & 0xFFL) << 32) | 387 ((value[2] & 0xFFL) << 24) | ((value[3] & 0xFFL) << 16) | 388 ((value[4] & 0xFFL) << 8) | (value[5] & 0xFFL); 389 if ((value[0] & 0x80L) != 0x00L) 390 { 391 longValue |= 0xFFFF000000000000L; 392 } 393 break; 394 395 case 7: 396 longValue = ((value[0] & 0xFFL) << 48) | ((value[1] & 0xFFL) << 40) | 397 ((value[2] & 0xFFL) << 32) | ((value[3] & 0xFFL) << 24) | 398 ((value[4] & 0xFFL) << 16) | ((value[5] & 0xFFL) << 8) | 399 (value[6] & 0xFFL); 400 if ((value[0] & 0x80L) != 0x00L) 401 { 402 longValue |= 0xFF00000000000000L; 403 } 404 break; 405 406 case 8: 407 longValue = ((value[0] & 0xFFL) << 56) | ((value[1] & 0xFFL) << 48) | 408 ((value[2] & 0xFFL) << 40) | ((value[3] & 0xFFL) << 32) | 409 ((value[4] & 0xFFL) << 24) | ((value[5] & 0xFFL) << 16) | 410 ((value[6] & 0xFFL) << 8) | (value[7] & 0xFFL); 411 break; 412 413 default: 414 throw new ASN1Exception(ERR_LONG_INVALID_LENGTH.get(value.length)); 415 } 416 417 return new ASN1Long(elementBytes[0], longValue, value); 418 } 419 catch (final ASN1Exception ae) 420 { 421 debugException(ae); 422 throw ae; 423 } 424 catch (final Exception e) 425 { 426 debugException(e); 427 throw new ASN1Exception(ERR_ELEMENT_DECODE_EXCEPTION.get(e), e); 428 } 429 } 430 431 432 433 /** 434 * Decodes the provided ASN.1 element as a long element. 435 * 436 * @param element The ASN.1 element to be decoded. 437 * 438 * @return The decoded ASN.1 long element. 439 * 440 * @throws ASN1Exception If the provided element cannot be decoded as a long 441 * element. 442 */ 443 public static ASN1Long decodeAsLong(final ASN1Element element) 444 throws ASN1Exception 445 { 446 long longValue; 447 final byte[] value = element.getValue(); 448 switch (value.length) 449 { 450 case 1: 451 longValue = (value[0] & 0xFFL); 452 if ((value[0] & 0x80L) != 0x00L) 453 { 454 longValue |= 0xFFFFFFFFFFFFFF00L; 455 } 456 break; 457 458 case 2: 459 longValue = ((value[0] & 0xFFL) << 8) | (value[1] & 0xFFL); 460 if ((value[0] & 0x80L) != 0x00L) 461 { 462 longValue |= 0xFFFFFFFFFFFF0000L; 463 } 464 break; 465 466 case 3: 467 longValue = ((value[0] & 0xFFL) << 16) | ((value[1] & 0xFFL) << 8) | 468 (value[2] & 0xFFL); 469 if ((value[0] & 0x80L) != 0x00L) 470 { 471 longValue |= 0xFFFFFFFFFF000000L; 472 } 473 break; 474 475 case 4: 476 longValue = ((value[0] & 0xFFL) << 24) | ((value[1] & 0xFFL) << 16) | 477 ((value[2] & 0xFFL) << 8) | (value[3] & 0xFFL); 478 if ((value[0] & 0x80L) != 0x00L) 479 { 480 longValue |= 0xFFFFFFFF00000000L; 481 } 482 break; 483 484 case 5: 485 longValue = ((value[0] & 0xFFL) << 32) | ((value[1] & 0xFFL) << 24) | 486 ((value[2] & 0xFFL) << 16) | ((value[3] & 0xFFL) << 8) | 487 (value[4] & 0xFFL); 488 if ((value[0] & 0x80L) != 0x00L) 489 { 490 longValue |= 0xFFFFFF0000000000L; 491 } 492 break; 493 494 case 6: 495 longValue = ((value[0] & 0xFFL) << 40) | ((value[1] & 0xFFL) << 32) | 496 ((value[2] & 0xFFL) << 24) | ((value[3] & 0xFFL) << 16) | 497 ((value[4] & 0xFFL) << 8) | (value[5] & 0xFFL); 498 if ((value[0] & 0x80L) != 0x00L) 499 { 500 longValue |= 0xFFFF000000000000L; 501 } 502 break; 503 504 case 7: 505 longValue = ((value[0] & 0xFFL) << 48) | ((value[1] & 0xFFL) << 40) | 506 ((value[2] & 0xFFL) << 32) | ((value[3] & 0xFFL) << 24) | 507 ((value[4] & 0xFFL) << 16) | ((value[5] & 0xFFL) << 8) | 508 (value[6] & 0xFFL); 509 if ((value[0] & 0x80L) != 0x00L) 510 { 511 longValue |= 0xFF00000000000000L; 512 } 513 break; 514 515 case 8: 516 longValue = ((value[0] & 0xFFL) << 56) | ((value[1] & 0xFFL) << 48) | 517 ((value[2] & 0xFFL) << 40) | ((value[3] & 0xFFL) << 32) | 518 ((value[4] & 0xFFL) << 24) | ((value[5] & 0xFFL) << 16) | 519 ((value[6] & 0xFFL) << 8) | (value[7] & 0xFFL); 520 break; 521 522 default: 523 throw new ASN1Exception(ERR_LONG_INVALID_LENGTH.get(value.length)); 524 } 525 526 return new ASN1Long(element.getType(), longValue, value); 527 } 528 529 530 531 /** 532 * Appends a string representation of this ASN.1 element to the provided 533 * buffer. 534 * 535 * @param buffer The buffer to which to append the information. 536 */ 537 @Override() 538 public void toString(final StringBuilder buffer) 539 { 540 buffer.append(longValue); 541 } 542 }