1package org.bouncycastle.asn1; 2 3import java.io.IOException; 4 5import org.bouncycastle.util.Arrays; 6import org.bouncycastle.util.Strings; 7 8/** 9 * DER NumericString object - this is an ascii string of characters {0,1,2,3,4,5,6,7,8,9, }. 10 */ 11public class DERNumericString 12 extends ASN1Primitive 13 implements ASN1String 14{ 15 private byte[] string; 16 17 /** 18 * return a Numeric string from the passed in object 19 * 20 * @exception IllegalArgumentException if the object cannot be converted. 21 */ 22 public static DERNumericString getInstance( 23 Object obj) 24 { 25 if (obj == null || obj instanceof DERNumericString) 26 { 27 return (DERNumericString)obj; 28 } 29 30 if (obj instanceof byte[]) 31 { 32 try 33 { 34 return (DERNumericString)fromByteArray((byte[])obj); 35 } 36 catch (Exception e) 37 { 38 throw new IllegalArgumentException("encoding error in getInstance: " + e.toString()); 39 } 40 } 41 42 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); 43 } 44 45 /** 46 * return an Numeric String from a tagged object. 47 * 48 * @param obj the tagged object holding the object we want 49 * @param explicit true if the object is meant to be explicitly 50 * tagged false otherwise. 51 * @exception IllegalArgumentException if the tagged object cannot 52 * be converted. 53 */ 54 public static DERNumericString getInstance( 55 ASN1TaggedObject obj, 56 boolean explicit) 57 { 58 ASN1Primitive o = obj.getObject(); 59 60 if (explicit || o instanceof DERNumericString) 61 { 62 return getInstance(o); 63 } 64 else 65 { 66 return new DERNumericString(ASN1OctetString.getInstance(o).getOctets()); 67 } 68 } 69 70 /** 71 * basic constructor - with bytes. 72 */ 73 DERNumericString( 74 byte[] string) 75 { 76 this.string = string; 77 } 78 79 /** 80 * basic constructor - without validation.. 81 */ 82 public DERNumericString( 83 String string) 84 { 85 this(string, false); 86 } 87 88 /** 89 * Constructor with optional validation. 90 * 91 * @param string the base string to wrap. 92 * @param validate whether or not to check the string. 93 * @throws IllegalArgumentException if validate is true and the string 94 * contains characters that should not be in a NumericString. 95 */ 96 public DERNumericString( 97 String string, 98 boolean validate) 99 { 100 if (validate && !isNumericString(string)) 101 { 102 throw new IllegalArgumentException("string contains illegal characters"); 103 } 104 105 this.string = Strings.toByteArray(string); 106 } 107 108 public String getString() 109 { 110 return Strings.fromByteArray(string); 111 } 112 113 public String toString() 114 { 115 return getString(); 116 } 117 118 public byte[] getOctets() 119 { 120 return Arrays.clone(string); 121 } 122 123 boolean isConstructed() 124 { 125 return false; 126 } 127 128 int encodedLength() 129 { 130 return 1 + StreamUtil.calculateBodyLength(string.length) + string.length; 131 } 132 133 void encode( 134 ASN1OutputStream out) 135 throws IOException 136 { 137 out.writeEncoded(BERTags.NUMERIC_STRING, string); 138 } 139 140 public int hashCode() 141 { 142 return Arrays.hashCode(string); 143 } 144 145 boolean asn1Equals( 146 ASN1Primitive o) 147 { 148 if (!(o instanceof DERNumericString)) 149 { 150 return false; 151 } 152 153 DERNumericString s = (DERNumericString)o; 154 155 return Arrays.areEqual(string, s.string); 156 } 157 158 /** 159 * Return true if the string can be represented as a NumericString ('0'..'9', ' ') 160 * 161 * @param str string to validate. 162 * @return true if numeric, fale otherwise. 163 */ 164 public static boolean isNumericString( 165 String str) 166 { 167 for (int i = str.length() - 1; i >= 0; i--) 168 { 169 char ch = str.charAt(i); 170 171 if (ch > 0x007f) 172 { 173 return false; 174 } 175 176 if (('0' <= ch && ch <= '9') || ch == ' ') 177 { 178 continue; 179 } 180 181 return false; 182 } 183 184 return true; 185 } 186} 187