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}