Java数字签名-ECDSA算法
ECDSA
微软的Office、Windows操作系统的验证就是ECDSA算法——椭圆曲线数字签名算法(Elliptic Curve Digital Signature Algorithm),在2000年的时候称为了ANSI和IEEE的标准。特点是:速度快、签名短、强度高。在JDK1.7update4之后提供了对ECDSA的支持。该签名的算法也和RSA的数字签名算法也是大同小异。
============================================================================ECDSA数字签名工具类:
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.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; public class DigitalSignECDSA { //公钥 private static final String PUBLIC_KEY = "ECDSAPublicKey"; //私钥 private static final String PRIVATE_KEY = "ECDSAPrivateKey"; /** 初始化密钥对 * @return Map 密钥对Map * @throws Exception */ public static Map<String, Object> initKey() { try { //实例化密钥对生成器 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC"); // 初始化密钥对生成器,密钥大小为256位 keyPairGenerator.initialize(256, new SecureRandom()); //生成密钥对 KeyPair keyPair = keyPairGenerator.generateKeyPair(); //公钥 ECPublicKey publicKey = (ECPublicKey) keyPair.getPublic(); //私钥 ECPrivateKey privateKey = (ECPrivateKey) 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("EC") .generatePrivate(new PKCS8EncodedKeySpec(privKey)); Signature signature = Signature.getInstance("SHA1WithECDSA"); 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("EC") .generatePublic(new X509EncodedKeySpec(pubKey)); Signature signature = Signature.getInstance("SHA1WithECDSA"); 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(); } }
============================================================================ECDSA数字签名工具测试类:
@Test public void test_DigitalSignECDSA() { //公钥 byte[] publicKey; //私钥 byte[] privateKey; //初始化密钥 //生成密钥对 Map<String, Object> keyMap = DigitalSignECDSA.initKey(); publicKey = DigitalSignECDSA.getPublicKey(keyMap); privateKey = DigitalSignECDSA.getPrivateKey(keyMap); System.out.println("ECDSA公钥:\n" + org.apache.commons.codec.binary.Base64.encodeBase64String(publicKey)); System.out.println("ECDSA私钥:\n" + org.apache.commons.codec.binary.Base64.encodeBase64String(privateKey)); System.out.println(); String msgA2B = "What can I do for you?"; //执行数字签名【私钥签名】 byte[] encodeMsgA2B = DigitalSignECDSA.digitalSign(msgA2B.getBytes(), privateKey); System.out.println("JDK ECDSA签名::\n" + org.apache.commons.codec.binary.Base64.encodeBase64String(encodeMsgA2B)); //验证签名【公钥验证】 boolean bool = DigitalSignECDSA.signVerify(msgA2B.getBytes(), encodeMsgA2B, publicKey); System.out.println("数字签名是否有效?:\n" + bool); }