Get a Pentest and security assessment of your IT network.

Cyber Security

Secure Document Signing with Bouncy Castle

TL;DR

This guide shows you how to digitally sign a document using Bouncy Castle so only the intended receiver can verify it. We’ll cover generating key pairs, signing the document, and verifying the signature.

Prerequisites

  • Java Development Kit (JDK) installed
  • Bouncy Castle libraries added to your project (bcprov-jdk18on-*.jar and bcutil-jdk18on-*.jar). You can download these from the Bouncy Castle website.

Step 1: Generate Key Pair

The sender needs a key pair – a private key for signing and a public key for verification.

  1. Create a new Java project or use an existing one.
  2. Add the Bouncy Castle libraries to your project’s classpath.
  3. Use the following code snippet to generate the key pair:
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
import java.security.SecureRandom;

public class KeyPairGeneratorExample {
    public static void main(String[] args) throws Exception {
        // Generate a 2048-bit RSA key pair.
        RSAKeyPairGenerator generator = new RSAKeyPairGenerator();
        generator.init(new RSAKeyGenerationParameters(
                BigInteger.valueOf(2048),
                new SecureRandom()));
        AsymmetricCipherKeyPair keyPair = generator.generateKeyPair();

        // Get the private and public keys.
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

        System.out.println("Private Key: " + privateKey);
        System.out.println("Public Key: " + publicKey);
    }
}

Important: Securely store the private key! Never share it.

Step 2: Sign the Document

  1. Load the document you want to sign into a byte array.
  2. Use the sender’s private key to create a digital signature.
import org.bouncycastle.crypto.signers.RSASigner;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;

public class DocumentSigner {
    public static byte[] signDocument(String documentPath, RSAPrivateKey privateKey) throws IOException {
        byte[] document = readFileAsByteArray(documentPath);
        RSASigner signer = new RSASigner(HmacSHA256.getInstance());
        signer.init(privateKey);
        signer.update(document, 0, document.length);
        return signer.generateSignature();
    }

    private static byte[] readFileAsByteArray(String filePath) throws IOException {
        FileInputStream fis = new FileInputStream(filePath);
        byte[] buffer = new byte[(int) fis.getChannel().size()];
        fis.read(buffer);
        fis.close();
        return buffer;
    }
}

The output of this step is the digital signature, which you’ll need to send along with the document.

Step 3: Verify the Signature

  1. Load both the original document and the digital signature into byte arrays.
  2. Use the sender’s public key to verify the signature against the document.
import org.bouncycastle.crypto.signers.RSAVerifier;
import org.bouncycastle.crypto.params.RSAKeyParameters;

public class DocumentVerifier {
    public static boolean verifyDocument(String documentPath, byte[] signature, RSAPublicKey publicKey) throws IOException {
        byte[] document = readFileAsByteArray(documentPath);
        RSAVerifier verifier = new RSAVerifier(HmacSHA256.getInstance());
        verifier.init(publicKey);
        verifier.update(document, 0, document.length);
        return verifier.verify(signature);
    }

    private static byte[] readFileAsByteArray(String filePath) throws IOException {
        FileInputStream fis = new FileInputStream(filePath);
        byte[] buffer = new byte[(int) fis.getChannel().size()];
        fis.read(buffer);
        fis.close();
        return buffer;
    }
}

If the verification is successful, it confirms that the document hasn’t been tampered with and was signed by the owner of the private key corresponding to the public key used for verification.

Important Considerations

  • Key Storage: Protect your private key! Use a hardware security module (HSM) or secure key management system.
  • Algorithm Choice: HmacSHA256 is used here as an example, but consider more robust algorithms depending on your security requirements.
  • Error Handling: Implement proper error handling in your code to deal with potential exceptions during signing and verification.
Related posts
Cyber Security

Zip Codes & PII: Are They Personal Data?

Cyber Security

Zero-Day Vulnerabilities: User Defence Guide

Cyber Security

Zero Knowledge Voting with Trusted Server

Cyber Security

ZeroNet: 51% Attack Risks & Mitigation