java数字签名
1.密钥对生成类:RSASignGenerate.java
package pers.li;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;
/**
* create by lishengbo on 2018-04-24 17:48
* <p>
* 数字签名生成工具类
*/
public class RSASignGenerate {
/**
* RSA -- 数字签名生成公私钥
* 公钥公布出去,私钥自己留着
* @Param name-- 针对哪个公司生成的名称
* @return
*/
public static Map<String, String> GenerateKeyPair(String name) {
Map<String, String> map = new HashMap<>();
try {
java.security.KeyPairGenerator keygen = java.security.KeyPairGenerator
.getInstance("RSA");
SecureRandom secrand = new SecureRandom();
// 初始化随机产生器
secrand.setSeed(name.getBytes());
keygen.initialize(512, secrand);
KeyPair keys = keygen.genKeyPair();
PublicKey pubkey = keys.getPublic();
PrivateKey prikey = keys.getPrivate();
String pubKey = bytesToHexStr(pubkey.getEncoded());
String priKey = bytesToHexStr(prikey.getEncoded());
System.out.println("pubKey=" + pubKey);
System.out.println("priKey=" + priKey);
map.put("priKey", priKey);
map.put("pubKey", pubKey);
System.out.println("生成密钥对成功");
} catch (java.lang.Exception e) {
e.printStackTrace();
System.out.println("生成密钥对失败");
};
return map;
}
/**
* Transform the specified byte into a Hex String form.
*/
public static final String bytesToHexStr(byte[] bcd) {
StringBuffer s = new StringBuffer(bcd.length * 2);
for (int i = 0; i < bcd.length; i++) {
s.append(bcdLookup[(bcd[i] >>> 4) & 0x0f]);
s.append(bcdLookup[bcd[i] & 0x0f]);
}
return s.toString();
}
/**
* Transform the specified Hex String into a byte array.
*/
public static final byte[] hexStrToBytes(String s) {
byte[] bytes;
bytes = new byte[s.length() / 2];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) Integer.parseInt(s.substring(2 * i, 2 * i + 2),
16);
}
return bytes;
}
private static final char[] bcdLookup = {'0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
}
2.私钥签名:SignatureData.js
package pers.li;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
/**
* 编写发送者的功能:首先通过私钥加密待输出数据Data,并输出Data和签名后的Data;
*/
public static String sign(String priKey,String info) {
try {
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(hexStrToBytes(priKey));
KeyFactory keyf = KeyFactory.getInstance("RSA");
PrivateKey myprikey = keyf.generatePrivate(priPKCS8);
// 用私钥对信息生成数字签名
java.security.Signature signet = java.security.Signature.getInstance("MD5withRSA");
signet.initSign(myprikey);
// 要签名的信息
signet.update(info.getBytes("ISO-8859-1"));
// 对信息的数字签名
byte[] signed = signet.sign();
System.out.println("signed(签名内容)原值=" + bytesToHexStr(signed));
System.out.println("info(原值)=" + info);
System.out.println("签名并生成文件成功");
return bytesToHexStr(signed);
} catch (java.lang.Exception e) {
e.printStackTrace();
System.out.println("签名并生成文件失败");
};
return null;
}
/**
* Transform the specified byte into a Hex String form.
*/
public static final String bytesToHexStr(byte[] bcd) {
StringBuffer s = new StringBuffer(bcd.length * 2);
for (int i = 0; i < bcd.length; i++) {
s.append(bcdLookup[(bcd[i] >>> 4) & 0x0f]);
s.append(bcdLookup[bcd[i] & 0x0f]);
}
return s.toString();
}
/**
* Transform the specified Hex String into a byte array.
*/
public static final byte[] hexStrToBytes(String s) {
byte[] bytes;
bytes = new byte[s.length() / 2];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) Integer.parseInt(s.substring(2 * i, 2 * i + 2),
16);
}
return bytes;
}
private static final char[] bcdLookup = {'0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
}
3.公钥解密:VerifySignature.java
package pers.li;
import java.security.DomainCombiner;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import static pers.li.GenerateKeyPair.hexStrToBytes;
/**
* 编写接收者的功能:使用发送者的公钥来验证发送过来的加密Data,判断签名的合法性
* 签名并生成文件成功
*/
public class VerifySignature {
public static boolean verifySign(String pubkeyvalue, String info, String sign) {
try {
//这是GenerateKeyPair输出的公钥编码
X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(hexStrToBytes(pubkeyvalue));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(bobPubKeySpec);
//这是SignatureData输出的数字签名
byte[] signed = hexStrToBytes(sign);
java.security.Signature signetcheck = java.security.Signature.getInstance("MD5withRSA");
signetcheck.initVerify(pubKey);
signetcheck.update(info.getBytes());
if (signetcheck.verify(signed)) {
System.out.println("签名正常");
} else {
System.out.println("非签名正常");
}
return signetcheck.verify(signed);
} catch (java.lang.Exception e) {
e.printStackTrace();
}
return false;
}
}
4.测试:test.java
package pers.li;
import java.util.Map;
public class test {
public static void main(String[] args) {
Map<String, String> map = RSASignGenerate.GenerateKeyPair("www.baidu.com");
String priKey = map.get("priKey");
String pubKey = map.get("pubKey");
String info = "orderId=10dkfadsfksdkssdkd&amount=80&orderTime=20060509";
String signed = SignatureData.sign(priKey, info);
boolean b = VerifySignature.verifySign(pubKey, info, signed);
}
}
5.测试结果: