ECDSA数字签名算法及JAVA实现
2017-12-26 16:58
316 查看
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);
}
}
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.getC 996f urve().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); } }
相关文章推荐
- SM2算法第十五篇:ECDSA数字签名算法的C语言实现
- java RSA/DSA/ECDSA实现数字签名
- Java实现数字签名算法
- Java实现RSA数字签名算法
- java RSA/DSA/ECDSA实现数字签名
- 常用数字签名算法RSA与DSA的Java程序内实现示例
- SM2算法第二十五篇:ECDSA数字签名算法原理与实现
- 使用 .NET实现JavaTM Pet Store J2EETM 蓝图应用程序
- 利用Java实现网络通信
- 在java中实现对FORM的打印功能
- 如何在Java应用程序中实现copy图像功能。
- Java图形设计中,利用Bresenham算法实现直线线型,线宽的控制(NO 2D GRAPHICS)
- 从一个ConnectionPool的实现看design pattern的运用 (source code for Java 1.1)
- 用Java实现的设计模式系列(1)-Factory
- dom规范和java中的实现(三)
- dom规范和java中的实现(二)
- IBM Java Jvm GC实现内幕
- 用 Java 实现回调例程
- 在Java applet中如何实现一个模式对话框?
- 利用Java实现串口全双工通讯