Search code examples
javasslrsax509certificatebouncycastle

X509 RSA bouncy castle sign and verify plain text in Java


I am currently writing a Java program using BouncyCastle that generates an X509 SSL certificate with an RSA key pair.

I have been able to successfully create the SSL cert but I also want the ability to then sign arbitrary plain text and with that signature verify ownership of the keys by verifying the signature against the plain text.

The methods should look something like this:

protected String SignData(String privateKey, String text)
{
    //return a signature
}

and

protected boolean verifySignature(String text, String signature, String pubKey)
{
    //return either true or false depending on whether the signature is valid or not
}

I have successfully generated a self signed SSL certificate using the following:

protected X509Certificate generateCert()
{
    try
    {
        Security.addProvider(new BouncyCastleProvider());
        // generate a key pair
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC");
        keyPairGenerator.initialize(4096, new SecureRandom());
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        // build a certificate generator
        X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
        X500Principal dnName = new X500Principal("cn=example");
        // add some options
        certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
        certGen.setSubjectDN(new X509Name("dc=name"));
        certGen.setIssuerDN(dnName); // use the same
        // yesterday
        certGen.setNotBefore(new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000));
        // in 2 years
        certGen.setNotAfter(new Date(System.currentTimeMillis() + 2 * 365 * 24 * 60 * 60 * 1000));
        certGen.setPublicKey(keyPair.getPublic());
        certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
        certGen.addExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage(KeyPurposeId.id_kp_timeStamping));

        // finally, sign the certificate with the private key of the same KeyPair
        X509Certificate cert = certGen.generate(keyPair.getPrivate(), "BC");

        return cert;
    }
    catch (Exception e)
    {
        e.printStackTrace();
        return null;
    }
}

Solution

  • Found the solution:

    to Sign:

            Signature rsaSign = Signature.getInstance("SHA256withRSA", "BC");
            rsaSign.initSign(pair.getPrivate());
            rsaSign.update(plaintext.getBytes("UTF-8"));
            byte[] signature = rsaSign.sign();
            return signature;
    

    To verify:

            rsaVerify = Signature.getInstance("SHA256withRSA", "BC");
            rsaVerify.initVerify(pubKey);
            rsaVerify.update(plaintext.getBytes("UTF-8"));
            return rsaVerify.verify(signature);