0 votes
by (220 points)

How can I create a certificate that its Validate method will return ValidationOptions.WrongUsage?

1 Answer

0 votes
by (64.4k points)

You will get ValidationStatus.WrongUsage when the certificate is used in a way it was not issued for.

For example:
One of possible uses is KeyUses.KeyCertSign (Certificate signing).
If you use a certificate without KeyCertSign usage to issue another certificate, correct validation routine would report ValidationStatus.WrongUsage when validating issued certificate.

Here is sample code to get ValidationStatus.WrongUsage:

// we will need two certificates
Certificate rootCert, invalidCert;

// prepare info for root certificate
var rootInfo = new CertificateInfo();
rootInfo.Subject = new DistinguishedName("CN=Sample root");

// specify very limited usage
rootInfo.Usage = KeyUses.KeyAgreement;

using (var alg = new AsymmetricKeyAlgorithm())
    // generate a 2048-bit RSA key for the certificate
    alg.GenerateKey(AsymmetricKeyAlgorithmId.RSA, 2048);
    var privateKey = alg.GetPrivateKey();

    // create the self-signed (root) certificate
    rootCert = CertificateIssuer.Issue(rootInfo, privateKey);

// prepare info for certificate with invalid usage
var invalidCertInfo = new CertificateInfo();
invalidCertInfo.Subject = new DistinguishedName("CN=This should not be never issued");
invalidCertInfo.Usage = KeyUses.KeyAgreement;

using (var alg = new AsymmetricKeyAlgorithm())
    // generate a 2048-bit RSA key for the certificate
    alg.GenerateKey(AsymmetricKeyAlgorithmId.RSA, 2048);
    var publicKey = alg.GetPublicKey();

    // issue invalid certificate
    invalidCert = CertificateIssuer.Issue(rootCert, invalidCertInfo, publicKey);

// check usage of invalid certificate
// Note: Because root cert is not in Certificate Store, 
//       we need to use certificate chain to link the two certs.
var chain = new CertificateChain() { invalidCert, rootCert };
var result = chain.Validate();

You can try for yourself, that when you give the root certificate correct usage, validation result will not contain ValidationStatus.WrongUsage. To do this, change line rootInfo.Usage = KeyUses.KeyAgreement to:

rootInfo.Usage = KeyUses.KeyCertSign;
by (220 points)
Ok, thank you,
In my case I encrypt,decrypt,sign and verify signature and call the Validate method of the certificate that will be used for the operation just before the operation.

In this case, the certificate by itself is not aware of the operation that will follow.
How can i prevent the operation since the Validate method returns a valid certificate?

For example, I  have a valid certificate for server authentication only(created by IIS)  and I can encrypt a file using it.
by (64.4k points)
Please note that certificate.Validate() method validates the certificate itself. It doesn't validate the certificate for usage of specific operation.

The key usage checks are responsibility of higher level API.

For example:
1 - TLS explicitly defines: "digitalSignature bit MUST be set if the key usage extension is present" (https://tools.ietf.org/html/rfc5246#page-48)

2 - S/MIME explictly defines:

   If the extended key usage extension is present in the certificate,
   then interpersonal message S/MIME receiving agents MUST check that it
   contains either the emailProtection or the anyExtendedKeyUsage OID as
   defined in [KEYM]. (https://tools.ietf.org/html/rfc5750#section-4.4.4)

This means, that some protocols can restrict the usage of certificate by its extensions, but other do not need to.

It depends on your protocol whether you can Sign/Verify/Encrypt/Decrypt using particular certificate. The Rebex Certificate API do not check key usage extensions in this operations. You have to do it for yourself, if required by your protocol (because you act as higher level API).
Note: Rebex TLS API and Rebex S/MIME API performs the required checks automatically.

You can retrieve the "key usage extension" by the  Certificate.GetIntendedUsage() method.
You can retrieve the "extended key usage extension" by the  Certificate.GetEnhancedUsage() method.
by (220 points)
Thank you, yes I will do it manually by getting the usage