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}