ECDSA数字签名算法及JAVA实现

ECDSA数字签名算法

         ECDSA椭圆曲线数字签名算法是针对素数域和伽罗瓦域上的椭圆曲线定义的,在实际中前者更为常用,以下是针对素数域的说明:

         1.使用椭圆曲线E其中

                  椭圆曲线E的模数为p,系数为a和b,生成素数阶q的循环群的点A

         2.选择一个随机整数d,并且0<d<q

         3.计算B=dA

         4.这时,公钥和私钥就全部都生成了

                  公钥:{p,a,b,q,A,B}            私钥:d

         5.签名,ECDSA签名是由两个整数r,s构成,下面是r,s的获取方式

                  R=kA

                  r=X  

                  s=(h(M)+d·r)k^-1mod q

                  注:X是R这个点的x轴坐标,h(M)是明文的哈希值

         6.签名验证,假设收到的明文为M’,收到的签名为s’、r’,则验证方式如下:

                  w=(s’)^-1mod q

                  u1=[H(M’)w] mod q

                  u2=(r’)w mod q

                  P=u1·A+u2·B

                  P的横坐标为X’,若X’=X则签名有效,反之则无效;

import sun.security.ec.ECPrivateKeyImpl;
import sun.security.ec.ECPublicKeyImpl;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECFieldFp;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.EllipticCurve;
import java.util.HashMap;
import java.util.Map;

public class EcDsaCode {
    private static final String KEY_ALGORITHM="EC";
    private static final int KEY_SIZE = 256;
    private static final String SIGNATURE_ALGORITHM = "SHA512withECDSA";

    //产生密钥对,获取密钥参数
    public static  Map<String,Object> initKey() throws Exception{
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        //初始化密钥对生成器
        keyPairGenerator.initialize(KEY_SIZE);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        //得到公钥和私钥
        ECPublicKey publicKey = (ECPublicKey) keyPair.getPublic();
        ECPrivateKey privateKey = (ECPrivateKey) keyPair.getPrivate();
        //获取私钥D
        BigInteger D = privateKey.getS();
        //得到公钥的横纵坐标
        BigInteger publicKeyX= publicKey.getW().getAffineX();
        BigInteger publicKeyY= publicKey.getW().getAffineY();
        //得到生成椭圆曲线的参数a,b
        java.security.spec.ECParameterSpec ecParams = privateKey.getParams();
        BigInteger curveA = ecParams.getCurve().getA();
        BigInteger curveB = ecParams.getCurve().getB();
        //获取此椭圆有限字段的素数 qq
        ECFieldFp fieldFp = (ECFieldFp) ecParams.getCurve().getField();
        BigInteger q = fieldFp.getP();
        //获取椭圆的基点的x,y值
        BigInteger coordinatesX = ecParams.getGenerator().getAffineX();
        BigInteger coordinatesY =  ecParams.getGenerator().getAffineY();
        //基点的阶
        BigInteger coordinatesG = ecParams.getOrder();
        //获取余因子
        int h = ecParams.getCofactor();

        Map<String, Object> initKeyMap = new HashMap<String,Object>();
        //椭圆曲线参数A,B
        initKeyMap.put("A",curveA);
        initKeyMap.put("B",curveB);
        //素数Q
        initKeyMap.put("Q",q);
        //G点的坐标
        initKeyMap.put("X",coordinatesX);
        initKeyMap.put("Y",coordinatesY);
        //N为G点的阶
        initKeyMap.put("N",coordinatesG);
        //H为余因子
        initKeyMap.put("H",h);
        //获取私钥
        initKeyMap.put("D",D);
        //获取公钥点的坐标
        initKeyMap.put("PUBKEY_X",publicKeyX);
        initKeyMap.put("PUBKEY_Y",publicKeyY);
        return initKeyMap;
    }

    //DATA是数据,Q是大素数q,A,B为椭圆曲线参数a,b,G为基点,N为点G的阶,H是余因子,X,Y是基点的坐标,PUBKEY_X,PUBKEY_Y是公钥(DG)的坐标,D是随机数私钥

    public static KeyPair generateKey(BigInteger Q, BigInteger A, BigInteger B, BigInteger N, int H, BigInteger X, BigInteger Y, BigInteger PUBKEY_X, BigInteger PUBKEY_Y, BigInteger D) throws Exception{
        //创建基于指定值的椭圆曲线域参数
        ECParameterSpec ecParameterSpec = new ECParameterSpec(new EllipticCurve(new ECFieldFp(Q),A,B),new ECPoint(X,Y),N,H);
        ECPublicKey publicKey = new ECPublicKeyImpl(new ECPoint(PUBKEY_X,PUBKEY_Y),ecParameterSpec);
        ECPrivateKey privateKey = new ECPrivateKeyImpl(D,ecParameterSpec);
        return new KeyPair(publicKey,privateKey);
    }
    public static   byte[] sign(byte[] data,PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(privateKey);
        signature.update(data);
        return signature.sign();
    }


