java数据安全 系列文章
1、【java数据安全】数据安全之加密解密(base64、MD、SHA、DES、AES、IDEA、PBE、DH、RSA、EIGamal)、数字签名(DSA、ECDSA)和数字证书介绍、应用示例详细介绍2、【java数据安全】base64与报文摘要MD(md5、sha、mac)简单介绍及应用场景、示例
3、【java数据安全】对称加密的5种(DES/3DES、AES、IDEA、PBE)常见算法的使用示例
4、【java数据安全】非对称加密算法(DH、RSA、EIGamal/DSA)的介绍、应用场景和示例
5、【java数据安全】数字签名的三种算法(RSA、DSA和ECDSA)使用示例
6、【java数据安全】数字信封介绍及实现流程
7、【java数据安全】国家商用密码介绍及对称加密、非对称加密使用示例(一)
8、【java数据安全】国家商用密码介绍及数字签名、密钥交换、密钥编码格式使用示例(二)
文章目录
- java数据安全 系列文章
- 一、maven依赖
- 二、数字签名算法介绍、应用场景和示例
- 1、介绍
- 2、RSA签名
- 1)、介绍
- 2)、jdk示例
- 1、实现源码
- 2、testNG测试
- 3、DSA签名
- 1)、介绍
- 2)、jdk示例
- 1、实现源码
- 2、testNG测试
- 4、ECDSA签名
- 1)、介绍
- 2)、jdk示例
- 1、实现源码
- 2、testNG测试
- 3、签名服务实现
本文简单介绍了数字签名常用的三种算法以及具体使用示例。
一、maven依赖
org.testng
testng
6.9.10
二、数字签名算法介绍、应用场景和示例
1、介绍
数字签名算法是一种带有密钥的消息摘要算法,使用的是非对称加密算法与消息摘要算法的结合。
数字签名算法要求能够验证数据的完整性、数据的来源以及防抵赖。消息摘要算法是验证数据完整性的最佳算法;防抵赖靠签名来确保,也是基于消息摘要的。
数字签名算法包含签名和验证两个重要步骤,遵循“私钥签名,公钥验证”的签名验证方式。签名时需要私钥和待签名的数据;验证时需要公钥、签名值和待签名数据,其核心就是消息摘要信息,签名值与消息摘要值一样,通常以十六进制字符串来表示。简单来说先对原始数据做摘要处理,然后使用私钥对摘要值签名;验证时使用公钥验证消息的摘要值。
数字签名常用算法有RSA、DSA、ECDSA,其中RSA是基于整数因子分解问题,DSA和ECDSA则是基于离散对数问题。RSA是目前数字签名应用最广泛的算法。
2、RSA签名
1)、介绍
RSA数字签名算法与加密算法一致,统称RSA。RSA数字签名算法分为MD和SHA两个系列,MD系列主要包含MD2withRSA和MD5withRSA;SHA系列包含SHA1withRSA、SHA224withRSA、SHA256withRSA、SHA384withRSA、SHA512withRSA。
2)、jdk示例
1、实现源码
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
/**
* @author alan 2018年11月20日
*/
public class RSACoder {
/**
* 数字签名 密钥算法
*/
public static final String KEY_ALGORITHM = "RSA";
/**
* 数字签名 签名/验证算法
*/
public static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
/**
* 公钥
*/
private static final String PUBLIC_KEY = "RSAPublicKey";
/**
* 私钥
*/
private static final String PRIVATE_KEY = "RSAPrivateKey";
/**
* RSA密钥长度 默认1024位, 密钥长度必须是64的倍数, 范围在512至65536位之间。
*/
private static final int KEY_SIZE = 512;
/**
* 签名
*
* @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);
// 初始化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 verify(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);
// 初始化Signature
signature.initVerify(pubKey);
// 更新
signature.update(data);
// 验证
return signature.verify(sign);
}
/**
* 取得私钥
*
* @param keyMap
* @return
* @throws Exception
*/
public static byte[] getPrivateKey(Map keyMap) throws Exception {
Key key = (Key) keyMap.get(PRIVATE_KEY);
return key.getEncoded();
}
/**
* 取得公钥
*
* @param keyMap
* @return
* @throws Exception
*/
public static byte[] getPublicKey(Map keyMap) throws Exception {
Key key = (Key) keyMap.get(PUBLIC_KEY);
return key.getEncoded();
}
/**
* 初始化密钥
*
* @return Map 密钥对儿 Map
* @throws Exception
*/
public static Map initKey() throws Exception {
// 实例化密钥对儿生成器
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
// 初始化密钥对儿生成器
keyPairGen.initialize(KEY_SIZE);
// 生成密钥对儿
KeyPair keyPair = keyPairGen.generateKeyPair();
// 公钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// 私钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
// 封装密钥
Map keyMap = new HashMap(2);
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
}
2、testNG测试
import static org.testng.Assert.assertTrue;
import java.util.Map;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
* @author alan 2018年11月20日
*/
public class RSACoderTest {
/**
* 公钥
*/
private byte[] publicKey;
/**
* 私钥
*/
private byte[] privateKey;
/**
* 初始化密钥
*
* @throws Exception
*/
@BeforeMethod
public void initKey() throws Exception {
Map keyMap = RSACoder.initKey();
publicKey = RSACoder.getPublicKey(keyMap);
privateKey = RSACoder.getPrivateKey(keyMap);
System.err.println("公钥: n" + Base64.encodeBase64String(publicKey));
System.err.println("私钥: n" + Base64.encodeBase64String(privateKey));
}
/**
* 校验
*
* @throws Exception
*/
@Test
public void testSign() throws Exception {
String inputStr = "RSA数字签名";
byte[] data = inputStr.getBytes();
// 产生签名
byte[] sign = RSACoder.sign(data, privateKey);
System.err.println("签名:n" + Hex.encodeHexString(sign));
// 验证签名
boolean status = RSACoder.verify(data, publicKey, sign);
System.err.println("状态:n" + status);
assertTrue(status);
}
}
3、DSA签名
1)、介绍
DSA本质上是EIGamal数字签名算法,与RSA算法是数字证书中两种常见的算法,与RSA不同的是DSA仅仅包含数字签名算法,使用DSA算法的数字证书无法进行加密通信,而RSA算法即可加密也可签名。
DSA算法签名长度与密钥长度无关。
2)、jdk示例
1、实现源码
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
/**
* @author alan 2018年11月20日
*/
public class DSACoder {
/**
* 数字签名密钥算法
*/
public static final String ALGORITHM = "DSA";
/**
* 数字签名 签名/验证算法
*/
public static final String SIGNATURE_ALGORITHM = "SHA1withDSA";
/**
* 公钥
*/
private static final String PUBLIC_KEY = "DSAPublicKey";
/**
* 私钥
*/
private static final String PRIVATE_KEY = "DSAPrivateKey";
/**
* 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(ALGORITHM);
// 生成私钥对象
PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 实例化Signature
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
// 初始化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 verify(byte[] data, byte[] publicKey, byte[] sign) throws Exception {
// 还原公钥
// 转换公钥材料
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
// 实例化密钥工厂
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
// 取公钥匙对象
PublicKey pubKey = keyFactory.generatePublic(keySpec);
// 实例话Signature
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
// 初始化Signature
signature.initVerify(pubKey);
// 更新
signature.update(data);
// 验证
return signature.verify(sign);
}
/**
* 生成密钥
*
* @return 密钥对象
* @throws Exception
*/
public static Map initKey() throws Exception {
// 初始化密钥对儿生成器
KeyPairGenerator keygen = KeyPairGenerator.getInstance(ALGORITHM);
// 实例化密钥对儿生成器
keygen.initialize(KEY_SIZE, new SecureRandom());
// 实例化密钥对儿
KeyPair keys = keygen.genKeyPair();
DSAPublicKey publicKey = (DSAPublicKey) keys.getPublic();
DSAPrivateKey privateKey = (DSAPrivateKey) keys.getPrivate();
// 封装密钥
Map map = new HashMap(2);
map.put(PUBLIC_KEY, publicKey);
map.put(PRIVATE_KEY, privateKey);
return map;
}
/**
* 取得私钥
*
* @param keyMap
* 密钥Map
* @return byte[] 私钥
* @throws Exception
*/
public static byte[] getPrivateKey(Map keyMap) throws Exception {
Key key = (Key) keyMap.get(PRIVATE_KEY);
return key.getEncoded();
}
/**
* 取得公钥
*
* @param keyMap
* 密钥Map
* @return byte[] 公钥
* @throws Exception
*/
public static byte[] getPublicKey(Map keyMap) throws Exception {
Key key = (Key) keyMap.get(PUBLIC_KEY);
return key.getEncoded();
}
}
2、testNG测试
import static org.testng.Assert.assertTrue;
import java.util.Map;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
* @author alan
* 2018年11月20日
*/
public class DSACoderTest {
/**
* 公钥
*/
private byte[] publicKey;
/**
* 私钥
*/
private byte[] privateKey;
/**
* 初始化密钥
*
* @throws Exception
*/
@BeforeMethod
public void initKey() throws Exception {
Map keyMap = DSACoder.initKey();
publicKey = DSACoder.getPublicKey(keyMap);
privateKey = DSACoder.getPrivateKey(keyMap);
System.err.println("公钥: n" + Base64.encodeBase64String(publicKey));
System.err.println("私钥: n" + Base64.encodeBase64String(privateKey));
}
/**
* 校验签名
*
* @throws Exception
*/
@Test
public void test() throws Exception {
String inputStr = "DSA数字签名";
byte[] data = inputStr.getBytes();
// 产生签名
byte[] sign = DSACoder.sign(data, privateKey);
System.err.println("签名:r" + Hex.encodeHexString(sign));
// 验证签名
boolean status = DSACoder.verify(data, publicKey, sign);
System.err.println("状态:r" + status);
assertTrue(status);
}
}
4、ECDSA签名
1)、介绍
ECDSA相对于传统的签名算法,速度更快、强度更高、签名更短优点,其用途越来越广泛。
2)、jdk示例
1、实现源码
import java.math.BigInteger;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;
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.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
/**
* @author alan 2018年11月20日
*/
public class ECDSACoder {
/**
* 数字签名 密钥算法
*/
private static final String KEY_ALGORITHM = "ECDSA";
/**
* 数字签名 签名/验证算法
*
* Bouncy Castle支持以下7种算法 NONEwithECDSA RIPEMD160withECDSA SHA1withECDSA
* SHA224withECDSA SHA256withECDSA SHA384withECDSA SHA512withECDSA
*/
private static final String SIGNATURE_ALGORITHM = "SHA512withECDSA";
/**
* 公钥
*/
private static final String PUBLIC_KEY = "ECDSAPublicKey";
/**
* 私钥
*/
private static final String PRIVATE_KEY = "ECDSAPrivateKey";
/**
* 初始化密钥
*
* @return Map 密钥Map
* @throws Exception
*/
public static Map initKey() throws Exception {
// 加入BouncyCastleProvider支持
Security.addProvider(new BouncyCastleProvider());
BigInteger p = new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839");
ECFieldFp ecFieldFp = new ECFieldFp(p);
BigInteger a = new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16);
BigInteger b = new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16);
EllipticCurve ellipticCurve = new EllipticCurve(ecFieldFp, a, b);
BigInteger x = new BigInteger("110282003749548856476348533541186204577905061504881242240149511594420911");
BigInteger y = new BigInteger("869078407435509378747351873793058868500210384946040694651368759217025454");
ECPoint g = new ECPoint(x, y);
BigInteger n = new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307");
ECParameterSpec ecParameterSpec = new ECParameterSpec(ellipticCurve, g, n, 1);
// 实例化密钥对儿生成器
KeyPairGenerator kpg = KeyPairGenerator.getInstance(KEY_ALGORITHM);
// 初始化密钥对儿生成器
kpg.initialize(ecParameterSpec, new SecureRandom());
// 生成密钥对儿
KeyPair keypair = kpg.generateKeyPair();
ECPublicKey publicKey = (ECPublicKey) keypair.getPublic();
ECPrivateKey privateKey = (ECPrivateKey) keypair.getPrivate();
// 封装密钥
Map map = new HashMap(2);
map.put(PUBLIC_KEY, publicKey);
map.put(PRIVATE_KEY, privateKey);
return map;
}
/**
* 取得私钥
*
* @param keyMap
* 密钥Map
* @return byte[] 私钥
* @throws Exception
*/
public static byte[] getPrivateKey(Map keyMap) throws Exception {
Key key = (Key) keyMap.get(PRIVATE_KEY);
return key.getEncoded();
}
/**
* 取得公钥
*
* @param keyMap
* 密钥Map
* @return byte[] 公钥
* @throws Exception
*/
public static byte[] getPublicKey(Map keyMap) throws Exception {
Key key = (Key) keyMap.get(PUBLIC_KEY);
return key.getEncoded();
}
/**
* 签名
*
* @param data
* 待签名数据
* @param privateKey
* 私钥
* @return byte[] 数字签名
* @throws Exception
*/
public static byte[] sign(byte[] data, byte[] privateKey) throws Exception {
// 加入BouncyCastleProvider支持
Security.addProvider(new BouncyCastleProvider());
// 转换私钥材料
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey);
// 实例化密钥工厂
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 取私钥匙对象
PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 实例化Signature
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
// 初始化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 verify(byte[] data, byte[] publicKey, byte[] sign) throws Exception {
// 加入BouncyCastleProvider支持
Security.addProvider(new BouncyCastleProvider());
// 转换公钥材料
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
// 实例化密钥工厂
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 生成公钥
PublicKey pubKey = keyFactory.generatePublic(keySpec);
// 实例化Signature
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
// 初始化Signature
signature.initVerify(pubKey);
// 更新
signature.update(data);
// 验证
return signature.verify(sign);
}
}
2、testNG测试
import static org.testng.Assert.assertTrue;
import java.util.Map;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
* @author alan 2018年11月20日
*/
public class ECDSACoderTest {
/**
* 公钥
*/
private byte[] publicKey;
/**
* 私钥
*/
private byte[] privateKey;
/**
* 初始化密钥
*
* @throws Exception
*/
@BeforeMethod
public void initKey() throws Exception {
Map keyMap = ECDSACoder.initKey();
publicKey = ECDSACoder.getPublicKey(keyMap);
privateKey = ECDSACoder.getPrivateKey(keyMap);
System.err.println("公钥: n" + Base64.encodeBase64String(publicKey));
System.err.println("私钥: n" + Base64.encodeBase64String(privateKey));
}
/**
* 校验
*
* @throws Exception
*/
@Test
public void test() throws Exception {
String inputStr = "ECDSA 数字签名";
byte[] data = inputStr.getBytes();
// 产生签名
byte[] sign = ECDSACoder.sign(data, privateKey);
System.err.println("签名:r" + Hex.encodeHexString(sign));
// 验证签名
boolean status = ECDSACoder.verify(data, publicKey, sign);
System.err.println("状态:r" + status);
assertTrue(status);
}
}
3、签名服务实现
import java.security.InvalidKeyException;
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.SignatureException;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.codec.binary.Hex;
/**
* @author alan
* 2018年11月20日
*/
public class ECDSASignatrueService {
private Map key = null;
private String PRIVATEKEY = "privatekey";
private String PUBLICKEY = "publickey";
private String ECAlGORIYTHMS = "EC";
// ECDSA: 椭圆曲线数字签名算法
private String SIGNATUREALGORIYTHMS = "SHA1withECDSA";
public Map getKey() {
return key;
}
/**
* 通过构造函数生成密钥对
*/
private ECDSASignatrueService() {
key = new HashMap();
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ECAlGORIYTHMS);
SecureRandom secrand = new SecureRandom();
secrand.setSeed("www.okcard.com".getBytes()); // 初始化随机产生器
keyPairGenerator.initialize(256, secrand);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
ECPublicKey ecPublicKey = (ECPublicKey) keyPair.getPublic();
ECPrivateKey ecPrivateKey = (ECPrivateKey) keyPair.getPrivate();
key.put(PUBLICKEY, ecPublicKey);
key.put(PRIVATEKEY, ecPrivateKey);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
/**
* 针对需要签名的字符进行签名
*
* @param message
* @return
*/
public byte[] doSignature(String message) {
byte[] result = null;
ECPrivateKey ecPrivateKey = (ECPrivateKey) key.get(PRIVATEKEY);
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(ecPrivateKey.getEncoded());
try {
KeyFactory keyFactory = KeyFactory.getInstance(ECAlGORIYTHMS);
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Signature signature = Signature.getInstance(SIGNATUREALGORIYTHMS);
signature.initSign(privateKey);
signature.update(message.getBytes());
result = signature.sign();
System.out.println("jdk 加密结果 : " + Hex.encodeHexString(result));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (SignatureException e) {
e.printStackTrace();
}
return result;
}
/**
* 针对签名的字符使用公钥进行验证
*
* @param message
* @param signatureMessage
* @param eCPublicKey
* @return
*/
public boolean verify(String message, byte[] signatureMessage, ECPublicKey eCPublicKey) {
boolean flag = true;
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(eCPublicKey.getEncoded());
try {
KeyFactory keyFactory = KeyFactory.getInstance(ECAlGORIYTHMS);
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
Signature signature = Signature.getInstance(SIGNATUREALGORIYTHMS);
signature.initVerify(publicKey);
signature.update(message.getBytes());
flag = signature.verify(signatureMessage);
System.out.println("jdk 签名验证结果 : " + flag);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (SignatureException e) {
e.printStackTrace();
}
return flag;
}
public static void main(String[] args) {
ECDSASignatrueService eCDSASignatrueService = new ECDSASignatrueService();
String message = "test a signatrue string";
eCDSASignatrueService.verify(message, eCDSASignatrueService.doSignature(message),
(ECPublicKey) eCDSASignatrueService.getKey().get(eCDSASignatrueService.PUBLICKEY));
}
}
以上,简单介绍了数字签名常用的三种算法以及具体使用示例。
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
题意:计算n!最后一位不为0的数 解题思路:1*2*3*……*n,每次乘完一个数后,把末尾0去掉,然后模上一个数,这样算出来的数肯定是最后一位不为0的数。。 注意这里模的数不能太小,同时也不能太大,太小可能会影响乘积的效果,譬如可能出现0的情况被之前的…