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