数字证书pfx加密,公钥文件解密异常

来源:互联网 发布:js的事件驱动原理 编辑:程序博客网 时间:2024/05/17 23:53
package com.nantian.tools.pfx;


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.Key;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;


import javax.crypto.Cipher;


import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;


/**
 * pfx证书操作类
 * 
 * @version 1.0
 * @author Administrator
 * 
 */
public class PfxCoder {
/**
* Java密钥库(Java Key Store,JKS)KEY_STORE
*/
public static final String KEY_STORE = "PKCS12";


public static final String X509 = "X.509";


/** */
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 117;


/** */
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 128;


public static void main(String[] args) throws Exception {
String password = "111111";


String keyStorePath = "d:\\cert\\testcert.pfx";
PfxCoder pfCoder = new PfxCoder();
String src="2013-11-07 09:46:01,984  main   717969  INFO org.springframework.context.support.ClassPathXmlApplicationContext:495 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@946d22: startup date [Thu Nov 07 09:46:01 CST 2013]; root of context hierarchy2013-11-07 09:46:02,000  main   717985  INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader:315 - Loading XML bean definitions from class path resource [spring/context-config.xml]2013-11-07 09:46:02,046  main   718031  INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader:315 - Loading XML bean definitions from class path resource [spring/applicationContext-base.xml]"
+" 2013-11-07 09:46:02,125  main   718110  INFO org.springframework.beans.factory.config.PropertyPlaceholderConfigurer:177 - Loading properties file from URL [file:C:/test/test/config/sysconfig.properties]"
+"2013-11-07 09:46:02,125  main   718110  INFO org.springframework.beans.factory.config.PropertyPlaceholderConfigurer:177 - Loading properties file from class path resource [config/init.properties]"
+" 2013-11-07 09:46:02,140  main   718125  INFO org.springframework.beans.factory.support.DefaultListableBeanFactory:557 - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@9bc984: defining beans [placeholderConfig,HttpsFileConfig,HttpsPackConfig,HttpsMainConfig,HttpsFileClient,HttpsPackClient,MainController,DefaultCodec,SocketConfig,TcpNioServer]; root of factory hierarchy"
+"2013-11-07 09:46:02,171  main   718156  INFO com.nantian.sg.client.tcpserver.TcpNioServer:69 - 启动成功"
+" 2013-11-07 09:46:02,187  main   718172  INFO com.nantian.sg.client.win.main.MainEntry:97 - send login pack:000002600<ap><CCTransCode>SGQ000</CCTransCode><ReqSeqNo>111111111</ReqSeqNo><ReqDate/><ReqTime/><ProductID/><ChannelType/><CorpNo>20131107001</CorpNo><OpNo>SG1001</OpNo><AuthNo/><PassWord>ea729fae0050c890335e86dc9dc55d59</PassWord><Sign/><CVersion>v1.0</CVersion></ap>"
+ "2013-11-07 09:46:02,187  main   718172  INFO com.nantian.sg.client.win.main.MainEntry:101 - ==login business=="
+" 2013-11-07 09:46:02,187  main   718172  INFO com.nantian.sg.client.https.HttpsPackClient:418 - connect to url:https://127.0.0.1:8443/SG_SERVER/login.htmls"
+"2013-11-07 09:46:31,218  main   747203  INFO com.nantian.sg.client.https.HttpsPackClient:434 - Proxy Response Status:HTTP/1.1 200 OK"
+" 2013-11-07 09:46:31,218  main   747203  INFO com.nantian.sg.client.https.HttpsPackClient:436 - Proxy Response content length: 390";

String alias=pfCoder.getALIAS(keyStorePath, password);

X509Certificate cert=(X509Certificate)pfCoder.getCertificate(keyStorePath, password);
System.out.println("cert message:"+cert.getSigAlgName());
System.out.println("cert message:"+cert.getSerialNumber().toString(16));

PrivateKey key = pfCoder.getPrivateKeyFromPFX(keyStorePath, password);
System.out.println("私钥:" + key);


String encData = pfCoder.encryptBlockByPrivateKey(src, keyStorePath,
password);
System.out.println("私钥加密数据:" + encData);
System.out.println("私钥加密数据LENGTH:" + encData.length());
String signData = pfCoder.sign(encData, keyStorePath, password);
System.out.println("签名数据:" + signData);

File file = new File("d:\\cert\\test.cer");
byte[] certBytes = new byte[(int) file.length()];
FileInputStream input = new FileInputStream(file);
while (input.read(certBytes) != -1) {


}
System.out.println("certBytes:" + certBytes.length);
boolean flag = pfCoder.verify(encData, signData, certBytes);
System.out.println("验签结果:" + flag);


String decData = pfCoder.decryptBlockByPublicKey(encData, certBytes);
System.out.println("公钥解密:" + decData);
System.out.println("公钥解密length:" + decData.length());



/*
File file = new File("d:\\cert\\test.cer");
byte[] certBytes = new byte[(int) file.length()];
FileInputStream input = new FileInputStream(file);
while (input.read(certBytes) != -1) {


}
System.out.println("certBytes:" + certBytes.length);
String encDataPublic=pfCoder.encryptBlockByPublicKey(src, certBytes);
System.out.println("公钥加密:"+encDataPublic);
String decData=pfCoder.decryptByPrivateKey(encDataPublic, keyStorePath, password);
System.out.println("公钥加密:"+decData);*/
}


public PfxCoder() {
/*
* try { Security.addProvider(new BouncyCastleProvider()); } catch
* (Exception e) { e.printStackTrace(); }
*/
}


/**
* 获得KeyStore

* @param keyStorePath
* @param password
* @return
* @throws Exception
*/
private KeyStore getKeyStore(String keyStorePath, String password)
throws Exception {
InputStream is = new FileInputStream(keyStorePath);
KeyStore ks = KeyStore.getInstance(KEY_STORE);
ks.load(is, password.toCharArray());
is.close();
return ks;
}


/**
* 由KeyStore获得私钥

* @param keyStorePath
* @param alias
* @param password
* @return
* @throws Exception
*/
public PrivateKey getPrivateKeyFromPFX(String keyStorePath, String password)
throws Exception {
KeyStore ks = getKeyStore(keyStorePath, password);
PrivateKey key = null;
Enumeration<String> alias = ks.aliases();


String ALIAS = null;
while (alias.hasMoreElements()) {
ALIAS = (String) alias.nextElement();
if (ks.isKeyEntry(ALIAS)) {
key = (PrivateKey) ks.getKey(ALIAS, password.toCharArray());
}
}
return key;
}


/**
* 得到库中的别名

* @param keyStorePath
* @param password
* @return
* @throws Exception
*/
public String getALIAS(String keyStorePath, String password)
throws Exception {
KeyStore ks = this.getKeyStore(keyStorePath, password);
Enumeration<String> alias = ks.aliases();
String ALIAS = null;
while (alias.hasMoreElements()) {
ALIAS = (String) alias.nextElement();
if (ks.isKeyEntry(ALIAS)) {
Certificate cert=ks.getCertificate(ALIAS);
break;
}
}
return ALIAS;
}


/**
* 私钥加密

* @param data
* @param keyStorePath
* @param alias
* @param password
* @return
* @throws Exception
*/
public String encryptByPrivateKey(String srcData, String keyStorePath,
String password) throws Exception {
// 取得私钥
PrivateKey privateKey = getPrivateKeyFromPFX(keyStorePath, password);


// 对数据加密
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);


return encryptBASE64(cipher.doFinal(srcData.getBytes("gb2312")));


}


