I trying to add certificate extension to my X509Certificate2 object in pure .NET 4.7.2
I was using BouncyCastle by this method:
private static void AddCdpUrl(X509V3CertificateGenerator certificateGenerator, string cdptUrl)
{
var uriGeneralName = new GeneralName(GeneralName.UniformResourceIdentifier, cdptUrl);
var cdpName = new DistributionPointName(DistributionPointName.FullName, uriGeneralName);
var cdp = new DistributionPoint(cdpName, null, null);
certificateGenerator.AddExtension(X509Extensions.CrlDistributionPoints, false, new CrlDistPoint(new[] { cdp }));
}
Add its works and I get great result:
Now in pure .NET I am using this method:
const string X509CRLDistributionPoints = "2.5.29.31";
certificateRequest.CertificateExtensions.Add(new X509Extension(new Oid(X509CRLDistributionPoints), Encoding.UTF8.GetBytes("http://crl.example.com"), false));
I am missing the sequences for "Distribution Point Name", "Full Name" and "URL="
How can I generate the same result that BouncyCastle does with pure .NET
Thanks
Update (2023-03-20): .NET 7 now has the CertificateRevocationListBuilder method to do this for you (and isn't even limited to a single 119-character value!).
X509Extension cdpExtension =
CertificateRevocationListBuilder.BuildCrlDistributionPointExtension(
new[] { url });
If you only want to write one distribution point, and it's less than or equal to 119 ASCII characters long, and you aren't delegating CRL signing authority to a different certificate:
private static X509Extension MakeCdp(string url)
{
byte[] encodedUrl = Encoding.ASCII.GetBytes(url);
if (encodedUrl.Length > 119)
{
throw new NotSupportedException();
}
byte[] payload = new byte[encodedUrl.Length + 10];
int offset = 0;
payload[offset++] = 0x30;
payload[offset++] = (byte)(encodedUrl.Length + 8);
payload[offset++] = 0x30;
payload[offset++] = (byte)(encodedUrl.Length + 6);
payload[offset++] = 0xA0;
payload[offset++] = (byte)(encodedUrl.Length + 4);
payload[offset++] = 0xA0;
payload[offset++] = (byte)(encodedUrl.Length + 2);
payload[offset++] = 0x86;
payload[offset++] = (byte)(encodedUrl.Length);
Buffer.BlockCopy(encodedUrl, 0, payload, offset, encodedUrl.Length);
return new X509Extension("2.5.29.31", payload, critical: false);
}
Past 119 characters the outer payload length exceeds 0x7F
and then you really start wanting a proper DER encoder. You definitely want one for variable numbers of URLs, or including any of the optional data from the extension.