How to issue certificate to an entity with custom DN format? - certificate

In our application we generate certificates for internal entities like platform and user. Our internal entities are identified by custom DNs:
Platform DN: p=platformName
User DN: cn=userName,p=platformName
We tried to generate X.509 certificate for platform or user with popular tools like openssl, keytool, implementation of javax.security (BouncyCastle), e.g.:
keytool -genkey -dname "p=platformName" -alias platformName
However, those tools do not accept/recognize keyword "P" or require certain keywords like "CN" in certificate subject DN.
How to issue certificate to an entity with custom DN format?
Note: We do not need to have DNs containing standard keywords (CN, OU, etc.), because all certificates will be for internal use of our products (will not be validated by 3rd party or included in certificate chain).

We do not need to have DNs containing standard keywords (CN, OU, etc.)
How to issue certificate to an entity with custom DN format?
The attributes or fields displayed are a presentation level detail. There is no distinguished DN field per se. The fields used to form the DN are a mashup of other attributes and are arbitrarily chosen. The common ones are C, O, OU, CN, etc.
Attributes or fields like C, O, OU, CN have well known OIDs associated with them. There are other OIDs you can use that are recognized by tools. For example, the ITU's X.520 list hundreds of them. There are other standards that declare them too. For example, the email address attribute is from PKCS 9 and has an OID of 1.2.840.113549.1.9.1.
As Burhan Khalid stated, you can even add your own name/value pairs by making up OIDs (some hand waiving). However, other presentation tools won't know how to display them. That is, they won't know the "friendly name".
Because other tools don't recognize your OID for platform (or "p=..."), that's why you are getting ... those tools do not accept/recognize keyword "P". The tools don't know how to deal with your custom attributes.

I can only speak for openssl, as I am not familiar with other tools.
From the openssl docs
ASN1 OBJECT CONFIGURATION MODULE
This module has the name oid_section. The value of this variable
points to a section containing name value pairs of OIDs: the name is
the OID short and long name, the value is the numerical form of the
OID. Although some of the openssl utility sub commands already have
their own ASN1 OBJECT section functionality not all do. By using the
ASN1 OBJECT configuration module all the openssl utility sub commands
can see the new objects as well as any compliant applications.
So what you have to do is create these oids in /etc/openssl.conf or wherever the file is for your platform, then openssl will not give you the Subject attribute p has no known NID, skipped message, which I suspect is what you are getting now.

Related

How to Parse P12 File

I'm writing a parse tool to extract each field of P12 file in C language, OpenSSL is too huge for my project.
After reading PKCS# series documents and ASN.1 documents, I understand the basic parse step.
I use OpenSSL to generate a self-signed P12 file,there're some questions during parsing:
Why Certificate is not stored in a Safebag, in my case it's stored in EncryptedData field?
What does the localKeyId attribute mean? it has an OctetString, what is the OctectString used for?
Why the contentType of encryptedContentInfo is id-data? I think it should be id-encryptedData. In my case, Certificate is stored in encryptedContentInfo field.
Thanks,
CZ
The PKCS12 standard also available as rfc7292 formally allows a very wide range and combination of options, but in practice only a few of these options are used. There are basically 3 levels:
the file has type/structure PFX consisting mostly of a PKCS7/CMS ContentInfo which theoretically can be 'data' or 'signed-data' but in practice is always the former (with the nominally optional MacData appended) and contains
'AuthenticatedSafe' which is a sequence of one or more (almost always more) ContentInfo(s) each of which (separately) may be encrypted or not and contains (after decryption if applicable)
a sequence of one of more 'bag'(s) each of which contains actual data of a certain type such as an encrypted privatekey or a certificate along with optional attributes.
In practice there is usually:
one CI (at level 2) with PKCS7/CMS type 'encrypted-data' using a very weak algorithm (RC2-40) containing one or more CertBag(s) each containing a cert plus any attributes for it, and
one or more CI(s) (each) with type 'data' containing a PKCS8ShroudedKeyBag containing an encrypted privatekey (using PKCS8 as stated) usually using a strong algorithm commonly 3DES, plus attributes.
My answer here shows the first levels of parsing to find the encryption details; further parsing requires decryption as shown (for a specific case) in my answer here.
As mentioned all bags can have attributes; in practice depending on the implementation some bags may have the 'friendlyName' attribute with a value intended for people to use, and if a matching privatekey and cert are present they both have a 'localKeyId' attribute with the same value to tie them together, as explained in my answer to a different but related Q. 'localKeyId' is not intended for people to use and you should not normally present it to people.