/**
* 公钥解密 2013-11-7增加
*/
public String decryptByPublicKey(String data, byte[] certBytes)
throws Exception {
// 解码
byte[] dataBytes = decryptBASE64(data);
X509Certificate cert = (X509Certificate) this.getCertificate(certBytes);
PublicKey publicKey = cert.getPublicKey();
// 对数据解密
Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return new String(cipher.doFinal(dataBytes), "gb2312");
}


public String encryptBASE64(byte[] sign) {
BASE64Encoder encode = new BASE64Encoder();


return encode.encode(sign);
}


public byte[] decryptBASE64(String sign) throws IOException {


BASE64Decoder encode = new BASE64Decoder();
return encode.decodeBuffer(sign);


}


/**
* 得到公钥

* @param keyStorePath
* @param password
* @return
* @throws Exception
*/
public PublicKey getPublicKeyfromPFX(String keyStorePath, String password)
throws Exception {
KeyStore ks = this.getKeyStore(keyStorePath, password);
PublicKey publicKey = null;
Enumeration<String> alias = ks.aliases();
Vector vectors = new Vector();
String ALIAS = "";
X509Certificate cert = null;
while (alias.hasMoreElements()) {
vectors.add(alias.nextElement());
String[] aliases = (String[]) vectors.toArray(new String[0]);
for (int i = 0; i < aliases.length; i++) {
if (ks.isKeyEntry(aliases[i])) {
ALIAS = aliases[i];
break;
}
}
cert = (X509Certificate) ks.getCertificate(ALIAS);
publicKey = cert.getPublicKey();
}
return publicKey;
}


