001/*
002 * Copyright 2017-2019 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2017-2019 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}