最近项目增加新功能,通过与其他公司的功能进行互动,数据要求传送字节数长度.以及通过数字验签验证数据完整性,且两公司项目编码不同,一个UTF-8,一个gb2312,然后,悲催开始了..
首先是加签验签类的代码,采用rsa1024算法
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.GeneralSecurityException;
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.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.ArrayUtils;
import org.apache.log4j.Logger;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import sun.security.pkcs.PKCS8Key;
public class RsaEncryptSign {
private static final Logger logger = Logger.getLogger(ContractInfo.class);
/**
* 私钥
*/
private RSAPrivateKey privateKey;
/**
* 公钥
*/
private RSAPublicKey publicKey;
/**
* 签名私钥
*/
private static PrivateKey privateKeyV;
/**
* 签名公钥
*/
private PublicKey publicKeyV;
/**
* 字节数据转字符串专用集合
*/
private static final char[] HEX_CHAR= {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
/**
* 获取私钥
* @return 当前的私钥对象
*/
public RSAPrivateKey getPrivateKey() {
return privateKey;
}
/**
* 获取公钥
* @return 当前的公钥对象
*/
public RSAPublicKey getPublicKey() {
return publicKey;
}
/**
* 获取签名私钥
* @return 当前的私钥对象
*/
public PrivateKey getPrivateKeyV() {
return privateKeyV;
}
/**
* 获取签名公钥
* @return 当前的公钥对象
*/
public PublicKey getPublicKeyV() {
return publicKeyV;
}
/**
* 随机生成密钥对
*/
public void genKeyPair(){
KeyPairGenerator keyPairGen= null;
try {
keyPairGen= KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
keyPairGen.initialize(1024, new SecureRandom());
KeyPair keyPair= keyPairGen.generateKeyPair();
this.privateKey= (RSAPrivateKey) keyPair.getPrivate();
this.publicKey= (RSAPublicKey) keyPair.getPublic();
System.out.println("私钥" + this.privateKey);
System.out.println("公钥"+this.publicKey);
}
/**
* 从文件中输入流中加载公钥
* @param in 公钥输入流
* @throws Exception 加载公钥时产生的异常
*/
public String loadPublicKey(FileInputStream file) throws Exception{
StringBuilder sb= new StringBuilder();
try {
//加载公钥文件
BufferedReader br= new BufferedReader(new InputStreamReader(file,"gb2312"));
String readLine= null;
while((readLine= br.readLine())!=null){
if(readLine.charAt(0)=='-'){
continue;
}else{
sb.append(readLine);
sb.append('\r');
}
}
//将获取到的公钥字符串传入加载为公钥
loadPublicKey(sb.toString());
} catch (IOException e) {
throw new Exception("公钥数据流读取错误");
} catch (NullPointerException e) {
throw new Exception("公钥输入流为空");
}
return sb.toString();
}
/**
* 从字符串中加载公钥
* @param publicKeyStr 公钥数据字符串
* @throws Exception 加载公钥时产生的异常
*/
public void loadPublicKey(String publicKeyStr) throws Exception{
try {
BASE64Decoder base64Decoder= new BASE64Decoder();
byte[] buffer= base64Decoder.decodeBuffer(publicKeyStr);
KeyFactory keyFactory= KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec= new X509EncodedKeySpec(buffer);
this.publicKey= (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (NoSuchAlgorithmException e) {
throw new Exception("无此算法");
} catch (InvalidKeySpecException e) {
throw new Exception("公钥非法");
} catch (IOException e) {
throw new Exception("公钥数据内容读取错误");
} catch (NullPointerException e) {
throw new Exception("公钥数据为空");
}
}
/**
* 从字符串中加载签名公钥
* @param publicKeyStr 公钥数据字符串
* @throws Exception 加载公钥时产生的异常
*/
public PublicKey loadPublicKeyV(String publicKeyStr) throws Exception{
try {
BASE64Decoder base64Decoder= new BASE64Decoder();
byte[] buffer= base64Decoder.decodeBuffer(publicKeyStr);
KeyFactory keyFactory= KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec= new X509EncodedKeySpec(buffer);
this.publicKeyV= (PublicKey) keyFactory.generatePublic(keySpec);
} catch (NoSuchAlgorithmException e) {
throw new Exception("无此算法");
} catch (InvalidKeySpecException e) {
throw new Exception("签名公钥非法");
} catch (IOException e) {
throw new Exception("签名公钥数据内容读取错误");
} catch (NullPointerException e) {
throw new Exception("签名公钥数据为空");
}
return this.publicKeyV;
}
/**
* 从文件中加载私钥
* @param keyFileName 私钥文件名
* @return 是否成功
* @throws Exception
*/
public String loadPrivateKey(FileInputStream file) throws Exception{
StringBuilder sb= new StringBuilder();
try {
//获取私钥文件中的内容
BufferedReader br= new BufferedReader(new InputStreamReader(file,"gb2312"));
String readLine= null;
while((readLine= br.readLine())!=null){
if(readLine.charAt(0)=='-'){
continue;
}else{
sb.append(readLine);
sb.append('\r');
}
}
loadPrivateKey(sb.toString());
} catch (IOException e) {
throw new Exception("私钥数据读取错误");
} catch (NullPointerException e) {
throw new Exception("私钥输入流为空");
}
return sb.toString();
}
/**
* 加载私钥
* @param privateKeyStr私钥字符串
* @throws Exception
*/
public void loadPrivateKey(String privateKeyStr) throws Exception{
try {
BASE64Decoder base64Decoder= new BASE64Decoder();
byte[] buffer= base64Decoder.decodeBuffer(privateKeyStr);
PKCS8EncodedKeySpec keySpec= new PKCS8EncodedKeySpec(buffer);
KeyFactory keyFactory= KeyFactory.getInstance("RSA");
this.privateKey= (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
} catch (NoSuchAlgorithmException e) {
throw new Exception("无此算法");
} catch (InvalidKeySpecException e) {
e.printStackTrace();
throw new Exception("私钥非法");
} catch (IOException e) {
throw new Exception("私钥数据内容读取错误");
} catch (NullPointerException e) {
throw new Exception("私钥数据为空");
}
}
/**
* 加载签名私钥
* @param privateKeyStr私钥字符串
* @return
* @throws Exception
*/
public PrivateKey loadPrivateKeyV(String privateKeyStr) throws Exception{
try {
BASE64Decoder base64Decoder= new BASE64Decoder();
byte[] buffer= base64Decoder.decodeBuffer(privateKeyStr);
PKCS8EncodedKeySpec keySpec= new PKCS8EncodedKeySpec(buffer);
KeyFactory keyFactory= KeyFactory.getInstance("RSA");
this.privateKeyV= (PrivateKey) keyFactory.generatePrivate(keySpec);
} catch (NoSuchAlgorithmException e) {
throw new Exception("无此算法");
} catch (InvalidKeySpecException e) {
throw new Exception("签名私钥非法");
} catch (IOException e) {
throw new Exception("签名私钥数据内容读取错误");
} catch (NullPointerException e) {
throw new Exception("签名私钥数据为空");
}
return this.privateKeyV;
}
/**
* 加密过程
* @param publicKey 公钥
* @param plainTextData 明文数据
* @return
* @throws Exception 加密过程中的异常信息
*/
public String encrypt(RSAPublicKey publicKey, String plainTextData) throws Exception{
if(publicKey== null){
throw new Exception("加密公钥为空, 请设置");
}
Cipher cipher= null;
try {
cipher= Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] output= cipher.doFinal(plainTextData.getBytes("gb2312"));
return new BASE64Encoder().encode(output);
} catch (NoSuchAlgorithmException e) {
throw new Exception("无此加密算法");
} catch (NoSuchPaddingException e) {
e.printStackTrace();
return null;
}catch (InvalidKeyException e) {
throw new Exception("加密公钥非法,请检查");
} catch (IllegalBlockSizeException e) {
throw new Exception("明文长度非法");
} catch (BadPaddingException e) {
throw new Exception("明文数据已损坏");
}
}
/**
* 解密过程
* @param privateKey 私钥
* @param cipherData 密文数据
* @return 明文
* @throws Exception 解密过程中的异常信息
*/
public String decrypt(RSAPrivateKey privateKey, String cipherData) throws Exception{
byte[] msg = new BASE64Decoder().decodeBuffer(cipherData);
StringBuffer sb = new StringBuffer();
if (privateKey== null){
throw new Exception("解密私钥为空, 请设置");
}
Cipher cipher= null;
try {
cipher= Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
for (int i = 0; i < msg.length; i += 128) {
byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(msg, i,i + 128));
sb.append(new String(doFinal, "gb2312"));
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
throw new Exception("无此解密算法");
} catch (NoSuchPaddingException e) {
e.printStackTrace();
return null;
}catch (InvalidKeyException e) {
throw new Exception("解密私钥非法,请检查");
} catch (IllegalBlockSizeException e) {
throw new Exception("密文长度非法");
} catch (BadPaddingException e) {
throw new Exception("密文数据已损坏");
}
}
/**
* 字节数据转十六进制字符串
* @param data 输入数据
* @return 十六进制内容
*/
public static String byteArrayToString(byte[] data){
StringBuilder stringBuilder= new StringBuilder();
for (int i=0; i<data.length; i++){
//取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移
stringBuilder.append(HEX_CHAR[(data[i] & 0xf0)>>> 4]);
//取出字节的低四位 作为索引得到相应的十六进制标识符
stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);
if (i<data.length-1){
stringBuilder.append(' ');
}
}
return stringBuilder.toString();
}
/** *//**
* <p>
* 用私钥对信息生成数字签名
* </p>
*
* @param data 已加密数据
* @param privateKey 私钥(BASE64编码)
*
* @return
* @throws Exception
*/
public static String sign(byte[] data, PrivateKey privateKey) throws Exception {
Signature signature = Signature.getInstance("SHA1WithRSA");
signature.initSign(privateKey);
signature.update(data);
return new String(Base64.encodeBase64(signature.sign()));
}
/** *//**
* <p>
* 校验数字签名
* </p>
*
* @param data 已加密数据
* @param publicKey 公钥(BASE64编码)
* @param sign 数字签名
*
* @return
* @throws Exception
*
*/
public static boolean verify(byte[] data, PublicKey publicKey, String sign)
throws Exception {
Signature signature = Signature.getInstance("SHA1WithRSA");
signature.initVerify(publicKey);
signature.update(data);
return signature.verify(Base64.decodeBase64(sign.getBytes()));
}
// 验签
public static boolean verifyPublicKey(String content, String sign,PublicKey key) throws NoSuchAlgorithmException, IOException,
InvalidKeySpecException, InvalidKeyException, SignatureException {
PublicKey pubkey = key;
byte[] signed = Base64.decodeBase64(sign.getBytes());
Signature signature = Signature.getInstance("SHA1WithRSA");
signature.initVerify(pubkey);
signature.update(content.getBytes("gb2312"));
return signature.verify(signed);
}
// 签名
public static String signPrivateKey(String content)
throws NoSuchAlgorithmException, IOException,
InvalidKeySpecException, InvalidKeyException, SignatureException {
PrivateKey prikey = privateKeyV;
Signature signature = Signature.getInstance("SHA1WithRSA");
signature.initSign(prikey);
signature.update(content.getBytes("gb2312"));
byte[] signBytes = signature.sign();
String sign = new String(Base64.encodeBase64(signBytes));
return sign;
}
public static void main(String[] args){
RsaEncryptSign rsaEncrypt= new RsaEncryptSign();
//rsaEncrypt.genKeyPair();
//加载公钥
try {
//rsaEncrypt.loadPublicKey(RsaEncryptSign.DEFAULT_PUBLIC_KEY);
rsaEncrypt.loadPublicKey(new FileInputStream("C:\\Users\\Administrator\\rsa_public_key.pem"));
System.out.println("加载公钥成功");
} catch (Exception e) {
System.err.println(e.getMessage());
System.err.println("加载公钥失败");
}
//加载私钥
try {
//rsaEncrypt.loadPrivateKey(new FileInputStream("C:\\Users\\Administrator\\Desktop\\rsa_private_key.pem"));
rsaEncrypt.loadPrivateKey(new FileInputStream("C:\\Users\\Administrator\\pkcs8_rsa_private_key.pem"));
//rsaEncrypt.loadPrivateKey(RsaEncryptSign.DEFAULT_PRIVATE_KEY);
System.out.println("加载私钥成功");
} catch (Exception e) {
System.err.println(e.getMessage());
System.err.println("加载私钥失败");
}
//加载签名公钥
try {
rsaEncrypt.loadPublicKeyV(rsaEncrypt.loadPublicKey(new FileInputStream("C:\\Users\\Administrator\\rsa_public_key.pem")));
System.out.println("加载签名公钥成功");
} catch (Exception e) {
System.err.println(e.getMessage());
System.err.println("加载公钥失败");
}
//加载签名私钥
try {
rsaEncrypt.loadPrivateKeyV(rsaEncrypt.loadPrivateKey(new FileInputStream("C:\\Users\\Administrator\\pkcs8_rsa_private_key.pem")));
//rsaEncrypt.loadPrivateKeyV(RsaEncryptSign.DEFAULT_PRIVATE_KEY);
System.out.println("加载签名私钥成功");
} catch (Exception e) {
System.err.println(e.getMessage());
System.err.println("加载签名私钥失败");
}
StringBuffer buf = new StringBuffer();
String signMethod="signMethod RSA\n";
buf.append("from 1128218290237514<陈祥德名下账号6228671147597026>\nto 10201<账单平台>\n")
.append("type request\nid ").append(System.currentTimeMillis())
.append("\ncontentType keyvalue\nkeepliver null\ncontentCharset gb2312\ncontent:\n")
.append("命令: 账单/4查询\n")
.append("账单流水号: 30808095638203\n");
//测试字符串
//String encryptStr= "Test String chaijunkun";
String encryptStr = "signMethod RSA" + "\n" +
"from 1128213888888888<刘丽名下账号6228590101005491959>" + "\n" +
"to 10201<账单平台>" + "\n" +
"type request" + "\n" +
"id 1378115341665" + "\n" +
"contentType keyvalue" + "\n" +
"keepliver null" + "\n" +
"contentCharset gb2312" + "\n" +
"content:" + "\n" +
"命令: 账单/4查询" + "\n" +
"账单流水号: 30808095638210" + "\n";
try {
/* //加密
String cipher = rsaEncrypt.encrypt(rsaEncrypt.getPublicKey(), encryptStr);
//解密
String plainText = rsaEncrypt.decrypt(rsaEncrypt.getPrivateKey(), cipher);
System.out.println("密文: "+cipher);
System.out.println("密文长度:"+ cipher.getBytes().length);
System.out.println(RsaEncryptSign.byteArrayToString("".getBytes()));
System.out.println("明文长度:"+ plainText.getBytes().length);
System.out.println(RsaEncryptSign.byteArrayToString(plainText.getBytes()));
System.out.println("明文: "+plainText); */
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
在测试过程中发现数字验签失败,经判断均是字符编码格式问题_!.且通过测试发现String.getBytes("gb2312")