Creating an X.509 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:

 Certificate  ::=  SEQUENCE  {
     tbsCertificate       TBSCertificate,
     signatureAlgorithm   AlgorithmIdentifier,
     signature            BIT STRING  }

So for instance, take this certificate with a valid signature:

-----BEGIN CERTIFICATE-----
MIIGgTCCBWmgAwIBAgIIP2loSeAn4ucwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE
BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl
cm5ldCBBdXRob3JpdHkgRzIwHhcNMTQwNTIyMTEyODU3WhcNMTQwODIwMDAwMDAw
WjBmMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN
TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEVMBMGA1UEAwwMKi5n
b29nbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEQ80mW9KOdkTavOvJ
T8KdnZW/ClBvM2DNSYlXEjlHxLfN23DIgwfk7xnThlwyH4RTk4bhhtWtBTyR9Gh4
3BIE5aOCBBkwggQVMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjCCAuIG
A1UdEQSCAtkwggLVggwqLmdvb2dsZS5jb22CDSouYW5kcm9pZC5jb22CFiouYXBw
ZW5naW5lLmdvb2dsZS5jb22CEiouY2xvdWQuZ29vZ2xlLmNvbYIWKi5nb29nbGUt
YW5hbHl0aWNzLmNvbYILKi5nb29nbGUuY2GCCyouZ29vZ2xlLmNsgg4qLmdvb2ds
ZS5jby5pboIOKi5nb29nbGUuY28uanCCDiouZ29vZ2xlLmNvLnVrgg8qLmdvb2ds
ZS5jb20uYXKCDyouZ29vZ2xlLmNvbS5hdYIPKi5nb29nbGUuY29tLmJygg8qLmdv
b2dsZS5jb20uY2+CDyouZ29vZ2xlLmNvbS5teIIPKi5nb29nbGUuY29tLnRygg8q
Lmdvb2dsZS5jb20udm6CCyouZ29vZ2xlLmRlggsqLmdvb2dsZS5lc4ILKi5nb29n
bGUuZnKCCyouZ29vZ2xlLmh1ggsqLmdvb2dsZS5pdIILKi5nb29nbGUubmyCCyou
Z29vZ2xlLnBsggsqLmdvb2dsZS5wdIIPKi5nb29nbGVhcGlzLmNughQqLmdvb2ds
ZWNvbW1lcmNlLmNvbYIRKi5nb29nbGV2aWRlby5jb22CDSouZ3N0YXRpYy5jb22C
CiouZ3Z0MS5jb22CDCoudXJjaGluLmNvbYIQKi51cmwuZ29vZ2xlLmNvbYIWKi55
b3V0dWJlLW5vY29va2llLmNvbYINKi55b3V0dWJlLmNvbYIWKi55b3V0dWJlZWR1
Y2F0aW9uLmNvbYILKi55dGltZy5jb22CC2FuZHJvaWQuY29tggRnLmNvggZnb28u
Z2yCFGdvb2dsZS1hbmFseXRpY3MuY29tggpnb29nbGUuY29tghJnb29nbGVjb21t
ZXJjZS5jb22CCnVyY2hpbi5jb22CCHlvdXR1LmJlggt5b3V0dWJlLmNvbYIUeW91
dHViZWVkdWNhdGlvbi5jb20wCwYDVR0PBAQDAgeAMGgGCCsGAQUFBwEBBFwwWjAr
BggrBgEFBQcwAoYfaHR0cDovL3BraS5nb29nbGUuY29tL0dJQUcyLmNydDArBggr
BgEFBQcwAYYfaHR0cDovL2NsaWVudHMxLmdvb2dsZS5jb20vb2NzcDAdBgNVHQ4E
FgQUZ+wFAJG6n8knT4i1EhyqBhTlMxgwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAW
gBRK3QYWG7z2aLV29YG2u2IaulqBLzAXBgNVHSAEEDAOMAwGCisGAQQB1nkCBQEw
MAYDVR0fBCkwJzAloCOgIYYfaHR0cDovL3BraS5nb29nbGUuY29tL0dJQUcyLmNy
bDANBgkqhkiG9w0BAQUFAAOCAQEAFId/P3amOfPZtGwUDvIZlfp4kUJ/Qr/y9KMc
syO7YdcO+mSwOarZtZ1UdB3zBJ3d7vn2Ld1G0TiqFW8vIZk1OtWtdMC6hFQuC21P
Papck9jRhLZO1Jx4uFbGQdWM25z+a1TzxaoULmhAN9FF38OFKcrZlb/Gf4uETYV7
mMFQ10GT6UBESCkvEsT4hgEONQ/wXiOxDgMrbXBBm67IfXJzxmpncPDG6o49Dqw4
F6Jkkotp7ca6OvBnTvi0hcd4qS/64c/+0SjjLsWFq04W/zRJAUvF7mt8yiZHmv8f
E+FdDynG49hiV4MhWpmLdY5xzOWqb7+xmPdo3947SoHe9ZO2Mg==
-----END CERTIFICATE-----

(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:

E+FdDynG49hiV4MhWpmLdY5xzOWqb7+xmPdo3947SoHe9YO2Mg==

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.