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 java.math.BigInteger; 026 027import com.unboundid.util.Debug; 028import com.unboundid.util.NotMutable; 029import com.unboundid.util.ThreadSafety; 030import com.unboundid.util.ThreadSafetyLevel; 031 032import static com.unboundid.asn1.ASN1Messages.*; 033 034 035 036/** 037 * This class provides an ASN.1 integer element that is backed by a Java 038 * {@code BigInteger} and whose value can be represented as an integer of any 039 * magnitude. For an ASN.1 integer implementation that is backed by a signed 040 * 32-bit {@code int}, see {@link ASN1Integer}. For an implementation that is 041 * backed by a signed 64-bit {@code long}, see {@link ASN1Long}. 042 */ 043@NotMutable() 044@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 045public final class ASN1BigInteger 046 extends ASN1Element 047{ 048 /** 049 * The serial version UID for this serializable class. 050 */ 051 private static final long serialVersionUID = 2631806934961821260L; 052 053 054 055 // The BigInteger value for this element. 056 private final BigInteger value; 057 058 059 060 /** 061 * Creates a new ASN.1 big integer element with the default BER type and the 062 * provided value. 063 * 064 * @param value The value to use for this element. It must not be 065 * {@code null}. 066 */ 067 public ASN1BigInteger(final BigInteger value) 068 { 069 this(ASN1Constants.UNIVERSAL_INTEGER_TYPE, value); 070 } 071 072 073 074 /** 075 * Creates a new ASN.1 big integer element with the specified BER type and the 076 * provided value. 077 * 078 * @param type The BER type to use for this element. 079 * @param value The value to use for this element. It must not be 080 * {@code null}. 081 */ 082 public ASN1BigInteger(final byte type, final BigInteger value) 083 { 084 super(type, value.toByteArray()); 085 086 this.value = value; 087 } 088 089 090 091 /** 092 * Creates a new ASN.1 big integer element with the specified BER type and the 093 * provided value. 094 * 095 * @param type The BER type to use for this element. 096 * @param bigIntegerValue The value to use for this element. It must not be 097 * {@code null}. 098 * @param berValue The encoded BER value for this element. It must 099 * not be {@code null} or empty. 100 */ 101 private ASN1BigInteger(final byte type, final BigInteger bigIntegerValue, 102 final byte[] berValue) 103 { 104 super(type, berValue); 105 value = bigIntegerValue; 106 } 107 108 109 110 /** 111 * Creates a new ASN.1 big integer element with the default BER type and the 112 * provided long value. 113 * 114 * @param value The int value to use for this element. 115 */ 116 public ASN1BigInteger(final long value) 117 { 118 this(ASN1Constants.UNIVERSAL_INTEGER_TYPE, BigInteger.valueOf(value)); 119 } 120 121 122 123 /** 124 * Creates a new ASN.1 big integer element with the specified BER type and the 125 * provided long value. 126 * 127 * @param type The BER type to use for this element. 128 * @param value The int value to use for this element. 129 */ 130 public ASN1BigInteger(final byte type, final long value) 131 { 132 this(type, BigInteger.valueOf(value)); 133 } 134 135 136 137 /** 138 * Retrieves the value for this element as a Java {@code BigInteger}. 139 * 140 * @return The value for this element as a Java {@code BigInteger}. 141 */ 142 public BigInteger getBigIntegerValue() 143 { 144 return value; 145 } 146 147 148 149 /** 150 * Decodes the contents of the provided byte array as a big integer element. 151 * 152 * @param elementBytes The byte array to decode as an ASN.1 big integer 153 * element. 154 * 155 * @return The decoded ASN.1 big integer element. 156 * 157 * @throws ASN1Exception If the provided array cannot be decoded as a big 158 * integer element. 159 */ 160 public static ASN1BigInteger decodeAsBigInteger(final byte[] elementBytes) 161 throws ASN1Exception 162 { 163 try 164 { 165 int valueStartPos = 2; 166 int length = (elementBytes[1] & 0x7F); 167 if (length != elementBytes[1]) 168 { 169 final int numLengthBytes = length; 170 171 length = 0; 172 for (int i=0; i < numLengthBytes; i++) 173 { 174 length <<= 8; 175 length |= (elementBytes[valueStartPos++] & 0xFF); 176 } 177 } 178 179 if ((elementBytes.length - valueStartPos) != length) 180 { 181 throw new ASN1Exception(ERR_ELEMENT_LENGTH_MISMATCH.get(length, 182 (elementBytes.length - valueStartPos))); 183 } 184 185 if (length == 0) 186 { 187 throw new ASN1Exception(ERR_BIG_INTEGER_DECODE_EMPTY_VALUE.get()); 188 } 189 190 final byte[] elementValue = new byte[length]; 191 System.arraycopy(elementBytes, valueStartPos, elementValue, 0, length); 192 193 final BigInteger bigIntegerValue = new BigInteger(elementValue); 194 return new ASN1BigInteger(elementBytes[0], bigIntegerValue, elementValue); 195 } 196 catch (final ASN1Exception ae) 197 { 198 Debug.debugException(ae); 199 throw ae; 200 } 201 catch (final Exception e) 202 { 203 Debug.debugException(e); 204 throw new ASN1Exception(ERR_ELEMENT_DECODE_EXCEPTION.get(e), e); 205 } 206 } 207 208 209 210 /** 211 * Decodes the provided ASN.1 element as a big integer element. 212 * 213 * @param element The ASN.1 element to be decoded. 214 * 215 * @return The decoded ASN.1 big integer element. 216 * 217 * @throws ASN1Exception If the provided element cannot be decoded as a big 218 * integer element. 219 */ 220 public static ASN1BigInteger decodeAsBigInteger(final ASN1Element element) 221 throws ASN1Exception 222 { 223 final byte[] value = element.getValue(); 224 if (value.length == 0) 225 { 226 throw new ASN1Exception(ERR_BIG_INTEGER_DECODE_EMPTY_VALUE.get()); 227 } 228 229 return new ASN1BigInteger(element.getType(), new BigInteger(value), value); 230 } 231 232 233 234 /** 235 * {@inheritDoc} 236 */ 237 @Override() 238 public void toString(final StringBuilder buffer) 239 { 240 buffer.append(value); 241 } 242}