@TOC
该算法是微软操作系统及办公软件的序列号验证算法。
ECDSA(Elliptic Curve Digital Signature Algorithm, 椭圆曲线数字签名算法) 于1999年作为ANSI标准, 并于2000年成为IEEE和NIST标准。
ECDSA算法具有速度快、强度高、签名短等有点。
Java中未对该算法做实现, 而在Bouncy Castle中有该算法实现。
下面的表格说明了实现细节。
算法 | 密钥长度 | 密钥默认长度 | 签名长度 | 备注 |
---|---|---|---|---|
NONEwithECDSA、RIPEMD160withECDSA、SHA1withECDSA、SHA224withECDSA、SHA256withECDSA、SHA384withECDSA、SHA512withECDSA | - | - | 128、160、160、224、256、384、512 | Bouncy Castle实现 |
基于Bouncy Castle的 ECDSA算法实现
package com.calvin.android.demo2.secrity;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
/**
* Author:cl
* Email:[email protected]
* Date:20-10-21
*/
//java – 在BouncyCastle上使用数字签名算法(ECDSA)实现的椭圆曲线 http://www.voidcn.com/article/p-vmamxfcn-bup.html
public class ECDSACoder {
/**
* 数字签名密钥算法
*/
public static final String KEY_ALGORITHM = "ECDSA";
/**
* 数字签名
* 签名/验证算法
*/
public static final String SIGNATURE_ALGORITHM = "SHA1withECDSA";
//公钥 Map Key
private static final String PUBLIC_KEY = "ECDSAPublicKey";
//私钥Map key
private static final String PRIVATE_KEY = "ECDSAPrivateKey";
/**
* DSA密钥长度,默认1024位,密钥长度必须是64的倍数,范围512~1024位之间
*/
private static final int KEY_SIZE = 1024;
/**
* 签名
* @param data 待签名数据
* @param privateKey 私钥
* @return byte[] 数字签名
* @throws Exception 异常
*/
public static byte[] sign(byte[] data, byte[] privateKey) throws Exception {
//转换私钥材料
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey);
//实例化密钥工厂
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//取私钥对象
PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
//实例化Signature
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM, "BC");
//初始化Signature
signature.initSign(priKey);
//更新
signature.update(data);
//签名
return signature.sign();
}
/**
* 校验
* @param data 待校验数据
* @param publicKey 公钥
* @param sign 数字签名
* @return boolean 校验成功返回true,校验失败返回false
* @throws Exception
*/
public static boolean verity(byte[] data, byte[] publicKey, byte[] sign) throws Exception{
//转换公钥材料
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
//实例化密钥工厂
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//生成公钥
PublicKey pubKey = keyFactory.generatePublic(keySpec);
//实例化Signature
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM, "BC");
//初始化Signature
signature.initVerify(pubKey);
//更新
signature.update(data);
//校验证
return signature.verify(sign);
}
public static Map<String, Object> initKey() throws Exception {
//实例化BC Provider
Provider bcProvider = new BouncyCastleProvider();
Security.removeProvider("BC");
Security.addProvider(bcProvider);
ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("B-571");
//实例化密钥对生成器
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM, "BC");
keyPairGen.initialize(ecSpec, new SecureRandom());
//生成密钥对
KeyPair keyPair = keyPairGen.generateKeyPair();
//公钥
PublicKey publicKey = (PublicKey)keyPair.getPublic();
//私钥
PrivateKey privateKey = (PrivateKey)keyPair.getPrivate();
//封装密钥
Map<String, Object> keyMap = new HashMap<>(2);
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
public static byte[] getPublicKey(Map<String, Object> keyMap){
return ((Key)keyMap.get(PUBLIC_KEY)).getEncoded();
}
public static byte[] getPrivateKey(Map<String, Object> keyMap){
return ((Key)keyMap.get(PRIVATE_KEY)).getEncoded();
}
}
@Test
public void ecdsaSignTest() throws Exception {
//初始化密钥
Map<String, Object> keyMap = ECDSACoder.initKey();
byte[] publicKey = ECDSACoder.getPublicKey(keyMap);
byte[] privateKey = ECDSACoder.getPrivateKey(keyMap);
System.out.println("ECDSA公钥:\t"+Base64.encodeToString(publicKey, Base64.DEFAULT));
System.out.println("ECDSA私钥:\t"+Base64.encodeToString(privateKey, Base64.DEFAULT));
String inputStr = "ECDSA数字签名";
byte[] data = inputStr.getBytes();
//产生签名
byte[] sign = ECDSACoder.sign(data, privateKey);
System.out.println("ECDSA签名:\t"+ Hex.toHexString(sign));
//验证签名
boolean status = ECDSACoder.verity(data, publicKey, sign);
System.out.println("ECDSA验签状态:\t"+ status);
assertTrue(status);
}
2020-10-21 15:41:36.454 16472-16487/com.calvin.android.demo2 I/System.out: ECDSA公钥: MIGnMBAGByqGSM49AgEGBSuBBAAnA4GSAAQA9ile2ZpcTRb3y22xpaxeMcqJ0GuU8GuovBxpVnAC
2020-10-21 15:41:36.455 16472-16487/com.calvin.android.demo2 I/System.out: xeEjE0UdFe8V+8T0cCrhCw8zkJjvv+lpAlX+NtedI1oIL9APgIzOFEACBNB5qQwFYQn9hh8PA5P+
2020-10-21 15:41:36.455 16472-16487/com.calvin.android.demo2 I/System.out: y+QXTgw6ATLGPfxg73U7Ydp51ZPXLt5VivuN+dOynDpoY8nJhIuhC4N6aNde2P6R+0u8mz2HAJY=
2020-10-21 15:41:36.455 16472-16487/com.calvin.android.demo2 I/System.out: ECDSA私钥: MIIBCQIBADAQBgcqhkjOPQIBBgUrgQQAJwSB8TCB7gIBAQRIA32LqVgupwwD8q7eItT6vM7X1xB8
2020-10-21 15:41:36.455 16472-16487/com.calvin.android.demo2 I/System.out: OUZnP222ZEhIvLkHciYb7AQrRVX1XRuH2a8tX0LyH6YRHDBe9aPZkxyBpzkSGuaV9Ez8oAcGBSuB
2020-10-21 15:41:36.455 16472-16487/com.calvin.android.demo2 I/System.out: BAAnoYGVA4GSAAQA9ile2ZpcTRb3y22xpaxeMcqJ0GuU8GuovBxpVnACxeEjE0UdFe8V+8T0cCrh
2020-10-21 15:41:36.455 16472-16487/com.calvin.android.demo2 I/System.out: Cw8zkJjvv+lpAlX+NtedI1oIL9APgIzOFEACBNB5qQwFYQn9hh8PA5P+y+QXTgw6ATLGPfxg73U7
2020-10-21 15:41:36.455 16472-16487/com.calvin.android.demo2 I/System.out: Ydp51ZPXLt5VivuN+dOynDpoY8nJhIuhC4N6aNde2P6R+0u8mz2HAJY=
2020-10-21 15:41:36.705 16472-16487/com.calvin.android.demo2 I/System.out: ECDSA签名: 3081940248019e556404e8cfae0f752bef094de22d35677f231aa2262f353371d1f518b7429b9f49390a19fd212652fb1b271d3bd2170f8b23594d81e4779f61aff13f130d104613479e91ad76024800e4eafe20e9980e0a402693207ec11546f9c2a1fca1aa6e25f9de0b8416fd91b03b62e7090592dda26dd094a2b1338e6801b439cf5072ada0522daa2ef8ecc5c422f46a4efb2b3c
2020-10-21 15:41:36.854 16472-16487/com.calvin.android.demo2 I/System.out: ECDSA验签状态: true