Creating an X.509 certificate with a valid signature with OpenSSL is pretty well documented all over the Internet. There are instructions on creating certificates that are signed by themselves and certificates that are signed by a certificate authority (CA). But how does one create a certificate with an invalid signature?
The simplest way to create an X.509 certificate with an invalid signature is to create one with a valid signature, and then alter the signature. A simple text editor will do the trick if you use the PEM encoding of certificates (the one with the "-----BEGIN CERTIFICATE-----" header and Base64 encoding).
X.509 certificates use ASN.1 and the signature value comes last, as specified in the standard:
So for instance, take this certificate with a valid signature:
(This is one of Google's certificates, I hope they don't mind.)
To turn that certificate into one with an invalid signature, you just have to modify one letter at the end. Don't touch the '=' signs (if they are present -- they are padding for Base64 when the binary data length is not a multiple of 3); to avoid an exceedingly rare potential issue with BER encoding, don't modify one of the four letters which immediately precede these equal signs (or end of data) either. To do what you are trying to achieve, you may change the last 'Z' into another letter (e.g., a 'Y'), so that the last data line now reads:
and voilà! a certificate which decodes properly but has an invalid signature.
A signature is generally just an encrypted hash of the contents of the message. Any change to either the contents or the signature itself will make it invalid.
There are two different ways that a signature could be invalid. The signature itself could fail to decode (when you try the public key associated with the signer, it doesn't decrypt correctly) or it could not match the hash generated from the input but be validly decrypted.
For the former, simply make any random alteration to the signature data itself since it will then not decode to the original hash if it decodes to anything remotely valid.
For the later, simply change any value or character within the body of the certificate. Something as simple as adding a space or changing capitalization should be sufficient to make it so the signature does not match.
If you are testing certificate behaviors, you should also test how a self-signed certificate with a valid signature but an invalid chain of trust behaves by signing your own certificate with a root certificate that is not trusted by the client you are testing.
As an added bonus consider parsing the resulting certificate to verify that you have successfully corrupted the signature. I have found this website to be immensely helpful when working with ASN1 structures. This will also help ensure that you did not inadvertently corrupt the ASN1 encoding.