Java数字签名-RSA算法
数字签名
数字签名是带有密钥(公钥、私钥)的消息摘要算法。主要作用是验证数据的完整性、认证数据来源、抗否认。在数字签名的实现中我们使用私钥签名、公钥验证。常用的数字签名算法包括RSA、DSA、ECDSA。
RSA
该算法是数字签名的经典算法。主要包括MD和SHA两类。
应用场景:
Java实现RSA数字签名如下:
============================================================================RSA数字签名工具类:
import java.security.Key; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; public class DigitalSignRSA { //公钥 private static final String PUBLIC_KEY = "RSAPublicKey"; //私钥 private static final String PRIVATE_KEY = "RSAPrivateKey"; /** 初始化密钥对 * @return Map 密钥对Map * @throws Exception */ public static Map<String, Object> initKey() { try { //实例化密钥对生成器 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); // 初始化密钥对生成器,密钥大小为96-1024位 keyPairGenerator.initialize(512, new SecureRandom()); //生成密钥对 KeyPair keyPair = keyPairGenerator.generateKeyPair(); //公钥 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); //私钥 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); //将密钥对存储在Map中 Map<String, Object> keyMap = new HashMap<String, Object>(2); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return null; } /** 执行数字签名【私钥签名】 * @param data 待加密数据 * @param privKey 私钥 * @return byte[] 加密数据 * @throws Exception */ public static byte[] digitalSign(byte[] data, byte[] privKey) { try { PrivateKey privateKey = (PrivateKey) KeyFactory.getInstance("RSA") .generatePrivate(new PKCS8EncodedKeySpec(privKey)); Signature signature = Signature.getInstance("MD5WithRSA"); signature.initSign(privateKey); signature.update(data); return signature.sign(); } catch (Exception ex) { ex.printStackTrace(); } return null; } /** 验证签名【公钥验证】 * @param data 待解密数据 * @param pubKey 公钥 * @return byte[] 解密数据 * @throws Exception */ public static boolean signVerify(byte[] data, byte[] rsaData, byte[] pubKey) { try { PublicKey publicKey = (PublicKey) KeyFactory.getInstance("RSA") .generatePublic(new X509EncodedKeySpec(pubKey)); Signature signature = Signature.getInstance("MD5WithRSA"); signature.initVerify(publicKey); signature.update(data); return signature.verify(rsaData); } catch (Exception ex) { ex.printStackTrace(); } return false; } /** 取得私钥 * @param keyMap 密钥Map * @return byte[] 私钥 * @throws Exception */ public static byte[] getPrivateKey(Map<String, Object> keyMap) { Key key = (Key) keyMap.get(PRIVATE_KEY); return key.getEncoded(); } /** 取得公钥 * @param keyMap 密钥Map * @return byte[] 公钥 * @throws Exception */ public static byte[] getPublicKey(Map<String, Object> keyMap) { Key key = (Key) keyMap.get(PUBLIC_KEY); return key.getEncoded(); } }
============================================================================RSA数字签名工具测试类:
@Test public void test_DigitalSignRSA() { //公钥 byte[] publicKey; //私钥 byte[] privateKey; //初始化密钥 //生成密钥对 Map<String, Object> keyMap = DigitalSignRSA.initKey(); publicKey = DigitalSignRSA.getPublicKey(keyMap); privateKey = DigitalSignRSA.getPrivateKey(keyMap); System.out.println("RSA公钥:\n" + org.apache.commons.codec.binary.Base64.encodeBase64String(publicKey)); System.out.println("RSA私钥:\n" + org.apache.commons.codec.binary.Base64.encodeBase64String(privateKey)); System.out.println(); String msgA2B = "What can I do for you?"; //执行数字签名【私钥签名】 byte[] encodeMsgA2B = DigitalSignRSA.digitalSign(msgA2B.getBytes(), privateKey); System.out.println("JDK RSA签名::\n" + org.apache.commons.codec.binary.Base64.encodeBase64String(encodeMsgA2B)); //验证签名【公钥验证】 boolean bool = DigitalSignRSA.signVerify(msgA2B.getBytes(), encodeMsgA2B, publicKey); System.out.println("数字签名是否有效?:\n" + bool); }