Explanation of X.509 Certificate DN December 4 th, 2008
BySoloman || 823 views
X.509 uses the DN (distinct name) to uniquely identify an object. Its function is similar to the ID we usually use. However, the difference is that the DN is no longer a digital identifier similar to 123456, multiple fields are used to identify an object, such as "cn =, c = cn". The advantage of this is that it is convenient to match to directory services such as LDAP. Can the DN field be added at will? For example, can I add an ID attribute on a dn such as "cn =, O = "to "cn =, O =, id = 123456?
Hands-on test. First, use Microsoft's xenroll component for testing. Xenroll is an ActiveX control on the Microsoft platform that provides the certificate adding service, such as creating a PKCS #10 certificate request. We can use JavaScript to call this ActiveX Control:
VaR soid = ''; var SDN = 'cn =" ", O =" testing company ", id =" 123456 "'; alert (SDN ); vaR spkcs10 = oxenroll. createpkcs10 (SDN, soid );
The createpkcs10 function accepts two parameters. The first is the string type DN, and the second is the oId used to identify the purpose of the certificate request. Here, we do not care about the purpose of the certificate, so set it to null. After running the code segment through IE, I got an object error. It seems that the DN field cannot be simply added.
So I began to search for X.509 DN information. Originally, the DN attributes in the X.509 Certificate were all ASN1-based encoded objects. That is to say, for the well-known attributes of CN, or CommonName, the program could not obtain them from the certificate, the certificate does not contain information such as Cn = xxx. All fields are represented as OID of the field type. Oid is the unified expression of ASN1 objects. This method adopts a tree structure and is centrally managed by international organizations. If a company wants to add a field type and want to be widely used, it must apply like a management OID organization, just like a common domain name application.
On the www.oid-info.com site, we can query all registered OID information. This website provides two ways to query: Expand the oId levels by tree structure, or directly enter oid such as "2.3.4" for query.
If we expand the oId layer 2.5.4, we will find many common DN fields:
- 2.5.4.3-CommonName
- 2.5.4.4-Surname
- 2.5.4.13-Description
- 2.5.4.10-organizationname
- ......
In this case, we will use the oId form to add the attribute type. For example, I use OID = 2.5.4.888, which is an unregistered OID and can be used for testing:
VaR soid = ''; var SDN = 'cn =" ", O =" test Company ", 2.5.4.888 =" 123456 "'; alert (SDN ); vaR spkcs10 = oxenroll. createpkcs10 (SDN, soid );
After this step is completed, we can find the certificate application from the certificate application library on the machine and view its attributes:
It can be seen that although the property is successfully added with the OID, this OID cannot be translated into a form that is convenient for us to read, just as we can only use IP instead of domain names. To display the certificate ID = instead of 2.5.4.888 =, we must:
- Register 2.5.4.888 with the standard organization as the ID;
- Notify Microsoft to modify its windows program and translate the oId into ID
Obviously, this is very unrealistic.
Next, we will test it with OpenSSL. I chose pyopenssl, an OpenSSL Python packaging Library:
>>> from OpenSSL import crypto>>> req = crypto.X509Req()>>> subject = req.get_subject()>>> setattr(subject, 'CN', 'soloman')>>> setattr(subject, 'ID', '123456')Traceback (most recent call last):File "
", line 1, in
AttributeError: No such attribute>>>
It seems that pyopenssl only knows CN, not ID. Query the source code of pyopenssl:
static intcrypto_X509Name_setattr(crypto_X509NameObj *self, char *name, PyObject *value){int nid;int result;char *buffer;if ((nid = OBJ_txt2nid(name)) == NID_undef){PyErr_SetString(PyExc_AttributeError, "No such attribute");return -1;}......
We can see that when setting the DN for pyopenssl, we first call the obj_txt2nid () function of OpenSSL to translate the object names that are easy to remember into OID, and then translate them into your NID in the OpenSSL program.
Continue to query the source code of OpenSSL. In the objects. h file, we found the definition of all DN fields:
......#define SN_commonName"CN"#define LN_commonName"commonName"#define NID_commonName13#define OBJ_commonNameOBJ_X509,3L#define SN_countryName"C"#define LN_countryName"countryName"#define NID_countryName14#define OBJ_countryNameOBJ_X509,6L#define SN_localityName"L"#define LN_localityName"localityName"#define NID_localityName15#define OBJ_localityNameOBJ_X509,7L......
Here, OpenSSL defines four common DN attributes: Sn, LN, NID, and obj. SN indicates short name, ln indicates long name, which is a two-form OID for us to read. OBJ defines its OID information.
In the OpenSSL/crypto/ASN1/a_strnid.c file, the DN field supported and translated by OpenSSL is bound:
static ASN1_STRING_TABLE tbl_standard[] = {{NID_commonName,1, ub_common_name, DIRSTRING_TYPE, 0},{NID_countryName,2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},{NID_localityName,1, ub_locality_name, DIRSTRING_TYPE, 0},{NID_stateOrProvinceName,1, ub_state_name, DIRSTRING_TYPE, 0},{NID_organizationName,1, ub_organization_name, DIRSTRING_TYPE, 0},{NID_organizationalUnitName,1, ub_organization_unit_name, DIRSTRING_TYPE, 0},{NID_pkcs9_emailAddress,1, ub_email_address, B_ASN1_IA5STRING, STABLE_NO_MASK},{NID_pkcs9_unstructuredName,1, -1, PKCS9STRING_TYPE, 0},{NID_pkcs9_challengePassword,1, -1, PKCS9STRING_TYPE, 0},{NID_pkcs9_unstructuredAddress,1, -1, DIRSTRING_TYPE, 0},{NID_givenName,1, ub_name, DIRSTRING_TYPE, 0},{NID_surname,1, ub_name, DIRSTRING_TYPE, 0},{NID_initials,1, ub_name, DIRSTRING_TYPE, 0},{NID_serialNumber,1, ub_serial_number, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},{NID_friendlyName,-1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},{NID_name,1, ub_name, DIRSTRING_TYPE, 0},{NID_dnQualifier,-1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},{NID_domainComponent,1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK},{NID_ms_csp_name,-1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}};
We can see that if we want our OpenSSL-based program to support a custom attribute, we need to modify the OpenSSL source code, add the "name-oid" binding of our new field (long name can be used only), and re-compile OpenSSL and our program so that it can use new attributes.
Let's look back at why the Standardization Organization didn't provide us with a property like id? This is because dn is used as an ID. It binds some attributes to identify an object. If there is another common ID attribute, the logic will conflict. Of course, for specific applications, you can register a special ID attribute, such as openid, but this requires a strong company to register and promote it.
However, in practical applications, when we want to bind the certificate system to an ID in a particular application, and do not have the ability to register and promote oid to international organizations, we can use the existing attributes to implement it. For example, we can design two solutions for this requirement:
- Solution 1: Cn = @ 123456
- Solution 2: Cn = 123456, surname = old, givenname =
- Solution 3: Cn = 123456, name = old office
- Solution 4: Cn = old office, description = 123456
Solution 1: Combine the user's name and ID into CN in a certain way, and then parse the ID in the application. This method is not very easy for users to write, when filling in the certificate application materials, you must pay attention to the compliance with this specification.
The concept of solution 2 and 3 is to use CN to record IDs. After all, the common name can be defined as needed. The user name is specified by Surname + givenname or name. This method has passed the OpenSSL test:
>>> req = crypto.X509Req()>>> subject = req.get_subject()>>> setattr(subject, 'surname', 'Lao')>>> setattr(subject, 'givenName', 'Suo')>>> setattr(subject, 'name', 'Lao Suo')
However, xenroll does not support Surname + givenname or name attributes. It is described in this document that the X.500 specification is supported, not the X.509 specification.
Solution 4: The description attribute is used to record information related to a specific application, such as our ID. This method passes the openssll test:
>>> req = crypto.X509Req()>>> subject = req.get_subject()>>> setattr(subject, 'CN', 'Lao Suo')>>> setattr(subject, 'description', '123456')
And xenroll testing:
Original http://blog.ipattern.org/archives/653