001package org.apache.commons.ssl.org.bouncycastle.asn1;
002
003import java.io.IOException;
004import java.math.BigInteger;
005
006import org.bouncycastle.util.Arrays;
007
008/**
009 * Class representing the ASN.1 INTEGER type.
010 */
011public class ASN1Integer
012    extends ASN1Primitive
013{
014    byte[] bytes;
015
016    /**
017     * return an integer from the passed in object
018     *
019     * @param obj an ASN1Integer or an object that can be converted into one.
020     * @throws IllegalArgumentException if the object cannot be converted.
021     * @return an ASN1Integer instance.
022     */
023    public static ASN1Integer getInstance(
024        Object obj)
025    {
026        if (obj == null || obj instanceof ASN1Integer)
027        {
028            return (ASN1Integer)obj;
029        }
030
031        if (obj instanceof byte[])
032        {
033            try
034            {
035                return (ASN1Integer)fromByteArray((byte[])obj);
036            }
037            catch (Exception e)
038            {
039                throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
040            }
041        }
042
043        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
044    }
045
046    /**
047     * return an Integer from a tagged object.
048     *
049     * @param obj      the tagged object holding the object we want
050     * @param explicit true if the object is meant to be explicitly
051     *                 tagged false otherwise.
052     * @throws IllegalArgumentException if the tagged object cannot
053     * be converted.
054     * @return an ASN1Integer instance.
055     */
056    public static ASN1Integer getInstance(
057        ASN1TaggedObject obj,
058        boolean explicit)
059    {
060        ASN1Primitive o = obj.getObject();
061
062        if (explicit || o instanceof ASN1Integer)
063        {
064            return getInstance(o);
065        }
066        else
067        {
068            return new ASN1Integer(ASN1OctetString.getInstance(obj.getObject()).getOctets());
069        }
070    }
071
072    public ASN1Integer(
073        long value)
074    {
075        bytes = BigInteger.valueOf(value).toByteArray();
076    }
077
078    public ASN1Integer(
079        BigInteger value)
080    {
081        bytes = value.toByteArray();
082    }
083
084    public ASN1Integer(
085        byte[] bytes)
086    {
087        this(bytes, true);
088    }
089
090    ASN1Integer(byte[] bytes, boolean clone)
091    {
092        this.bytes = (clone) ? Arrays.clone(bytes) : bytes;
093    }
094
095    public BigInteger getValue()
096    {
097        return new BigInteger(bytes);
098    }
099
100    /**
101     * in some cases positive values get crammed into a space,
102     * that's not quite big enough...
103     * @return the BigInteger that results from treating this ASN.1 INTEGER as unsigned.
104     */
105    public BigInteger getPositiveValue()
106    {
107        return new BigInteger(1, bytes);
108    }
109
110    boolean isConstructed()
111    {
112        return false;
113    }
114
115    int encodedLength()
116    {
117        return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length;
118    }
119
120    void encode(
121        ASN1OutputStream out)
122        throws IOException
123    {
124        out.writeEncoded(BERTags.INTEGER, bytes);
125    }
126
127    public int hashCode()
128    {
129        int value = 0;
130
131        for (int i = 0; i != bytes.length; i++)
132        {
133            value ^= (bytes[i] & 0xff) << (i % 4);
134        }
135
136        return value;
137    }
138
139    boolean asn1Equals(
140        ASN1Primitive o)
141    {
142        if (!(o instanceof ASN1Integer))
143        {
144            return false;
145        }
146
147        ASN1Integer other = (ASN1Integer)o;
148
149        return Arrays.areEqual(bytes, other.bytes);
150    }
151
152    public String toString()
153    {
154        return getValue().toString();
155    }
156
157}