1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.asn1.x509; 2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 34c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.io.IOException; 44c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.ASN1InputStream; 64c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1ObjectIdentifier; 74c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1Primitive; 8c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.asn1.DERPrintableString; 9b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.util.Strings; 10b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 11b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam/** 12b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * It turns out that the number of standard ways the fields in a DN should be 13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * encoded into their ASN.1 counterparts is rapidly approaching the 14b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * number of machines on the internet. By default the X509Name class 15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * will produce UTF8Strings in line with the current recommendations (RFC 3280). 16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * <p> 17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * An example of an encoder look like below: 18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * <pre> 19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * public class X509DirEntryConverter 20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * extends X509NameEntryConverter 21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * { 224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom * public ASN1Primitive getConvertedValue( 234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom * ASN1ObjectIdentifier oid, 24b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * String value) 25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * { 26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * if (str.length() != 0 && str.charAt(0) == '#') 27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * { 28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * return convertHexEncoded(str, 1); 29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * } 30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * if (oid.equals(EmailAddress)) 31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * { 32b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * return new DERIA5String(str); 33b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * } 34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * else if (canBePrintable(str)) 35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * { 36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * return new DERPrintableString(str); 37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * } 38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * else if (canBeUTF8(str)) 39b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * { 40b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * return new DERUTF8String(str); 41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * } 42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * else 43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * { 44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * return new DERBMPString(str); 45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * } 46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * } 47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * } 48b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 49b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic abstract class X509NameEntryConverter 50b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{ 51b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Convert an inline encoded hex string rendition of an ASN.1 53b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * object back into its corresponding ASN.1 object. 54b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 55b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param str the hex encoded object 56b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param off the index at which the encoding starts 57b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @return the decoded object 58b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom protected ASN1Primitive convertHexEncoded( 60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam String str, 61b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int off) 62b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throws IOException 63b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 64b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam str = Strings.toLowerCase(str); 65b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] data = new byte[(str.length() - off) / 2]; 66b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam for (int index = 0; index != data.length; index++) 67b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 68b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam char left = str.charAt((index * 2) + off); 69b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam char right = str.charAt((index * 2) + off + 1); 70b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 71b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (left < 'a') 72b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 73b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam data[index] = (byte)((left - '0') << 4); 74b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 75b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam else 76b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 77b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam data[index] = (byte)((left - 'a' + 10) << 4); 78b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 79b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (right < 'a') 80b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 81b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam data[index] |= (byte)(right - '0'); 82b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 83b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam else 84b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 85b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam data[index] |= (byte)(right - 'a' + 10); 86b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 87b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 88b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 89b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam ASN1InputStream aIn = new ASN1InputStream(data); 90b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 91b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return aIn.readObject(); 92b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 93b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 94b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * return true if the passed in String can be represented without 96b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * loss as a PrintableString, false otherwise. 97b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 98b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam protected boolean canBePrintable( 99b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam String str) 100b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 101c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom return DERPrintableString.isPrintableString(str); 102b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 103b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 104b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Convert the passed in String value into the appropriate ASN.1 106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * encoded object. 107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param oid the oid associated with the value in the DN. 109b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param value the value of the particular DN component. 110b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @return the ASN.1 equivalent for the value. 111b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 1124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom public abstract ASN1Primitive getConvertedValue(ASN1ObjectIdentifier oid, String value); 113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam} 114