Win32OpenSSL_Light-0_9_8k.exe
1. 生成不含密码保护的私钥:
openssl genrsa -out private-rsa.key 1024
2. 生成证书
openssl req -new -x509 -key private-rsa.key -days 750 -out public-rsa.cer
3. 生成Keystore
3.1. 生成PKCS12 格式Keystore
openssl pkcs12 -export -name test-alias -in public-rsa.cer -inkey private-rsa.key -out 99bill-rsa.pfx
pfx格式证书转换为pem格式命令
openssl pkcs12 -in 99bill-rsa.pfx -passin pass:生成证书设置的密码 -nodes -out 99bill-rsa.pem
private-rsa.pfx
public-rsa.cer
附:签名方法
package com.verify.cert;
public class CertUtil {
/**
* 对字符串进行签名
*
* @param TobeSigned
* 需要进行签名的字符串
* @param KeyFile
* PFX证书文件路径
* @param PassWord
* 私钥保护密码
* @return 签名成功返回true(从LastResult属性获取结果),失败返回false(从LastErrMsg属性获取失败原因)
*/
public static String SignMsg(final String TobeSigned, final String KeyFile, final String PassWord) throws Exception {
CryptNoRestrict cryptNoRestrict = new CryptNoRestrict();
cryptNoRestrict.SignMsg(TobeSigned, KeyFile, PassWord);
return cryptNoRestrict.lastSignMsg;
}
/**
* 验证签名
*
* @param TobeVerified
* 待验证签名的密文
* @param PlainText
* 待验证签名的明文
* @param CertFile
* 签名者公钥证书
* @return 验证成功返回true,失败返回false(从LastErrMsg属性获取失败原因)
*/
public static boolean VerifyMsg(String TobeVerified, String PlainText, String CertFile) throws Exception {
CryptNoRestrict cryptNoRestrict = new CryptNoRestrict();
return cryptNoRestrict.VerifyMsg(TobeVerified, PlainText, CertFile);
}
public static void main(String[] args) {
try {
String a = "100|123123122222222222222";
String b = SignMsg(a, "com/verify/cert/private-rsa.pfx", "123456");
System.err.println(b);
System.err.println(VerifyMsg(b, a, "com/verify/cert/public-rsa.cer"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package com.verify.cert;
public interface CryptInf {
public boolean VerifyMsg(String TobeVerified, String PlainText, String CertFile) throws Exception;
public boolean SignMsg(String TobeSigned, String KeyFile, String PassWord) throws Exception;
public String getLastSignMsg();
}
/**
*
*/
package com.verify.cert;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.Provider;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Enumeration;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
/**
* @author Administrator
*
*/
public class CryptNoRestrict implements CryptInf {
public static Provider provider = new BouncyCastleProvider();
/**
* 构造函数
*/
public CryptNoRestrict() {
}
public CryptNoRestrict(String encoding) {
this.encoding = encoding;
}
private String encoding = "GBK";
/**
* 取出上次调用加密、解密、签名函数成功后的输出结果
*/
protected String lastResult;
/**
* 返回上一次签名结果
*/
protected String lastSignMsg;
/**
* 对字符串进行签名
*
* @param TobeSigned
* 需要进行签名的字符串
* @param KeyFile
* PFX证书文件路径
* @param PassWord
* 私钥保护密码
* @return 签名成功返回true(从LastResult属性获取结果),失败返回false(从LastErrMsg属性获取失败原因)
*/
public boolean SignMsg(final String TobeSigned, final String KeyFile, final String PassWord) throws Exception {
ClassLoader cl = CryptNoRestrict.class.getClassLoader();
InputStream fiKeyFile = cl.getResourceAsStream(KeyFile);
// 传入绝对路径
//FileInputStream fiKeyFile = null;
//fiKeyFile = new FileInputStream(KeyFile);
boolean result = false;
this.lastSignMsg = "";
KeyStore ks = KeyStore.getInstance("PKCS12");
try {
ks.load(fiKeyFile, PassWord.toCharArray());
} catch (Exception ex) {
if (fiKeyFile != null)
fiKeyFile.close();
throw ex;
}
Enumeration myEnum = ks.aliases();
String keyAlias = null;
RSAPrivateCrtKey prikey = null;
// keyAlias = (String) myEnum.nextElement();
/* IBM JDK必须使用While循环取最后一个别名,才能得到个人私钥别名 */
while (myEnum.hasMoreElements()) {
keyAlias = (String) myEnum.nextElement();
// System.out.println("keyAlias==" + keyAlias);
if (ks.isKeyEntry(keyAlias)) {
prikey = (RSAPrivateCrtKey) ks.getKey(keyAlias, PassWord.toCharArray());
break;
}
}
if (prikey == null) {
result = false;
throw new Exception("没有找到匹配私钥");
} else {
Signature sign = Signature.getInstance("SHA1withRSA");
sign.initSign(prikey);
sign.update(TobeSigned.getBytes(encoding));
byte signed[] = sign.sign();
byte sign_asc[] = new byte[signed.length * 2];
Hex2Ascii(signed.length, signed, sign_asc);
this.lastResult = new String(sign_asc);
this.lastSignMsg = this.lastResult;
result = true;
}
return result;
}
/**
* 验证签名
*
* @param TobeVerified
* 待验证签名的密文
* @param PlainText
* 待验证签名的明文
* @param CertFile
* 签名者公钥证书
* @return 验证成功返回true,失败返回false(从LastErrMsg属性获取失败原因)
*/
public boolean VerifyMsg(String TobeVerified, String PlainText, String CertFile) throws Exception {
boolean result = false;
ClassLoader cl = CryptNoRestrict.class.getClassLoader();
InputStream certfile = cl.getResourceAsStream(CertFile);
// 传入绝对路径
//FileInputStream certfile = null;
//certfile = new FileInputStream(CertFile);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate x509cert = null;
try {
x509cert = (X509Certificate) cf.generateCertificate(certfile);
} catch (Exception ex) {
if (certfile != null)
certfile.close();
throw ex;
}
RSAPublicKey pubkey = (RSAPublicKey) x509cert.getPublicKey();
Signature verify = Signature.getInstance("SHA1withRSA");
verify.initVerify(pubkey);
byte signeddata[] = new byte[TobeVerified.length() / 2];
Ascii2Hex(TobeVerified.length(), TobeVerified.getBytes(encoding), signeddata);
verify.update(PlainText.getBytes(encoding));
if (verify.verify(signeddata)) {
result = true;
} else {
result = false;
// throw new Exception("验签失败");
}
return result;
}
/**
* 返回上次调用加密、解密、签名函数成功后的输出结果
*
* @return 返回上次调用加密、解密、签名函数成功后的输出结果
*/
public String getLastResult() {
return this.lastResult;
}
/**
* 返回上一次签名结果
*
* @return 签名结果
*/
public String getLastSignMsg() {
return this.lastSignMsg;
}
/**
* 将十六进制数据转换成ASCII字符串
*
* @param len
* 十六进制数据长度
* @param data_in
* 待转换的十六进制数据
* @param data_out
* 已转换的ASCII字符串
*/
private static void Hex2Ascii(int len, byte data_in[], byte data_out[]) {
byte temp1[] = new byte[1];
byte temp2[] = new byte[1];
for (int i = 0, j = 0; i < len; i++) {
temp1[0] = data_in[i];
temp1[0] = (byte) (temp1[0] >>> 4);
temp1[0] = (byte) (temp1[0] & 0x0f);
temp2[0] = data_in[i];
temp2[0] = (byte) (temp2[0] & 0x0f);
if (temp1[0] >= 0x00 && temp1[0] <= 0x09) {
(data_out[j]) = (byte) (temp1[0] + '0');
} else if (temp1[0] >= 0x0a && temp1[0] <= 0x0f) {
(data_out[j]) = (byte) (temp1[0] + 0x57);
}
if (temp2[0] >= 0x00 && temp2[0] <= 0x09) {
(data_out[j + 1]) = (byte) (temp2[0] + '0');
} else if (temp2[0] >= 0x0a && temp2[0] <= 0x0f) {
(data_out[j + 1]) = (byte) (temp2[0] + 0x57);
}
j += 2;
}
}
/**
* 将ASCII字符串转换成十六进制数据
*
* @param len
* ASCII字符串长度
* @param data_in
* 待转换的ASCII字符串
* @param data_out
* 已转换的十六进制数据
*/
private static void Ascii2Hex(int len, byte data_in[], byte data_out[]) {
byte temp1[] = new byte[1];
byte temp2[] = new byte[1];
for (int i = 0, j = 0; i < len; j++) {
temp1[0] = data_in[i];
temp2[0] = data_in[i + 1];
if (temp1[0] >= '0' && temp1[0] <= '9') {
temp1[0] -= '0';
temp1[0] = (byte) (temp1[0] << 4);
temp1[0] = (byte) (temp1[0] & 0xf0);
} else if (temp1[0] >= 'a' && temp1[0] <= 'f') {
temp1[0] -= 0x57;
temp1[0] = (byte) (temp1[0] << 4);
temp1[0] = (byte) (temp1[0] & 0xf0);
}
if (temp2[0] >= '0' && temp2[0] <= '9') {
temp2[0] -= '0';
temp2[0] = (byte) (temp2[0] & 0x0f);
} else if (temp2[0] >= 'a' && temp2[0] <= 'f') {
temp2[0] -= 0x57;
temp2[0] = (byte) (temp2[0] & 0x0f);
}
data_out[j] = (byte) (temp1[0] | temp2[0]);
i += 2;
}
}
protected String replaceAll(String strURL, String strAugs) {
// JDK1.3中String类没有replaceAll的方法
/** ********************************************************** */
int start = 0;
int end = 0;
String temp = new String();
while (start < strURL.length()) {
end = strURL.indexOf(" ", start);
if (end != -1) {
temp = temp.concat(strURL.substring(start, end).concat("%20"));
if ((start = end + 1) >= strURL.length()) {
strURL = temp;
break;
}
} else if (end == -1) {
if (start == 0)
break;
if (start < strURL.length()) {
temp = temp.concat(strURL.substring(start, strURL.length()));
strURL = temp;
break;
}
}
}
temp = "";
start = end = 0;
while (start < strAugs.length()) {
end = strAugs.indexOf(" ", start);
if (end != -1) {
temp = temp.concat(strAugs.substring(start, end).concat("%20"));
if ((start = end + 1) >= strAugs.length()) {
strAugs = temp;
break;
}
} else if (end == -1) {
if (start == 0)
break;
if (start < strAugs.length()) {
temp = temp.concat(strAugs.substring(start, strAugs.length()));
strAugs = temp;
break;
}
}
}
/** **************************************************************** */
return strAugs;
}
}