1
$\begingroup$

In our software we receive certificates in binary DER format from our clients. They are in advance used to perform certain identity checks between server and client. To ensure the certificates are valid and trustable, we verify the certificate chain. Using the APIs we have available this is easily possible.

But the main question is: How can we create certain certificates which actually have a broken chain of trust or any integrity problems which should be validated. It seems easy to generate valid ones, but for testing our validation system we need invalid ones.

I would like to understand what to change on my valid certificate to introduce the previously mentioned errors. Can it be easily done on binary level or are there maybe tools for it? I tried to search for explainations but all I found was about how to fix already broken certificates. I expect either I need to change some bytes of the public key, or change the issuer details.

$\endgroup$
2
$\begingroup$

Personally I wrote a generic ASN.1 decoder/encoder tool. It is called DDer. It transforms a DER-encoded object into a structured text representation (with parenthesis, somewhat reminiscent of Lisp). The interesting part is that it comes with a companion tool, MDer, which performs the reverse transform. Thus, you can edit certificate contents with a text editor, and MDer will work out the encoding subtleties.

Now a tricky remaining part is the signatures. Certificates are signed, and changing any bit in a certificate invalidates the signature, so this calls for a signing tool. I happen to have written my own crypto library (in C#, not published yet) that can apply a signature on an arbitrary DER-encoded object, even patching the inner SignatureAlgorithm in the to-be-signed structure of a certificate.

In a hurry, though, a RSA signature can be computed "by hand" with the help of the dc utility which is standard issue in Unix-like systems. That calculator can use hexadecimal input and output, process arbitrarily long integers, and compute modular exponentiations with the integrated | operator. Workflow would be:

  • Create the to-be-signed structure in the text representation of DDer, and use MDer to convert it to DER. When dabbling with certificates, you usually start with an existing certificate, so DDer-ize that.
  • Use sha256sum (another standard command-line tool on Linux) to compute the SHA-256 hash of the to-be-signed.
  • Assemble the hash value in a properly padded structure as befits RSA. You want to make it in hexadecimal, in a text editor. Make sure that all your hexadecimal is uppercase with no extra spaces, because that's what dc feeds on.
  • Use DDer on the private key file to obtain the key elements, specifically the modulus (first big integer) and the private exponent (third big integer in the structure)(the second big integer is the public exponent and is usually not that big).
  • Use dc to compute the modular exponentiation. You switch dc to hexadecimal input and output with 16 i 10 o (which reads as "set input radix to 16, then set output radix to 10"; that "10" is interpreted in hexadecimal, since you just switched the input radix to 16!). You then copy&paste the operands (padded hash, private exponent, modulus, in that order), and compute the modular exponentiation (|). You use p to print the result, which will be in hexadecimal.
  • Back to the DDer text representation of the to-be-signed, you write the wrapping structure, which is a SEQUENCE that contains the to-be-signed, an AlgorithmIdentifier that identifies the signature algorithm, and a BIT STRING whose contents are the signature value. MDer will expect the BIT STRING contents to be in hexadecimal, just like what you just obtained from dc, so it's a matter of copy&paste (again).
  • And a final MDer to produce the final certificate, DER-encoded.
  • If you need the new certificate in PEM format, convert with with openssl, or directly with the base64 tool (again a usual command-line tool in Linux) and add the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- lines manually (this may be necessary in case you purposefully made an incorrectly encoded certificate, that openssl won't accept to convert).

If you can go through all these steps in due order, then you know enough about RSA and ASN.1 to write your own tools to apply signatures. If using C#, you can reuse the ASN.1 library from DDer, as well as the big-integer class (ZInt) for some very basic and perfunctory RSA implementation (not secure enough for use in production, but usable for making test cases).

$\endgroup$
  • $\begingroup$ Thanks for your answer. Since the overall workflow seems to be quite complex, I'll try to adapt your tool to do an all-in-one corruption of the chain by changing the signature contained in the certificate and maybe details about the issuer. $\endgroup$ – Danielku15 Jul 21 '17 at 11:09
0
$\begingroup$

How can we create certain certificates which actually have a broken chain of trust or any integrity problems which should be validated

There seems to be two test cases

integrity problems

Thing is - tricky. Every X.509 certificate contains it's signature. So - technically you can change any value but the signature won't be valid anymore

broken chain

You can create a self-signed or certificate signed by CA which is not trusted, not yet valid, expired or having restricted properties (signing algorithm, keyUsage, ...)

I used BouncyCastle to build own certificates with custom attributes (such as MS cert enrollment, ...). Using direct ASN.1 nodes you should be able to manipulate any values. However - when loading the certificates, until now, all implementations I've seen nicely checked the signature of the certificate signature.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.