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