數字簽名
數字簽名是帶有密鑰(公鑰、私鑰)的消息摘要算法。主要作用是驗證數據的完整性、認證數據來源、抗否認。在數字簽名的實現中我們使用私鑰簽名、公鑰驗證。常用的數字簽名算法包括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); }