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