001/* 002 * Copyright 2017-2018 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2017-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 com.unboundid.util.NotMutable; 026import com.unboundid.util.ThreadSafety; 027import com.unboundid.util.ThreadSafetyLevel; 028 029import static com.unboundid.asn1.ASN1Constants.*; 030import static com.unboundid.asn1.ASN1Messages.*; 031import static com.unboundid.util.Debug.*; 032 033 034 035/** 036 * This class provides an ASN.1 bit string element, whose value represents a 037 * series of zero or more bits, where each bit is either one or zero. 038 */ 039@NotMutable() 040@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 041public final class ASN1BitString 042 extends ASN1Element 043{ 044 /** 045 * The serial version UID for this serializable class. 046 */ 047 private static final long serialVersionUID = -5962171503831966571L; 048 049 050 051 // An array of the bits in this bit string, where true is 1 and false is 0. 052 private final boolean[] bits; 053 054 // The bytes represented by the bits that comprise this bit string. 055 private final byte[] bytes; 056 057 058 059 /** 060 * Creates a new ASN.1 bit string element with the default BER type and the 061 * provided set of bits. 062 * 063 * @param bits The bits to include in the bit string. Each {@code boolean} 064 * value of {@code true} represents a bit of one, and each 065 * {@code boolean} value of {@code false} represents a bit of 066 * zero. It must not be {@code null} but may be empty. 067 */ 068 public ASN1BitString(final boolean... bits) 069 { 070 this(UNIVERSAL_BIT_STRING_TYPE, bits); 071 } 072 073 074 075 /** 076 * Creates a new ASN.1 bit string element with the specified BER type and the 077 * provided set of bits. 078 * 079 * @param type The BER type to use for this element. 080 * @param bits The bits to include in the bit string. Each {@code boolean} 081 * value of {@code true} represents a bit of one, and each 082 * {@code boolean} value of {@code false} represents a bit of 083 * zero. It must not be {@code null} but may be empty. 084 */ 085 public ASN1BitString(final byte type, final boolean... bits) 086 { 087 this(type, bits, null, encodeValue(bits)); 088 } 089 090 091 092 /** 093 * Creates a new ASN.1 bit string element with the provided information. 094 * 095 * @param type The BER type to use for this element. 096 * @param bits The bits to include in the bit string. Each 097 * {@code boolean} value of {@code true} represents a 098 * bit of one, and each {@code boolean} value of 099 * {@code false} represents a bit of zero. It must not 100 * be {@code null} but may be empty. 101 * @param bytes The bytes represented by the bits that comprise this 102 * bit string. This may be {@code null} if it has not 103 * yet been determined, or if the number of bits is not 104 * an even multiple of eight. 105 * @param encodedValue The encoded value for this element. 106 */ 107 private ASN1BitString(final byte type, final boolean[] bits, 108 final byte[] bytes, final byte[] encodedValue) 109 { 110 super(type, encodedValue); 111 112 this.bits = bits; 113 114 if (bytes == null) 115 { 116 if ((bits.length % 8) == 0) 117 { 118 this.bytes = new byte[bits.length / 8]; 119 120 byte currentByte = 0x00; 121 int byteIndex = 0; 122 for (int i=0; i < bits.length; i++) 123 { 124 currentByte <<= 1; 125 if (bits[i]) 126 { 127 currentByte |= 0x01; 128 } 129 130 if (((i + 1) % 8) == 0) 131 { 132 this.bytes[byteIndex++] = currentByte; 133 currentByte = 0x00; 134 } 135 } 136 } 137 else 138 { 139 this.bytes = null; 140 } 141 } 142 else 143 { 144 this.bytes = bytes; 145 } 146 } 147 148 149 150 /** 151 * Creates a new ASN.1 bit string with the default BER type and a value 152 * created from the provided string representation. 153 * 154 * @param stringRepresentation A string representation of the bit string to 155 * create. It must not be {@code null}, but may 156 * be empty. It must be comprised only of the 157 * characters '1' and '0'. 158 * 159 * @throws ASN1Exception If the provided string does not represent a valid 160 * bit string value. 161 */ 162 public ASN1BitString(final String stringRepresentation) 163 throws ASN1Exception 164 { 165 this(UNIVERSAL_BIT_STRING_TYPE, stringRepresentation); 166 } 167 168 169 170 /** 171 * Creates a new ASN.1 bit string with the default BER type and a value 172 * created from the provided string representation. 173 * 174 * @param type The BER type to use for this element. 175 * @param stringRepresentation A string representation of the bit string to 176 * create. It must not be {@code null}, but may 177 * be empty. It must be comprised only of the 178 * characters '1' and '0'. 179 * 180 * @throws ASN1Exception If the provided string does not represent a valid 181 * bit string value. 182 */ 183 public ASN1BitString(final byte type, final String stringRepresentation) 184 throws ASN1Exception 185 { 186 this(type, getBits(stringRepresentation)); 187 } 188 189 190 191 /** 192 * Decodes the provided string representation of a bit string into an array of 193 * bits. 194 * 195 * @param s A string representation of the bit string to create. It must 196 * not be {@code null}, but may be empty. It must be comprised 197 * only of the characters '1' and '0'. 198 * 199 * @return An array of {@code boolean} values that correspond to the bits in 200 * this bit string. 201 * 202 * @throws ASN1Exception If the provided string does not represent a valid 203 * bit string value. 204 */ 205 private static boolean[] getBits(final String s) 206 throws ASN1Exception 207 { 208 final char[] chars = s.toCharArray(); 209 final boolean[] bits = new boolean[chars.length]; 210 for (int i=0; i < chars.length; i++) 211 { 212 if (chars[i] == '0') 213 { 214 bits[i] = false; 215 } 216 else if (chars[i] == '1') 217 { 218 bits[i] = true; 219 } 220 else 221 { 222 throw new ASN1Exception( 223 ERR_BIT_STRING_DECODE_STRING_INVALID_CHAR.get()); 224 } 225 } 226 227 return bits; 228 } 229 230 231 232 /** 233 * Generates an encoded value for a bit string with the specified set of 234 * bits. 235 * 236 * @param bits The bits to include in the bit string. Each {@code boolean} 237 * value of {@code true} represents a bit of one, and each 238 * {@code boolean} value of {@code false} represents a bit of 239 * zero. It must not be {@code null} but may be empty. 240 * 241 * @return The encoded value. 242 */ 243 private static byte[] encodeValue(final boolean... bits) 244 { 245 // A bit string value always has at least one byte, and that byte specifies 246 // the number of padding bits needed in the last byte. The remaining bytes 247 // are used to hold the bits, with eight bits per byte. If the number of 248 // bits provided is not a multiple of eight, then it will be assumed that 249 // there are enough extra bits of zero to make an even last byte. 250 final byte[] encodedValue; 251 final int paddingBitsNeeded; 252 final int numBitsMod8 = (bits.length % 8); 253 if (numBitsMod8 == 0) 254 { 255 paddingBitsNeeded = 0; 256 encodedValue = new byte[(bits.length / 8) + 1]; 257 } 258 else 259 { 260 paddingBitsNeeded = 8 - numBitsMod8; 261 encodedValue = new byte[(bits.length / 8) + 2]; 262 } 263 264 encodedValue[0] = (byte) paddingBitsNeeded; 265 266 byte currentByte = 0x00; 267 int bitIndex = 0; 268 int encodedValueIndex = 1; 269 for (final boolean bit : bits) 270 { 271 currentByte <<= 1; 272 if (bit) 273 { 274 currentByte |= 0x01; 275 } 276 277 bitIndex++; 278 if ((bitIndex % 8) == 0) 279 { 280 encodedValue[encodedValueIndex] = currentByte; 281 currentByte = 0x00; 282 encodedValueIndex++; 283 } 284 } 285 286 if (paddingBitsNeeded > 0) 287 { 288 currentByte <<= paddingBitsNeeded; 289 encodedValue[encodedValueIndex] = currentByte; 290 } 291 292 return encodedValue; 293 } 294 295 296 297 /** 298 * Retrieves an array of {@code boolean} values that correspond to the bits in 299 * this bit string. Each {@code boolean} value of {@code true} represents a 300 * bit of one, and each {@code boolean} value of {@code false} represents a 301 * bit of zero. 302 * 303 * @return An array of {@code boolean} values that correspond to the bits in 304 * this bit string. 305 */ 306 public boolean[] getBits() 307 { 308 return bits; 309 } 310 311 312 313 /** 314 * Retrieves the bytes represented by the bits that comprise this bit string, 315 * if the number of bits is a multiple of eight. 316 * 317 * @return The bytes represented by the bits that comprise this bit string. 318 * 319 * @throws ASN1Exception If the number of bits in this bit string is not a 320 * multiple of eight. 321 */ 322 public byte[] getBytes() 323 throws ASN1Exception 324 { 325 if (bytes == null) 326 { 327 throw new ASN1Exception( 328 ERR_BIT_STRING_GET_BYTES_NOT_MULTIPLE_OF_EIGHT_BITS.get( 329 bits.length)); 330 } 331 else 332 { 333 return bytes; 334 } 335 } 336 337 338 339 /** 340 * Retrieves an array of booleans that represent the bits in the provided 341 * array of bytes. 342 * 343 * @param bytes The bytes for which to retrieve the corresponding bits. It 344 * must not be {@code null}. 345 * 346 * @return An array of the bits that make up the provided bytes. 347 */ 348 public static boolean[] getBitsForBytes(final byte... bytes) 349 { 350 final boolean[] bits = new boolean[bytes.length * 8]; 351 for (int i=0; i < bytes.length; i++) 352 { 353 final byte b = bytes[i]; 354 bits[i * 8] = ((b & 0x80) == 0x80); 355 bits[(i * 8) + 1] = ((b & 0x40) == 0x40); 356 bits[(i * 8) + 2] = ((b & 0x20) == 0x20); 357 bits[(i * 8) + 3] = ((b & 0x10) == 0x10); 358 bits[(i * 8) + 4] = ((b & 0x08) == 0x08); 359 bits[(i * 8) + 5] = ((b & 0x04) == 0x04); 360 bits[(i * 8) + 6] = ((b & 0x02) == 0x02); 361 bits[(i * 8) + 7] = ((b & 0x01) == 0x01); 362 } 363 364 return bits; 365 } 366 367 368 369 /** 370 * Decodes the contents of the provided byte array as a bit string element. 371 * 372 * @param elementBytes The byte array to decode as an ASN.1 bit string 373 * element. 374 * 375 * @return The decoded ASN.1 bit string element. 376 * 377 * @throws ASN1Exception If the provided array cannot be decoded as a bit 378 * string element. 379 */ 380 public static ASN1BitString decodeAsBitString(final byte[] elementBytes) 381 throws ASN1Exception 382 { 383 try 384 { 385 int valueStartPos = 2; 386 int length = (elementBytes[1] & 0x7F); 387 if (length != elementBytes[1]) 388 { 389 final int numLengthBytes = length; 390 391 length = 0; 392 for (int i=0; i < numLengthBytes; i++) 393 { 394 length <<= 8; 395 length |= (elementBytes[valueStartPos++] & 0xFF); 396 } 397 } 398 399 if ((elementBytes.length - valueStartPos) != length) 400 { 401 throw new ASN1Exception(ERR_ELEMENT_LENGTH_MISMATCH.get(length, 402 (elementBytes.length - valueStartPos))); 403 } 404 405 final byte[] elementValue = new byte[length]; 406 System.arraycopy(elementBytes, valueStartPos, elementValue, 0, length); 407 final boolean[] bits = decodeValue(elementValue); 408 409 final byte[] bytes; 410 if ((bits.length % 8) == 0) 411 { 412 bytes = new byte[elementValue.length - 1]; 413 System.arraycopy(elementValue, 1, bytes, 0, bytes.length); 414 } 415 else 416 { 417 bytes = null; 418 } 419 420 return new ASN1BitString(elementBytes[0], bits, bytes, elementValue); 421 } 422 catch (final ASN1Exception ae) 423 { 424 debugException(ae); 425 throw ae; 426 } 427 catch (final Exception e) 428 { 429 debugException(e); 430 throw new ASN1Exception(ERR_ELEMENT_DECODE_EXCEPTION.get(e), e); 431 } 432 } 433 434 435 436 /** 437 * Decodes the provided ASN.1 element as a bit string element. 438 * 439 * @param element The ASN.1 element to be decoded. 440 * 441 * @return The decoded ASN.1 bit string element. 442 * 443 * @throws ASN1Exception If the provided element cannot be decoded as a bit 444 * string element. 445 */ 446 public static ASN1BitString decodeAsBitString(final ASN1Element element) 447 throws ASN1Exception 448 { 449 final byte[] elementValue = element.getValue(); 450 final boolean[] bits = decodeValue(elementValue); 451 452 final byte[] bytes; 453 if ((bits.length % 8) == 0) 454 { 455 bytes = new byte[elementValue.length - 1]; 456 System.arraycopy(elementValue, 1, bytes, 0, bytes.length); 457 } 458 else 459 { 460 bytes = null; 461 } 462 463 return new ASN1BitString(element.getType(), bits, bytes, 464 element.getValue()); 465 } 466 467 468 469 /** 470 * Decodes the provided value into a set of bits. 471 * 472 * @param elementValue The bytes that comprise the encoded value for a 473 * bit string element. 474 * 475 * @return An array of {@code boolean} values that correspond to the bits in 476 * this bit string. 477 * 478 * @throws ASN1Exception If the provided value cannot be decoded as a valid 479 * bit string. 480 */ 481 private static boolean[] decodeValue(final byte[] elementValue) 482 throws ASN1Exception 483 { 484 if (elementValue.length == 0) 485 { 486 throw new ASN1Exception(ERR_BIT_STRING_DECODE_EMPTY_VALUE.get()); 487 } 488 489 final int paddingBitsNeeded = (elementValue[0] & 0xFF); 490 if (paddingBitsNeeded > 7) 491 { 492 throw new ASN1Exception( 493 ERR_BIT_STRING_DECODE_INVALID_PADDING_BIT_COUNT.get( 494 paddingBitsNeeded)); 495 } 496 497 if ((paddingBitsNeeded > 0) && (elementValue.length == 1)) 498 { 499 throw new ASN1Exception( 500 ERR_BIT_STRING_DECODE_NONZERO_PADDING_BIT_COUNT_WITH_NO_MORE_BYTES. 501 get()); 502 } 503 504 int bitsIndex = 0; 505 final int numBits = ((elementValue.length - 1) * 8) - paddingBitsNeeded; 506 final boolean[] bits = new boolean[numBits]; 507 for (int i=1; i < elementValue.length; i++) 508 { 509 byte b = elementValue[i]; 510 if ((i == (elementValue.length - 1)) && (paddingBitsNeeded > 0)) 511 { 512 for (int j=0; j < (8 - paddingBitsNeeded); j++) 513 { 514 bits[bitsIndex++] = ((b & 0x80) == 0x80); 515 b <<= 1; 516 } 517 } 518 else 519 { 520 bits[bitsIndex++] = ((b & 0x80) == 0x80); 521 bits[bitsIndex++] = ((b & 0x40) == 0x40); 522 bits[bitsIndex++] = ((b & 0x20) == 0x20); 523 bits[bitsIndex++] = ((b & 0x10) == 0x10); 524 bits[bitsIndex++] = ((b & 0x08) == 0x08); 525 bits[bitsIndex++] = ((b & 0x04) == 0x04); 526 bits[bitsIndex++] = ((b & 0x02) == 0x02); 527 bits[bitsIndex++] = ((b & 0x01) == 0x01); 528 } 529 } 530 531 return bits; 532 } 533 534 535 536 /** 537 * {@inheritDoc} 538 */ 539 @Override() 540 public void toString(final StringBuilder buffer) 541 { 542 buffer.ensureCapacity(buffer.length() + bits.length); 543 for (final boolean bit : bits) 544 { 545 if (bit) 546 { 547 buffer.append('1'); 548 } 549 else 550 { 551 buffer.append('0'); 552 } 553 } 554 } 555}