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