/**
* 得到证书对象

* @param keyStorePath
* @param password
* @return
* @throws Exception
*/
public Certificate getCertFromPFX(String keyStorePath, String password)
throws Exception {
KeyStore ks = this.getKeyStore(keyStorePath, password);
Enumeration<String> alias = ks.aliases();
Vector vectors = new Vector();
String ALIAS = "";
X509Certificate cert = null;
while (alias.hasMoreElements()) {
vectors.add(alias.nextElement());
String[] aliases = (String[]) vectors.toArray(new String[0]);
for (int i = 0; i < aliases.length; i++) {
if (ks.isKeyEntry(aliases[i])) {
ALIAS = aliases[i];
break;
}
}
cert = (X509Certificate) ks.getCertificate(ALIAS);
}
return cert;
}


/**
* 签名

* @param signData
* @param keyStorePath
* @param password
* @return
* @throws Exception
*/
public String sign(String signData, String keyStorePath, String password)
throws Exception {
byte[] sign = decryptBASE64(signData);
// 得到证书
X509Certificate x509Certificate = (X509Certificate) this
.getCertFromPFX(keyStorePath, password);
// 得到私钥
PrivateKey privateKey = this.getPrivateKeyFromPFX(keyStorePath,
password);
// 构建签名
Signature signature = Signature.getInstance(x509Certificate
.getSigAlgName());
signature.initSign(privateKey);
signature.update(sign);
return encryptBASE64(signature.sign());
}


/**
* 得到证书

* @param certBytes
* @return
* @throws Exception
*/
public Certificate getCertificate(byte[] certBytes) throws Exception {
InputStream in = new ByteArrayInputStream(certBytes);
CertificateFactory cf = CertificateFactory.getInstance(X509);
return cf.generateCertificate(in);
}


/**
* 验证签名

* @param priData
* @param signData
* @param certBytes
* @return
* @throws Exception
*/
public boolean verify(String priData, String signData, byte[] certBytes)
throws Exception {
X509Certificate x509Certificate = (X509Certificate) getCertificate(certBytes);
byte[] data = decryptBASE64(priData);
// 获得公钥
PublicKey publicKey = x509Certificate.getPublicKey();
// 构建签名
Signature signature = Signature.getInstance(x509Certificate
.getSigAlgName());
signature.initVerify(publicKey);
signature.update(data);


return signature.verify(decryptBASE64(signData));
}


/**
* 验证证书是否过期或无效

* @param date
* @param certificate
* @return
*/
public boolean verifyCertificate(Date date, byte[] certBytes) {
boolean status = true;
try {
X509Certificate x509Certificate = (X509Certificate) this
.getCertificate(certBytes);
x509Certificate.checkValidity(date);
} catch (Exception e) {
e.printStackTrace();
status = false;
}
return status;
}


