153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giropackage org.bouncycastle.asn1.x500.style; 253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giroimport java.io.IOException; 453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giroimport java.util.Enumeration; 553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giroimport java.util.Hashtable; 653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giroimport org.bouncycastle.asn1.ASN1Encodable; 853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giroimport org.bouncycastle.asn1.ASN1ObjectIdentifier; 9bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giroimport org.bouncycastle.asn1.ASN1ParsingException; 1053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giroimport org.bouncycastle.asn1.DERUTF8String; 1153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giroimport org.bouncycastle.asn1.x500.AttributeTypeAndValue; 1253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giroimport org.bouncycastle.asn1.x500.RDN; 1353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giroimport org.bouncycastle.asn1.x500.X500Name; 1453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giroimport org.bouncycastle.asn1.x500.X500NameStyle; 1553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 1653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro/** 1753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * This class provides some default behavior and common implementation for a 1853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * X500NameStyle. It should be easily extendable to support implementing the 1953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * desired X500NameStyle. 2053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro */ 2153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giropublic abstract class AbstractX500NameStyle 2253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro implements X500NameStyle 2353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro{ 2453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 2553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro /** 2653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * Tool function to shallow copy a Hashtable. 2753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * 2853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * @param paramsMap table to copy 2953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * @return the copy of the table 3053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro */ 3153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro public static Hashtable copyHashTable(Hashtable paramsMap) 3253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 3353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro Hashtable newTable = new Hashtable(); 3453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 3553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro Enumeration keys = paramsMap.keys(); 3653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro while (keys.hasMoreElements()) 3753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 3853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro Object key = keys.nextElement(); 3953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro newTable.put(key, paramsMap.get(key)); 4053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 4153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 4253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro return newTable; 4353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 4453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 4553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro private int calcHashCode(ASN1Encodable enc) 4653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 4753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro String value = IETFUtils.valueToString(enc); 4853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro value = IETFUtils.canonicalize(value); 4953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro return value.hashCode(); 5053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 5153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 5253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro public int calculateHashCode(X500Name name) 5353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 5453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro int hashCodeValue = 0; 5553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro RDN[] rdns = name.getRDNs(); 5653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 5753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro // this needs to be order independent, like equals 5853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro for (int i = 0; i != rdns.length; i++) 5953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 6053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro if (rdns[i].isMultiValued()) 6153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 6253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro AttributeTypeAndValue[] atv = rdns[i].getTypesAndValues(); 6353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 6453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro for (int j = 0; j != atv.length; j++) 6553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 6653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro hashCodeValue ^= atv[j].getType().hashCode(); 6753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro hashCodeValue ^= calcHashCode(atv[j].getValue()); 6853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 6953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 7053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro else 7153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 7253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro hashCodeValue ^= rdns[i].getFirst().getType().hashCode(); 7353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro hashCodeValue ^= calcHashCode(rdns[i].getFirst().getValue()); 7453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 7553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 7653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 7753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro return hashCodeValue; 7853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 7953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 8053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 8153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro /** 8253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * For all string values starting with '#' is assumed, that these are 8353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * already valid ASN.1 objects encoded in hex. 8453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * <p> 8553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * All other string values are send to 8653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * {@link AbstractX500NameStyle#encodeStringValue(ASN1ObjectIdentifier, String)}. 8753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * </p> 8853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * Subclasses should overwrite 8953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * {@link AbstractX500NameStyle#encodeStringValue(ASN1ObjectIdentifier, String)} 9053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * to change the encoding of specific types. 9153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * 9253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * @param oid the DN name of the value. 9353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * @param value the String representation of the value. 9453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro */ 9553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value) 9653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 9753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro if (value.length() != 0 && value.charAt(0) == '#') 9853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 9953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro try 10053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 10153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro return IETFUtils.valueFromHexString(value, 1); 10253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 10353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro catch (IOException e) 10453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 105bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro throw new ASN1ParsingException("can't recode value for oid " + oid.getId()); 10653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 10753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 10853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 10953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro if (value.length() != 0 && value.charAt(0) == '\\') 11053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 11153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro value = value.substring(1); 11253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 11353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 11453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro return encodeStringValue(oid, value); 11553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 11653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 11753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro /** 11853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * Encoded every value into a UTF8String. 11953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * <p> 12053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * Subclasses should overwrite 12153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * this method to change the encoding of specific types. 12253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * </p> 12353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * 12453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * @param oid the DN oid of the value 12553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * @param value the String representation of the value 12653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * @return a the value encoded into a ASN.1 object. Never returns <code>null</code>. 12753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro */ 12853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro protected ASN1Encodable encodeStringValue(ASN1ObjectIdentifier oid, String value) 12953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 13053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro return new DERUTF8String(value); 13153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 13253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 13353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro public boolean areEqual(X500Name name1, X500Name name2) 13453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 13553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro RDN[] rdns1 = name1.getRDNs(); 13653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro RDN[] rdns2 = name2.getRDNs(); 13753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 13853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro if (rdns1.length != rdns2.length) 13953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 14053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro return false; 14153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 14253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 14353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro boolean reverse = false; 14453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 14553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro if (rdns1[0].getFirst() != null && rdns2[0].getFirst() != null) 14653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 14753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro reverse = !rdns1[0].getFirst().getType().equals(rdns2[0].getFirst().getType()); // guess forward 14853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 14953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 15053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro for (int i = 0; i != rdns1.length; i++) 15153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 15253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro if (!foundMatch(reverse, rdns1[i], rdns2)) 15353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 15453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro return false; 15553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 15653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 15753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 15853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro return true; 15953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 16053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 16153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro private boolean foundMatch(boolean reverse, RDN rdn, RDN[] possRDNs) 16253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 16353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro if (reverse) 16453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 16553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro for (int i = possRDNs.length - 1; i >= 0; i--) 16653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 16753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i])) 16853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 16953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro possRDNs[i] = null; 17053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro return true; 17153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 17253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 17353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 17453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro else 17553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 17653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro for (int i = 0; i != possRDNs.length; i++) 17753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 17853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i])) 17953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 18053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro possRDNs[i] = null; 18153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro return true; 18253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 18353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 18453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 18553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 18653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro return false; 18753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 18853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro 18953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro protected boolean rdnAreEqual(RDN rdn1, RDN rdn2) 19053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro { 19153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro return IETFUtils.rDNAreEqual(rdn1, rdn2); 19253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro } 19353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro} 194