Correct way to tag x509 certificate with identity of user that created it?

I have a Windows service that processes Certificate Signing Requests to make Certificates. It also makes self signed certificates (Certificate Authorities) on request by Windows users. In either case, I want to put the user account name (the NT Account string like 'domain\user') from the user who made the request to make the certificate in the finished certificate so that it is straightforward to track who created what.
Where is the best place to stick a user account string in a certificate? The first thing that came to mind is a custom extension. Does that make the most sense? Or perhaps an alternate field in the subject? I do not know if this is at all a common practice.
If you aren't committed to using the NT Account format, you could consider the emailAddress attribute in the certificate subjectName. Simply change Test\Bloggs to bloggs#test.
There is also the pseudonym attribute that could be used. However, while OpenSSL displays this attribute's name correctly, Windows shows it as 2.5.4.65 which may not be what you want.
In theory, the subjectAltName extension could also be used to store this. There is a otherName field, that could be used. However, OpenSSL displays a certificate as follows:
X509v3 Subject Alternative Name:
DNS:test.example.org, othername:<unsupported>
While Windows displays:
DNS Name=test.example.org
Other Name:
1.3.6.1.4.1.1=0c 0b 54 45 53 54 5c 42 6c 6f 67 67 73
Obviously, neither are any good to you.
Therefore, be pragmatic - either use the pseudonym and live with the way Windows displays it, or be even more pragmatic and hijack the OrgnaizationalUnitName (OU) attribute and use that. You can have multiple OUs therefore there wouldn't be a need to sacrifice any current OUs you may have. Digicert, Microsoft and Verisign (and no doubt, others) use the OU as an additional text field without any harm. It may not be 100% standard compliant, but it works.
If you do go down the latter route and you are using name constraints, make sure that this additional OU is first in the list when creating your signing request. That is, it doesn't break the order of the name constraint.

Signature verification using only a hashed/encoded message

Is there any way to verify the OpenSSL signature using only {signature,hashed message} pair, skipping the original file to be presented for verification?
I need to verify the signature with only {signature,hashed message} pair remotely so using the original file is cumbersome specially when its very large.
Is there any way to verify the OpenSSL signature using only hash value and without needing the original file?
Yes, but there are strings attached.
The scheme which requires the original message to be presented to the verifying function is a Signature Scheme with Appendix (SSA). A scheme like the old PKCS #1.0 signing is an example of it.
The scheme which does not require the original message is a Signature Scheme with Recovery (PSSR). In a PSSR, the encoded message is part of the signature and masked. A scheme like the new PKCS #2.0 PSSR signing is an example of it.
There are no schemes that take just a hash, as far as I know. You have to have the {message,signature} pair. Allowing the message to be disgorged from the signing or verification can be a security violation.
OpenSSL provides both of them, as does most other security libraries, like Botan, Crypto++, NSS, etc.
Also see RSA signature on TLS on Information Security Stack Exchange.
I have been trying to verify the signature with hash value remotely so using the original file is cumbersome specially when its very large.
That's the insecure thing signature schemes want to avoid....

How do I verify a root DNS trust anchor?