    public static boolean verify(byte[] data,PublicKey publicKey, byte[] sign) throws Exception {
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(publicKey);
        signature.update(data);
        return signature.verify(sign);
    }



}
import sun.security.ec.ECPrivateKeyImpl;
import sun.security.ec.ECPublicKeyImpl;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECFieldFp;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.EllipticCurve;
import java.util.HashMap;
import java.util.Map;

public class EcDsaCode {
    private static final String KEY_ALGORITHM="EC";
    private static final int KEY_SIZE = 256;
    private static final String SIGNATURE_ALGORITHM = "SHA512withECDSA";

    //产生密钥对,获取密钥参数
    public static  Map<String,Object> initKey() throws Exception{
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        //初始化密钥对生成器
        keyPairGenerator.initialize(KEY_SIZE);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        //得到公钥和私钥
        ECPublicKey publicKey = (ECPublicKey) keyPair.getPublic();
        ECPrivateKey privateKey = (ECPrivateKey) keyPair.getPrivate();
        //获取私钥D
        BigInteger D = privateKey.getS();
        //得到公钥的横纵坐标
        BigInteger publicKeyX= publicKey.getW().getAffineX();
        BigInteger publicKeyY= publicKey.getW().getAffineY();
        //得到生成椭圆曲线的参数a,b
        java.security.spec.ECParameterSpec ecParams = privateKey.getParams();
        BigInteger curveA = ecParams.getCurve().getA();
        BigInteger curveB = ecParams.getCurve().getB();
        //获取此椭圆有限字段的素数 qq
        ECFieldFp fieldFp = (ECFieldFp) ecParams.getCurve().getField();
        BigInteger q = fieldFp.getP();
        //获取椭圆的基点的x,y值
        BigInteger coordinatesX = ecParams.getGenerator().getAffineX();
        BigInteger coordinatesY =  ecParams.getGenerator().getAffineY();
        //基点的阶
        BigInteger coordinatesG = ecParams.getOrder();
        //获取余因子
        int h = ecParams.getCofactor();

        Map<String, Object> initKeyMap = new HashMap<String,Object>();
        //椭圆曲线参数A,B
        initKeyMap.put("A",curveA);
        initKeyMap.put("B",curveB);
        //素数Q
        initKeyMap.put("Q",q);
        //G点的坐标
        initKeyMap.put("X",coordinatesX);
        initKeyMap.put("Y",coordinatesY);
        //N为G点的阶
        initKeyMap.put("N",coordinatesG);
        //H为余因子
        initKeyMap.put("H",h);
        //获取私钥
        initKeyMap.put("D",D);
        //获取公钥点的坐标
        initKeyMap.put("PUBKEY_X",publicKeyX);
        initKeyMap.put("PUBKEY_Y",publicKeyY);
        return initKeyMap;
    }

    //DATA是数据,Q是大素数q,A,B为椭圆曲线参数a,b,G为基点,N为点G的阶,H是余因子,X,Y是基点的坐标,PUBKEY_X,PUBKEY_Y是公钥(DG)的坐标,D是随机数私钥

    public static KeyPair generateKey(BigInteger Q, BigInteger A, BigInteger B, BigInteger N, int H, BigInteger X, BigInteger Y, BigInteger PUBKEY_X, BigInteger PUBKEY_Y, BigInteger D) throws Exception{
        //创建基于指定值的椭圆曲线域参数
        ECParameterSpec ecParameterSpec = new ECParameterSpec(new EllipticCurve(new ECFieldFp(Q),A,B),new ECPoint(X,Y),N,H);
        ECPublicKey publicKey = new ECPublicKeyImpl(new ECPoint(PUBKEY_X,PUBKEY_Y),ecParameterSpec);
        ECPrivateKey privateKey = new ECPrivateKeyImpl(D,ecParameterSpec);
        return new KeyPair(publicKey,privateKey);
    }
    public static   byte[] sign(byte[] data,PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(privateKey);
        signature.update(data);
        return signature.sign();
    }


    public static boolean verify(byte[] data,PublicKey publicKey, byte[] sign) throws Exception {
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(publicKey);
        signature.update(data);
        return signature.verify(sign);
    }



}



  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值