Yes, I know that Bouncy Castle is probably the only reasonable library for doing crypto in Java 8. However …

I can remember my first computer - Sinclair ZX Spectrum+ - with incredible 48KB RAM. The experience is still inside me and I find it hard to justify using 1.5+MB of Java code where 10 lines could do the trick. I talk about doing RSA signatures in Java 8.

Using system Java libraries for crypto is not fashionable as Bouncy Castle gives you a much wider set of functions. However, if you just need to do a bit of cryptography, Bouncy Castle may be an unnecessary dependency. Here’s how you can sign documents and verify signatures.

Signature Verification

The first thing you need is some input data and let’s start with signature verification:

we need a signature - the code below delivers it in the base64 form so we will decode it as well; some data that the signature is for - again, it’s base64 data as this snippet is for JWS-like signature verification; and and we need a public key - we got it in the form of X.509 certificate, from which we extract the public key.

Note: the example below is for 4,096 bit RSA and export crypto restrictions may kick in. So if you haven’t done it yet, and experience weird problems, you may need to install an unlimited crypto policy for your Java installation. Have a look here, it’s pretty simple (once you find the right folder:) ): Java Cryptography Extension (JCE) Unlimited Strength







import javax.security.* ; import java.security.* ; // create a Base64 decoder instance Base64 . Decoder b64decoder = Base64 . getDecoder (); // read a certificate from a base64 string byte [] derCertificate = b64decoder . decode ( "MIIC4TCCAcmgAwIBAgIQCaWR/8BMflFb9vqNRGJ3cTANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDDAppLTllN2M2NjEyMB4XDTE2MTAwMzIxNDYyNloXDTQxMDkyNzIxNDYyNlowFTETMBEGA1UEAwwKaS05ZTdjNjYxMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANdYTkecZIOHXR2iEIV24ISKP578ClBkSM1BM+EL3qYvx3ZuiqGxGqrUcAHKfUv4OjzXmfhprEAkemU3ao0d/rf0SBHuq99HTC3mecnvXMBhKe1ovd9Df5leqiXeSGOU6Z8gMYR15q3kWyAdnzS5+trGBvrtQxKx15CgLK3Ncw4PEGMzTivcJxV4oroV0mZzvHSaQQLl14lUNTEzs5OFTNYe8HZaSJI0VPlKPcDun25FDKOZMa3nE2l1m9ZttyWrsp4oghrUrNsaJXBC5lhBfD6oYQaOIWjlVnRv/gvSUp1X6VMupQaas78qXubI7OD74w26Oe/nFpUrLmdfC2eeAN0CAwEAAaMtMCswEgYDVR0TAQH/BAgwBgEB/wIBADAVBgNVHREEDjAMggppLTllN2M2NjEyMA0GCSqGSIb3DQEBCwUAA4IBAQCBjTxnNQX06M4qUAoCERmwJ/7k3xTg0FCqP0O58fhXb9oKMpJIZWVAbUYctcZCi0freKIyOQ+JF7J6CsuSkrd+ck8c4aYwRqX9YmBoyt7r14QYIKnvVbuudkT/djR3prI3Li4zT3VMT8FakckEP6tKrkrAjRQ+6KKT5YoM1TQqY0WEnzjqBtDva2CQvClj9rtfcNAnV2V24Qii2NUgOwanUudMqrutOsK2E3wt+Sa5t/NjAxva0FuO2101UISW6r28brvKTNN6IwW23662coEyQwJNA+o2TF9VwipzRbmb+g6lTDxdee77yIfOcssg03n7MMwKKt2KXGt7IE2btCgt" ); // create a X509Certificate instance X509Certificate testX509 = X509Certificate . getInstance ( derCertificate ); //here is the data String datab64 = "eyJ1c2VybmFtZSI6ICI2a3JjbWlhY2xR6NTVwcWNyd3d4ODllMmY4d2JpM3o3M29la2M2cWl1YnYwMDRlczAiLCAiYXV0aGVudGljYXRpb24iOiAiY2hhbGxlbmdlIiwgImFwaWtleSI6ICJ3dnhlemVpZnVwb2JpMnNuN3Bha2wyc3QxdngycTk3bnpvNGRia2cwdHlmaHF0ZXBhamU5Znl1c252dm1kdWxyIiwgInJlc3BvbnNlIjogInpxOTBubmdsbm1qbHljdXF2OGNxOTE5Zm1pOWxudjlueTdhM2hnMGVjdGU4aXJvNmphaXNzeTA0anZpaXY5Nmh4cGV5aDM4ZnMxcnZ2MG42bHM0cXV5bTlwMXNiM2F1MHB5dGUzbzRxNWZteXNkM2VuOGZncWpkNjllaTduOHlyIn0=" ; // and the last bit is the signature we verify String signatureb64 = "sUfTwtwoz0YLxwKfzUqtfLiatKiGHLvb7RasHTNrA7IDsNpMIU/KLB/TtvI8vXhRsJVxuDa3WsXRM9kjIuXIOBks/8WEi1tr4Yb0aGaFhIBGoThdUypXgxuEi2VOGwz2Ayv2UAi0Et9Vz/CORdH+sWFdAyZBkYbxLdYExciGldK/caVEjC4WFaMwb6c6blP8xQEUnN2kHEutuF3ROi2aknIYY3VQgbzPJCYUTqgviS+2ZabEL1FJEyahb2VZqO72+sOjqHT4wdDFrP+GuXc5SgbrZ9Jv0JHVP5H7h5kUeKIe/DaRb3865s0U0668+XNcSf8Yzvo+TVSCU5cG8+cBSA==" ; byte [] signature = b64decoder . decode ( signatureb64 ); // create a crypto instance - in this case we have SHA256 as hash algorithm // it's worth noting that the default padding is PKCS1.5 - if someone asks, OAEP is available as well Signature signAlg = Signature . getInstance ( "SHA256withRSA" ); // we will initialize the crypto signature instance with the public key extracted from the certificate signAlg . initVerify ( testX509 . getPublicKey ()); // we will load the data - this signature was computed from the base64 data, similar to JWS approach signAlg . update ( datab64 . getBytes ()); // and we simply verify the signature boolean result = signAlg . verify ( signature );

Signing

What is the difference for creating the signature? Well there are 2 points here:

you need a private key that will be used with signAlg.initVerify() method instead of the verify() method, you will call the sign() method, which returns a byte array





