铁马冰河2000

导航

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);
    }

 

posted on 2022-01-23 22:51  铁马冰河2000  阅读(1016)  评论(1编辑  收藏  举报