I am trying to verify root Key Signing Key (KSK) against the trust anchor (Kjqmt7v.crt) downloaded from here. I am getting root KSK using the Net::DNS module.
I am very confused at present on how to verify that both are the same. I tried to convert the .crt file to a Keyset object, but it is resulting in an error.
This is my code.
#!/usr/bin/perl
use strict;
use warnings;
use Net::DNS::Keyset;
my $keyset = Net::DNS::Keyset->new('Kjqmt7v.crt');
$keyset->print;
This is the error
We expected a match RDATA
0��0���0 *�H�� 0K10 U
this Should not happen
at a.pl line 5
I am very confused and therefore unable to provide any proper code, as I have no idea how to start. Pointing me in the right direction would be very helpful.
I want a way to verify trust anchor against the KSK that I am getting from root DNS servers. If there is any other way to do that please update me.
You seem to have misunderstood what's in the files IANA provides. None of them except the public root key itself is actually DNSSEC data. The Kjqmt7v.crt file, for example, is an X.509 certificate in DER format (so it's no wonder that Net::DNS::Keyset chokes on it). If you look at it (with the openssl x509 command, for example), you can see that included in its DN field is the textual representation of a DS record for the root KSK. So if you verify that certificate, you know that DS is genuine, and you can use that to verify the DNSKEY.
Another alternative available at the same URL, which is probably easier to use for most people, is a DS for the KSK in XML format, with a detached PGP signature. Verify the signature, use the data in the XML file to build a proper DS record in your favorite programming language, and then you can use that to verify the KSK DNSKEY record.

Notes Formula Language "#ValidateInternetAddress" Failing to Validate Properly?

We are using the following validation code to check for a valid email address formatting on a web form driving by Lotus Notes:
#If((#ValidateInternetAddress([Address821]; #ThisValue)!=""
| #Contains(#ThisValue; "\"") | #Contains(#ThisValue; "'")
| #Contains(#ThisValue; " ")); "Please include a valid email address."; "");
Currently, if a user enters any of the following inputs, the verification throws the error message:
empty field
" ", ', or / character
the domain portion of the email: "test.com"
only #
However, if a user enters test#test the form validates this as a valid email address format.
Is this format considered to be a valid "Address821" format? Or is the form validating an incorrect format as a valid email address?
Yes, it technically is valid address syntax, both by past and current standards.
The language in the RFC's has evolved over time:
RFC-821: 3.7. DOMAINS
Domains are a recently introduced concept in the ARPA Internet mail
system. The use of domains changes the address space from a flat
global space of simple character string host names to a hierarchically
structured rooted tree of global addresses. The host name is replaced
by a domain and host designator which is a sequence of domain element
strings separated by periods with the understanding that the domain
elements are ordered from the most specific to the most general.
This isn't very precise. It doesn't explicitly say that there must be more than one element in the domain name, but it doesn't explicitly prohibit it either. But this was obsoleted by:
RFC-2821: 2.3.5 Domain
A domain (or domain name) consists of one or more dot-separated
components.
...
The domain name, as described in this document and in [22], is the entire, fully-qualified name (often referred to as an "FQDN"). A domain name that is not in FQDN form is no more than a local alias. Local aliases MUST NOT appear in any SMTP transaction.
This seems to be saying that it's illegal, but actually it isn't saying that. I'll explain below, but first let's have a look at the draft standard that is intended to obsolete 2821, and which clarifies things a great deal:
RFC-5321 2.3.5 Domain Names
A domain name (or often just a "domain") consists of one or more components, separated by dots if more than one appears. In the case of a top-level domain used by itself in an email address, a single string is used without any dots. This makes the requirement, described in more detail below, that only fully-qualified domain names appear in SMTP transactions on the public Internet, particularly important where top-level domains are involved.
...
The domain name, as described in this document and in RFC 1035 [2], is the entire, fully-qualified name (often referred to as an "FQDN"). A domain name that is not in FQDN form is no more than a local alias. Local aliases MUST NOT appear in any SMTP transaction.
What this makes clear is that no dot is required in a domain name, as long as it is a top level domain.
#ValidateInternetAddress cannot reasonably know whether "test" is a valid top level domain. Even if IBM programmed in the list of approved public TLD's (which IMHO would be a bad idea since it can and does change), you can in fact set up a private TLD called "test" in your own DNS. That's not the same thing as a "local alias" which the standard does prohibit. There's no rule against actual TLDs.
And for that matter, it could even be a public TLD. Theoretically, the owner of a TLD could set up a mail server for the TLD. I.e., President#US, or Queen#UK. Not likely, but possible in those cases, but with all the new TLD's coming on line, I wouldn't be surprised if some of the registrars are using info#domain.
I guess theoretically #ValidateInternetAddress could make the DNS call to check whether it can resolve "test" as a TLD, but the doc for that function only says that it checks the syntax of the address, and the existence of the TLD is a semantic issue, not a syntax issue.