How to create a digital signature and sign data?

In the following code snippet you will learn how to generate a digital signature to sign a data or file. To create a signature we will need a key pair of public and private key. But for the signing process we’ll only use the private key, while the public key will be used to verify the signature.

To create a digital signature we need an instance of java.security.Signature. To get one we can call the Signature.getInstance() method and pass the algorithm and the provider arguments. In this code snippet we’ll use SHA1withDSA and SUN for the algorithm and provider.

But before we can use the Signature object we have to initialize it first with a PrivateKey. You can also see how to get a private key in the code snippet below. To initialize call the Signature‘s initSign() method.

And finally to generate the digital signature we need to update the Signature using the data that we are going to sign. To do this we read the file into byte[] using the helps of Files.readAllBytes() and supply the bytes into the Signature object using the update() method. To get the signature we call the sign() method which will return us a byte array of the signature.

And here is the complete code snippet:

package org.kodejava.security;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;

public class GenerateDigitalSignature {
    public static void main(String[] args) {
        try {
            // Get instance and initialize a KeyPairGenerator object.
            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA", "SUN");
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
            keyGen.initialize(1024, random);

            // Get a PrivateKey from the generated key pair.
            KeyPair keyPair = keyGen.generateKeyPair();
            PrivateKey privateKey = keyPair.getPrivate();

            // Get an instance of Signature object and initialize it.
            Signature signature = Signature.getInstance("SHA1withDSA", "SUN");
            signature.initSign(privateKey);

            // Supply the data to be signed to the Signature object
            // using the update() method and generate the digital
            // signature.
            byte[] bytes = Files.readAllBytes(Paths.get("README.md"));
            signature.update(bytes);
            byte[] digitalSignature = signature.sign();

            // Save digital signature and the public key to a file.
            Files.write(Paths.get("signature"), digitalSignature);
            Files.write(Paths.get("publickey"), keyPair.getPublic().getEncoded());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

On the next examples we are going to verify the digital signature. To verify the digital signature is to make sure that the data was sent by the original creator without any modification. To verify we’ll need the digital signature and the public key of the key pair. To get these in the code snippet above we have saved both the digital signature and the public key to files.

How do I generate public and private keys?

The code snippet below show you how to use the JDK Security API to generate public and private keys. A private key can be used to sign a document and the public key is used to verify that the signature of the document is valid.

The API we used to generate the key pairs is in the java.security package. That’s mean we have to import this package into our code. The class for generating the key pairs is KeyPairGenerator. To get an instance of this class we have to call the getInstance() methods by providing two parameters. The first parameter is algorithm and the second parameter is the provider.

After obtaining an instance of the key generator, we have to initialize it. The initialize() method takes two parameters, the key size and a source of randomness. We set the key size to 1024 and pass and instance of SecureRandom.

Finally, to generate the key pairs we call the generateKeyPair() method of the KeyPairGenerator class. This will return a KeyPair object from where we can get the PrivateKey and PublicKey by calling the getPrivate() and getPublic() method.

Let’s see the code snippet below:

package org.kodejava.security;

import java.security.*;
import java.util.Base64;

public class GenerateKeyPairDemo {
    public static void main(String[] args) {
        try {
            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA", "SUN");

            // Initialize KeyPairGenerator.
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
            keyGen.initialize(1024, random);

            // Generate Key Pairs, a private key and a public key.
            KeyPair keyPair = keyGen.generateKeyPair();
            PrivateKey privateKey = keyPair.getPrivate();
            PublicKey publicKey = keyPair.getPublic();

            Base64.Encoder encoder = Base64.getEncoder();
            System.out.println("privateKey: " + encoder.encodeToString(privateKey.getEncoded()));
            System.out.println("publicKey: " + encoder.encodeToString(publicKey.getEncoded()));
        } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
            e.printStackTrace();
        }
    }
}