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