Original link: https://www.dubby.cn/detail.html?id=9125
Previously Common encryption and decryption (1) The message digest is mentioned in it. What's the difference between the digital signature and the message digest? In fact, a digital signature is a message digest with asymmetric encryption.
The purpose of message digest is to prevent data from being tampered, while digital signature is to prevent denial.
The signature process is:

image

image
The conclusion is to use the private key to add signature and the public key to verify signature
import java.security.*; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; public class RSASignature { private static final String KEY_ALGORITHM = "RSA"; private static final String SIGN_ALGORITHM = "MD5withRSA"; public static byte[] sign(byte[] keyBytes, byte[] dataBytes) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException { PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); Signature signature = Signature.getInstance(SIGN_ALGORITHM); signature.initSign(privateKey); signature.update(dataBytes); return signature.sign(); } public static boolean verify(byte[] keyBytes, byte[] dataBytes, byte[] sign) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException { X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec); Signature signature = Signature.getInstance(SIGN_ALGORITHM); signature.initVerify(publicKey); signature.update(dataBytes); return signature.verify(sign); } }
Test code:
import cn.dubby.digital.signature.RSASignature; import org.apache.commons.codec.binary.Hex; import org.junit.Assert; import org.junit.Test; import java.nio.charset.Charset; import java.security.*; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; public class RSASignatureTest { private static final String key_algorithm = "RSA"; private static final int key_size = 1024; private static final String data = "Hello, Dubby"; @Test public void test() throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(key_algorithm); keyPairGenerator.initialize(key_size); KeyPair keyPair = keyPairGenerator.generateKeyPair(); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); byte[] dataBytes = data.getBytes(Charset.forName("UTF-8")); //Sign with private key byte[] sign = RSASignature.sign(privateKey.getEncoded(), dataBytes); System.out.println(Hex.encodeHexString(sign)); //Use public key to verify signature boolean verifyResult = RSASignature.verify(publicKey.getEncoded(), dataBytes, sign); Assert.assertTrue(verifyResult); } }
Result:
5363226f4c9a40a0a95fd526b4efa8697036b03b485a663473702e2cdf72e55082584450568b53502ddb11a78ba9ddf3160bda28d13273b15c5597f7e887d5a084bda94f9ffe41699f2d5c821863fa1ec28af6e38c8578a72f66034aa4a1f95e8bcce7b70710ce53af6a3a5c5324e73cc42eff8e6945a256cea89a1b156e346f