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