public boolean verifyCert(byte[] certBytes) {
return this.verifyCertificate(new Date(), certBytes);


}


/**
* 私钥加密 对数据分段加密

* @param srcData
* @param keyStorePath
* @param password
* @return
* @throws Exception
*/
public String encryptBlockByPrivateKey(String srcData, String keyStorePath,
String password) throws Exception {


byte[] data = srcData.getBytes("gb2312");


// 取得私钥
PrivateKey privateKey = getPrivateKeyFromPFX(keyStorePath, password);

System.out.println("私钥算法:"+privateKey.getAlgorithm());
// 对数据加密
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm(), "SunJCE");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);


int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();


return this.encryptBASE64(encryptedData);
}


/** */
/**
* <p>
* 公钥解密
* </p>

* @param encData
*            已加密数据 (BASE64编码)
* @return
* @throws Exception
*/
public String decryptBlockByPublicKey(String encData, byte[] certBytes)
throws Exception {
// 解码
byte[] encryptedData = decryptBASE64(encData);
X509Certificate cert = (X509Certificate) this.getCertificate(certBytes);
PublicKey publicKey = cert.getPublicKey();
System.out.println("公钥算法:"+publicKey.getAlgorithm());
// 对数据解密
Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm(), "SunJCE");
cipher.init(Cipher.DECRYPT_MODE, publicKey);


int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher
.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher
.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return new String(decryptedData, "gb2312");
}


/** */
/**
* <p>
* 公钥加密
* </p>

* @param dataSrc
*            源数据
* @return
* @throws Exception
*/
public String encryptBlockByPublicKey(String dataSrc, byte[] certBytes)
throws Exception {
byte[] data = dataSrc.getBytes("gb2312");
Key publicK = this.getCertificate(certBytes).getPublicKey();
// 对数据加密
Cipher cipher = Cipher.getInstance(publicK.getAlgorithm(), "SunJCE");
cipher.init(Cipher.ENCRYPT_MODE, publicK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptBASE64(encryptedData);
}


/** */
/**
* <P>
* 私钥解密
* </p>

* @param encryptedData
*            已加密数据
* @return
* @throws Exception
*/
public String decryptByPrivateKey(String encData, String keyStorePath,
String password) throws Exception {
byte[] encryptedData = decryptBASE64(encData);
Key privateK = this.getPrivateKeyFromPFX(keyStorePath, password);
Cipher cipher = Cipher.getInstance(privateK.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher
.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher
.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();

out.close();
return new String(decryptedData, "gb2312");
}


public Certificate getCertificate(String keyStorePath, String password)
throws Exception {
Certificate cert=null;
KeyStore ks = this.getKeyStore(keyStorePath, password);
Enumeration<String> alias = ks.aliases();
String ALIAS = null;
while (alias.hasMoreElements()) {
ALIAS = (String) alias.nextElement();
if (ks.isKeyEntry(ALIAS)) {
cert=ks.getCertificate(ALIAS);
break;
}
}
return cert;
}

}               

   用私钥加密后,用公钥解密异常:   

  Exception in thread "main" javax.crypto.BadPaddingException: Data must start with zero
at sun.security.rsa.RSAPadding.unpadV15(Unknown Source)
at sun.security.rsa.RSAPadding.unpad(Unknown Source)
at com.sun.crypto.provider.RSACipher.a(DashoA6275)
at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA6275)
at javax.crypto.Cipher.doFinal(DashoA12275)
at com.nantian.tools.pfx.PfxCoder.decryptBlockByPublicKey(Unknown Source)
at com.nantian.tools.pfx.PfxCoder.main(Unknown Source)

  苦苦调试半天,调试不成,网上也有人遇到过,可我还没有找到可解决的办法,希望高手给解决下,多谢!多谢!多谢!

测试如果需要证书,请加QQ:719472795,本人很乐意发送给你,多谢!

  server.pfx------------------密码:12345678   没有问题

  testCert.pfx----------------密码:111111     有问题

                                                                                                                                                 --------------------------------------------一个苦苦编程的人

原创粉丝点击