16e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrompackage org.bouncycastle.asn1;
26e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
3d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport java.io.IOException;
46e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.math.BigInteger;
56e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
6d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.util.Arrays;
7d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
8d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root/**
9d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root * Class representing the ASN.1 INTEGER type.
10d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root */
116e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrompublic class ASN1Integer
12d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    extends ASN1Primitive
136e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom{
1479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    private final byte[] bytes;
15d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
16d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    /**
17d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     * return an integer from the passed in object
18d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     *
19d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     * @param obj an ASN1Integer or an object that can be converted into one.
20d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     * @throws IllegalArgumentException if the object cannot be converted.
21d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     * @return an ASN1Integer instance.
22d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     */
23d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public static ASN1Integer getInstance(
24d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        Object obj)
25d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
26d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        if (obj == null || obj instanceof ASN1Integer)
27d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        {
28d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            return (ASN1Integer)obj;
29d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        }
30d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
31d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        if (obj instanceof byte[])
32d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        {
33d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            try
34d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            {
35d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                return (ASN1Integer)fromByteArray((byte[])obj);
36d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            }
37d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            catch (Exception e)
38d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            {
39d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
40d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            }
41d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        }
42d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
43d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
44d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
45d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
46d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    /**
47d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     * return an Integer from a tagged object.
48d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     *
49d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     * @param obj      the tagged object holding the object we want
50d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     * @param explicit true if the object is meant to be explicitly
51d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     *                 tagged false otherwise.
52d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     * @throws IllegalArgumentException if the tagged object cannot
53d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     * be converted.
54d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     * @return an ASN1Integer instance.
55d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     */
56d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public static ASN1Integer getInstance(
57d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        ASN1TaggedObject obj,
58d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        boolean explicit)
59d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
60d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        ASN1Primitive o = obj.getObject();
61d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
62d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        if (explicit || o instanceof ASN1Integer)
63d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        {
64d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            return getInstance(o);
65d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        }
66d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        else
67d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        {
68d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            return new ASN1Integer(ASN1OctetString.getInstance(obj.getObject()).getOctets());
69d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        }
70d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
71d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
72d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public ASN1Integer(
73d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        long value)
746e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
75d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        bytes = BigInteger.valueOf(value).toByteArray();
766e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
776e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
78d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public ASN1Integer(
79d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        BigInteger value)
806e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
81d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        bytes = value.toByteArray();
826e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
836e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
84d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public ASN1Integer(
85d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        byte[] bytes)
866e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
87d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        this(bytes, true);
886e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
89d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
90d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    ASN1Integer(byte[] bytes, boolean clone)
91d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
92d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        this.bytes = (clone) ? Arrays.clone(bytes) : bytes;
93d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
94d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
95d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public BigInteger getValue()
96d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
97d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return new BigInteger(bytes);
98d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
99d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
100d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    /**
101d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     * in some cases positive values get crammed into a space,
102d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     * that's not quite big enough...
103d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     * @return the BigInteger that results from treating this ASN.1 INTEGER as unsigned.
104d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     */
105d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public BigInteger getPositiveValue()
106d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
107d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return new BigInteger(1, bytes);
108d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
109d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
110d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    boolean isConstructed()
111d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
112d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return false;
113d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
114d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
115d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    int encodedLength()
116d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
117d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length;
118d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
119d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
120d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    void encode(
121d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        ASN1OutputStream out)
122d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        throws IOException
123d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
124d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        out.writeEncoded(BERTags.INTEGER, bytes);
125d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
126d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
127d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public int hashCode()
128d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
129d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int value = 0;
130d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
131d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        for (int i = 0; i != bytes.length; i++)
132d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        {
133d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            value ^= (bytes[i] & 0xff) << (i % 4);
134d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        }
135d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
136d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return value;
137d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
138d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
139d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    boolean asn1Equals(
140d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        ASN1Primitive o)
141d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
142d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        if (!(o instanceof ASN1Integer))
143d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        {
144d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            return false;
145d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        }
146d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
147d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        ASN1Integer other = (ASN1Integer)o;
148d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
149d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return Arrays.areEqual(bytes, other.bytes);
150d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
151d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
152d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public String toString()
153d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
154d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return getValue().toString();
155d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
156d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
1576e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom}
158