DeltaCertificateTool
General tool for handling the extension described in:
https://datatracker.ietf.org/doc/draft-bonnell-lamps-chameleon-certs/
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using System;
namespace Org.BouncyCastle.X509
{
public class DeltaCertificateTool
{
public static Org.BouncyCastle.Asn1.X509.Extension CreateDeltaCertificateExtension(bool isCritical, X509CertificateStructure deltaCert)
{
DeltaCertificateDescriptor deltaCertificateDescriptor = new DeltaCertificateDescriptor(deltaCert.SerialNumber, deltaCert.SignatureAlgorithm, deltaCert.Issuer, deltaCert.Validity, deltaCert.Subject, deltaCert.SubjectPublicKeyInfo, deltaCert.Extensions, deltaCert.Signature);
DerObjectIdentifier dRAFT_DeltaCertificateDescriptor = X509Extensions.DRAFT_DeltaCertificateDescriptor;
DerBoolean instance = DerBoolean.GetInstance(isCritical);
DerOctetString extnValue = DerOctetString.WithContents(deltaCertificateDescriptor.GetEncoded("DER"));
return new Org.BouncyCastle.Asn1.X509.Extension(dRAFT_DeltaCertificateDescriptor, instance, extnValue);
}
public static Org.BouncyCastle.Asn1.X509.Extension CreateDeltaCertificateExtension(bool isCritical, X509Certificate deltaCert)
{
return CreateDeltaCertificateExtension(isCritical, deltaCert.CertificateStructure);
}
public static X509CertificateStructure ExtractDeltaCertificate(TbsCertificateStructure baseTbsCert)
{
X509Extensions extensions = baseTbsCert.Extensions;
X509Extension extension = extensions.GetExtension(X509Extensions.DRAFT_DeltaCertificateDescriptor);
if (extension == null)
throw new InvalidOperationException("no deltaCertificateDescriptor present");
DeltaCertificateDescriptor instance = DeltaCertificateDescriptor.GetInstance(extension.GetParsedValue());
DerInteger versionNumber = baseTbsCert.VersionNumber;
DerInteger serialNumber = instance.SerialNumber;
AlgorithmIdentifier algorithmIdentifier = instance.Signature ?? baseTbsCert.Signature;
X509Name issuer = instance.Issuer ?? baseTbsCert.Issuer;
Validity validity = instance.Validity ?? baseTbsCert.Validity;
X509Name subject = instance.Subject ?? baseTbsCert.Subject;
SubjectPublicKeyInfo subjectPublicKeyInfo = instance.SubjectPublicKeyInfo;
X509Extensions extensions2 = ExtractDeltaExtensions(instance.Extensions, extensions);
return new X509CertificateStructure(new TbsCertificateStructure(versionNumber, serialNumber, algorithmIdentifier, issuer, validity, subject, subjectPublicKeyInfo, null, null, extensions2), algorithmIdentifier, instance.SignatureValue);
}
public static X509Certificate ExtractDeltaCertificate(X509Certificate baseCert)
{
return new X509Certificate(ExtractDeltaCertificate(baseCert.TbsCertificate));
}
public static DeltaCertificateDescriptor TrimDeltaCertificateDescriptor(DeltaCertificateDescriptor descriptor, TbsCertificateStructure tbsCertificate, X509Extensions tbsExtensions)
{
DerInteger serialNumber = descriptor.SerialNumber;
AlgorithmIdentifier algorithmIdentifier = descriptor.Signature;
if (algorithmIdentifier != null && algorithmIdentifier.Equals(tbsCertificate.Signature))
algorithmIdentifier = null;
X509Name x509Name = descriptor.Issuer;
if (x509Name != null && x509Name.Equals(tbsCertificate.Issuer))
x509Name = null;
Validity validity = descriptor.Validity;
if (validity != null && validity.Equals(tbsCertificate.Validity))
validity = null;
X509Name x509Name2 = descriptor.Subject;
if (x509Name2 != null && x509Name2.Equals(tbsCertificate.Subject))
x509Name2 = null;
SubjectPublicKeyInfo subjectPublicKeyInfo = descriptor.SubjectPublicKeyInfo;
X509Extensions x509Extensions = descriptor.Extensions;
if (x509Extensions != null) {
X509ExtensionsGenerator x509ExtensionsGenerator = new X509ExtensionsGenerator();
foreach (DerObjectIdentifier extensionOid in tbsExtensions.ExtensionOids) {
if (!X509Extensions.DRAFT_DeltaCertificateDescriptor.Equals(extensionOid)) {
X509Extension extension = x509Extensions.GetExtension(extensionOid);
if (extension != null && !extension.Equals(tbsExtensions.GetExtension(extensionOid)))
x509ExtensionsGenerator.AddExtension(extensionOid, extension);
}
}
x509Extensions = (x509ExtensionsGenerator.IsEmpty ? null : x509ExtensionsGenerator.Generate());
}
DerBitString signatureValue = descriptor.SignatureValue;
return new DeltaCertificateDescriptor(serialNumber, algorithmIdentifier, x509Name, validity, x509Name2, subjectPublicKeyInfo, x509Extensions, signatureValue);
}
private static X509Extensions ExtractDeltaExtensions(X509Extensions descriptorExtensions, X509Extensions baseExtensions)
{
X509ExtensionsGenerator x509ExtensionsGenerator = new X509ExtensionsGenerator();
foreach (DerObjectIdentifier extensionOid in baseExtensions.ExtensionOids) {
if (!X509Extensions.DRAFT_DeltaCertificateDescriptor.Equals(extensionOid))
x509ExtensionsGenerator.AddExtension(extensionOid, baseExtensions.GetExtension(extensionOid));
}
if (descriptorExtensions != null) {
foreach (DerObjectIdentifier extensionOid2 in descriptorExtensions.ExtensionOids) {
x509ExtensionsGenerator.ReplaceExtension(extensionOid2, descriptorExtensions.GetExtension(extensionOid2));
}
}
if (!x509ExtensionsGenerator.IsEmpty)
return x509ExtensionsGenerator.Generate();
return null;
}
}
}