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