Signature sign/verification demo in Java

Summary

Digital signatures are essential for ensuring data authentication and integrity during sensitive data transfers, protecting against tampering and man-in-the-middle attacks. Java's `Signature` class provides the core API for this, requiring a private key for signing via `initSign()` and a public key for verification using `initVerify()`. Developers can instantiate `Signature` with various algorithms like SHA256withRSA, which necessitates generating a corresponding RSA key pair. The practical workflow involves initializing the signature process with a private key, updating it with the data to be signed, and then generating the signature. Verification subsequently uses the public key, the original data, and the received signature to confirm authenticity.

Digital signature is commonly used in areas where data authentication and integrity are required. It is extremely important to have signature while transferring sensitive data from one peer to other peers through network since there might be malicious applications or man-in-the-middle attacks which may alter the data along the way.

Java provides some APIs to generate and verify digital signature. One important class is Signature

  • When generating the signature, a private key needs to be passed to initSign()
  • When verifying the signature, a public key needs to be passed to initVerify()

Java uses the popular getInstance() mechanism to create Signature instance, there are different signature algorithms available for creating Signature. For example, SHA256withRSA, SHA512withRSA. For a complete list of Signature algorithms, you can use below code block.

Provider[] providers = Security.getProviders();
for(Provider provider : providers){
	System.out.println("Provider : "+provider.getName());
	Set<Service> services = provider.getServices();
	for(Service service : services){
		if(service.getType().equals("Signature")){
			System.out.println("\t"+service.getAlgorithm());
		}
	}
}

Now we will take SHA256withRSA as example to demonstrate the signature sign/verification. Since this algorithm uses RSA as the private/public key algorithm, we first need to generate a RSA keypair. 

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048); // KeySize
KeyPair keyPair = keyPairGenerator.generateKeyPair();

PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();

Next, use privateKey to sign the data.

byte[] data = "sign me".getBytes();
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(data);
byte[] signedData = signature.sign();

The signedData is the signature generated. The length of signedData will be the keysize in bytes. For example, if we are using a 2048 bit RSA key, the generated signature will have length of 2048 bits. The signedData will be verified when the other peer receives this piece of data. 

signature.initVerify(publicKey);
signature.update(data);
if(signature.verify(signedData)){
	System.out.println("Verified");
}else{
	System.out.println("Something is wrong");
}

The update() method is to tell the Signature to handle the data passed in. This data can be a message or any other sensitive message.

Here is the completed code snippet.

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048); // KeySize
KeyPair keyPair = keyPairGenerator.generateKeyPair();

PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();

byte[] data = "sign me".getBytes();
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(data);
byte[] signedData = signature.sign();

signature.initVerify(publicKey);
signature.update(data);
if(signature.verify(signedData)){
	System.out.println("Verified");
}else{
	System.out.println("Something is wrong");
}
JAVA SECURITY SIGNATURE

  RELATED

  COMMENTS

0

No comment for this article.