Search code examples
javabouncycastledistinguishedname

How to validate Distinguish Name(DN) in Java?


I am trying to validate DN in java. So far I have tried to validate it using Bouncy castle libry

private boolean isValidDn(String dn) {
    try {
        X509Name name = new X509Name(dn);
        return true;
    } catch (IllegalArgumentException e) {

    }
    return false;
}

This code is working but the problem is this code allows to have multiple CN.

For example: this code return true for CN=first,CN=second,ou=org,ou=org2,c=US

But I want validation that return true only if there is one cn,ou,o,c etc..

Any help would be appreciated.


Solution

  • If you use the following enum, you should be able to iterate every element possible for an X500Name or X509Name.

    public enum MyBCStyle {
    
        /**
         * country code - StringType(SIZE(2))
         */
        C(BCStyle.C),
    
        /**
         * organization - StringType(SIZE(1..64))
         */
        O(BCStyle.O ),
    
        /**
         * organizational unit name - StringType(SIZE(1..64))
         */
        OU(BCStyle.OU),
    
        /**
         * Title
         */
        T(BCStyle.T ),
    
        /**
         * common name - StringType(SIZE(1..64))
         */
        CN(BCStyle.CN ),
    
        /**
         * device serial number name - StringType(SIZE(1..64))
         */
        SN(BCStyle.SN ),
    
        /**
         * street - StringType(SIZE(1..64))
         */
        STREET(BCStyle.STREET ),
    
        /**
         * device serial number name - StringType(SIZE(1..64))
         */
        SERIALNUMBER(BCStyle.SERIALNUMBER),
    
        /**
         * locality name - StringType(SIZE(1..64))
         */
        L(BCStyle.L ),
    
        /**
         * state, or province name - StringType(SIZE(1..64))
         */
        ST(BCStyle.ST ),
    
        /**
         * Naming attributes of type X520name
         */
        SURNAME(BCStyle.SURNAME ),
        GIVENNAME(BCStyle.GIVENNAME ),
        INITIALS(BCStyle.INITIALS ),
        GENERATION(BCStyle.GENERATION ),
        UNIQUE_IDENTIFIER(BCStyle.UNIQUE_IDENTIFIER ),
    
        /**
         * businessCategory - DirectoryString(SIZE(1..128)
         */
        BUSINESS_CATEGORY(BCStyle.BUSINESS_CATEGORY ),
    
        /**
         * postalCode - DirectoryString(SIZE(1..40)
         */
        POSTAL_CODE(BCStyle.POSTAL_CODE ),
    
        /**
         * dnQualifier - DirectoryString(SIZE(1..64)
         */
        DN_QUALIFIER(BCStyle.DN_QUALIFIER ),
    
        /**
         * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64)
         */
        PSEUDONYM(BCStyle.PSEUDONYM ),
    
    
        /**
         * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z
         */
        DATE_OF_BIRTH(BCStyle.DATE_OF_BIRTH ),
    
        /**
         * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128)
         */
        PLACE_OF_BIRTH(BCStyle.PLACE_OF_BIRTH ),
    
        /**
         * RFC 3039 Gender - PrintableString (SIZE(1)) -- "M", "F", "m" or "f"
         */
        GENDER(BCStyle.GENDER ),
    
        /**
         * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
         * codes only
         */
        COUNTRY_OF_CITIZENSHIP(BCStyle.COUNTRY_OF_CITIZENSHIP ),
    
        /**
         * RFC 3039 CountryOfResidence - PrintableString (SIZE (2)) -- ISO 3166
         * codes only
         */
        COUNTRY_OF_RESIDENCE(BCStyle.COUNTRY_OF_RESIDENCE ),
    
    
        /**
         * ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64)
         */
        NAME_AT_BIRTH(BCStyle.NAME_AT_BIRTH ),
    
        /**
         * RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF
         * DirectoryString(SIZE(1..30))
         */
        POSTAL_ADDRESS(BCStyle.POSTAL_ADDRESS ),
    
        /**
         * RFC 2256 dmdName
         */
        DMD_NAME(BCStyle.DMD_NAME ),
    
        /**
         * id-at-telephoneNumber
         */
        TELEPHONE_NUMBER(BCStyle.TELEPHONE_NUMBER),
    
        /**
         * id-at-name
         */
        NAME(BCStyle.NAME),
    
        /**
         * Email address (RSA PKCS#9 extension) - IA5String.
         * <p>Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
         */
        EmailAddress(BCStyle.EmailAddress),
    
        /**
         * more from PKCS#9
         */
        UnstructuredName(BCStyle.UnstructuredName),
        UnstructuredAddress(BCStyle.UnstructuredAddress),
        E(BCStyle.E),
        DC(BCStyle.DC),
    
        /**
         * LDAP User id.
         */
        UID(BCStyle.UID );
    
        private ASN1ObjectIdentifier identifier;
    
        public ASN1ObjectIdentifier getIdentifier() {
            return identifier;
        }
    
        private MyBCStyle(ASN1ObjectIdentifier asn1ObjectIdentifier) {
            this.identifier = asn1ObjectIdentifier;
        }
    }
    

    This way, you can do

    for(MyBCStyle bcStyle : MyBCStyle.values()) {
        if(x500name.getRDNs(bcStyle.getIdentifier()).length > 1) {
            throw new IllegalArgumentException("Multiple " + bcStyle.name() + " was found.");
        }
    }