日期:2014-05-16  浏览次数:20502 次

PHP,C# 和JAVARSA签名及验签

这个功能网上搜了好多资料。贡献一下,转载须注明并对卓二妹的无私奉献表示感谢。

1)签名算法使用SHA1withRSA。

2)签名后的数据位base64编码的密文字符串。

3)三个环境进行签名的私钥的格式不同,需要openssl工具进行转换。

——————————————————————————————————————————

JAVA签名:

1)从包含公私钥的pfx证书中取得.key私钥:

F:\openssl-0.9.8k_WIN32\bin>openssl pkcs12 -in f:\certs\zhuo.pfx -out f:\certs\zhuo.pem
Enter Import Password:(输入导出时的密码)
MAC verified OK
Enter PEM pass phrase:(长度至少为4位的pem证书密码)
Verifying - Enter PEM pass phrase:(确认一次pem证书密码)
 
F:\openssl-0.9.8k_WIN32\bin>openssl pkcs8 -topk8 -inform PEM -outform DER -in f:\certs\zhuo.pem -out f:\certs\zhuo_der.key -nocrypt
Enter pass phrase for f:\certs\zhuo.pem:(输入pem证书密码)
??

该步骤生成的.key文件即为JAVA签名所需私钥文件。

2)生成公钥:直接从IE中导出X.509格式二进制编码的cer为后缀的公钥证书即可。

?

?

3)签名验签:

?

//签名:
/**
	 * 
	 * 函数功能说明: 签名数据
	 * created by zhuoyueping 2013-8-17
	 * modified by zhuoyueping 2013-8-17 
	 * 修改内容说明: 
	 * @param @param content:签名原文
	 * @param @param keyfile:私钥文件.key路径
	 * @param @return
	 * @param @throws Exception     
	 * @return String :base64签名
	 * @throws
	 */
	public String sign(String content, String keyfile) throws Exception {
		File file = new File(keyfile); //keyfile key文件的地址
		FileInputStream in;
		in = new FileInputStream(file);

		ByteArrayOutputStream bout = new ByteArrayOutputStream();
		byte[] tmpbuf = new byte[1024];
		int count = 0;
		while ((count = in.read(tmpbuf)) != -1) {
			bout.write(tmpbuf, 0, count);
			tmpbuf = new byte[1024];
		}
		in.close();

		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(bout
				.toByteArray());
		RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory
				.generatePrivate(privateKeySpec);

		Signature dsa = Signature.getInstance("SHA1withRSA"); //采用SHA1withRSA加密
		dsa.initSign(privateKey);
		dsa.update(content.getBytes("UTF-8")); //voucher需要加密的String必须变成byte类型的
		byte[] sig = dsa.sign();

		String rtnValue = new String(Base64.encode(sig));

		return rtnValue;
	}

	/**
	 * <p>
	 * 验证签名
	 * </p>
	 *
	 * @param data 原文字节
	 * @param sign 数据签名[BASE64]
	 * @param certificatePath 证书存储路径
	 * @return
	 * @throws Exception
	 */
public static boolean verifySign(byte[] data, String sign,
			String certificatePath) throws Exception {
		// 获得证书
		X509Certificate x509Certificate = (X509Certificate) getCertificate(certificatePath);
		return verifySign(data,sign,x509Certificate);
	}

private static boolean verifySign(byte[] data, String sign, X509Certificate x509Certificate)throws Exception {
		PublicKey publicKey = x509Certificate.getPublicKey();
		Signature signature = Signature.getInstance(x509Certificate
				.getSigAlgName());
		signature.initVerify(publicKey);
		signature.update(data);
		return signature.verify(Base64.decode(sign.getBytes()));
	}

?

C#签名:

1)从包含公私钥的pfx证书中取得.key私钥:

F:\openssl-0.9.8k_WIN32\bin> openssl rsa -in d:\\certs\\zhuo.pfx -nocerts -nodes -out d:\\certs\\zhuo.key

该步骤生成的.key文件即为C#签名所需私钥文件。
?

2)公钥生成:于java方式相同,都是二进制格式的x509证书3)签名及验签:

using System;
using System.Text;
using System.Security.Cryptography;
using System.Web;
using System.IO;
using System.Security.Cryptography.X509Certificates;  

namespace Safe
{
    public class SafeUtil
    {
        /// <summary>
        /// 验证签名
        /// </summary>
        /