`

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>
        /// <param name="OriginalString">原文:UTF8编码</param>
        /// <param name="SignatureString">签名:base64编码的字节</param>
        /// <param name="publicKeyPath">公钥路径</param>
        /// <returns> 验签结果</returns>
        public bool Verify(String OriginalString, String SignatureString,String publicKeyPath)
        {
               //将base64签名数据转码为字节 
                byte[] signedBase64 = Convert.FromBase64String(SignatureString);
                byte[] orgin = Encoding.UTF8.GetBytes(OriginalString);
 
                X509Certificate2 x509_Cer1 = new X509Certificate2(publicKeyPath);

                RSACryptoServiceProvider oRSA = new RSACryptoServiceProvider();
                oRSA.FromXmlString(x509_Cer1.PublicKey.Key.ToXmlString(false));

                bool bVerify = oRSA.VerifyData(orgin, "SHA1", signedBase64);
                return bVerify;

        }

        /// <summary>
        /// 验证签名
        /// </summary>
        /// <param name="data">原文:UTF8编码</param>
        /// <param name="privateKeyPath">证书路径:D:/certs/mycert.key</param>
        /// <returns> 验签</returns>
        public string Sign(string data, string privateKeyPath)
        {
            RSACryptoServiceProvider rsaCsp = LoadCertificateFile(privateKeyPath);
            byte[] dataBytes = Encoding.UTF8.GetBytes(data);
            byte[] signatureBytes = rsaCsp.SignData(dataBytes, "SHA1");
            return Convert.ToBase64String(signatureBytes);
        }

        private  byte[] GetPem(string type, byte[] data)
        {
            string pem = Encoding.UTF8.GetString(data);
            string header = String.Format("-----BEGIN {0}-----", type);
            string footer = String.Format("-----END {0}-----", type);
            int start = pem.IndexOf(header) + header.Length;
            int end = pem.IndexOf(footer, start);
 
            string base64 = pem.Substring(start, (end - start));
   
            return Convert.FromBase64String(base64);
        }

        private  RSACryptoServiceProvider LoadCertificateFile(string filename)
        {
            using (System.IO.FileStream fs = System.IO.File.OpenRead(filename))
            {
                byte[] data = new byte[fs.Length];
                byte[] res = null;
                fs.Read(data, 0, data.Length);
                if (data[0] != 0x30)
                {
                    res = GetPem("RSA PRIVATE KEY", data);
                }
                try
                {
                    RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(res);
                    return rsa;
                }
                catch (Exception ex)
                {
                }
                return null;
            }
        }

        private  RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
        {
            byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
             
            // --------- Set up stream to decode the asn.1 encoded RSA private key ------  
            MemoryStream mem = new MemoryStream(privkey);
            BinaryReader binr = new BinaryReader(mem);  //wrap Memory Stream with BinaryReader for easy reading  
            byte bt = 0;
            ushort twobytes = 0;
            int elems = 0;
            try
            {
                twobytes = binr.ReadUInt16();
                if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)  
                    binr.ReadByte();    //advance 1 byte  
                else if (twobytes == 0x8230)
                    binr.ReadInt16();    //advance 2 bytes  
                else
                    return null;

                twobytes = binr.ReadUInt16();
                if (twobytes != 0x0102) //version number  
                    return null;
                bt = binr.ReadByte();
                if (bt != 0x00)
                    return null;


                //------ all private key components are Integer sequences ----  
                elems = GetIntegerSize(binr);
                MODULUS = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                E = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                D = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                P = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                Q = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                DP = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                DQ = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                IQ = binr.ReadBytes(elems);


                // ------- create RSACryptoServiceProvider instance and initialize with public key -----  
                CspParameters CspParameters = new CspParameters();
                CspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
                RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(1024, CspParameters);
                RSAParameters RSAparams = new RSAParameters();
                RSAparams.Modulus = MODULUS;
                RSAparams.Exponent = E;
                RSAparams.D = D;
                RSAparams.P = P;
                RSAparams.Q = Q;
                RSAparams.DP = DP;
                RSAparams.DQ = DQ;
                RSAparams.InverseQ = IQ;
                RSA.ImportParameters(RSAparams);
                return RSA;
            }
            catch (Exception ex)
            {
                
                return null;
            }
            finally
            {
                binr.Close();
            }
        }

        private  int GetIntegerSize(BinaryReader binr)
        {
            byte bt = 0;
            byte lowbyte = 0x00;
            byte highbyte = 0x00;
            int count = 0;
            bt = binr.ReadByte();
            if (bt != 0x02)     //expect integer  
                return 0;
            bt = binr.ReadByte();

            if (bt == 0x81)
                count = binr.ReadByte();    // data size in next byte  
            else
                if (bt == 0x82)
                {
                    highbyte = binr.ReadByte(); // data size in next 2 bytes  
                    lowbyte = binr.ReadByte();
                    byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
                    count = BitConverter.ToInt32(modint, 0);
                }
                else
                {
                    count = bt;     // we already have the data size  
                }

            while (binr.ReadByte() == 0x00)
            {   //remove high order zeros in data  
                count -= 1;
            }
            binr.BaseStream.Seek(-1, SeekOrigin.Current);       //last ReadByte wasn't a removed zero, so back up a byte  
            return count;
        }  
    }
}

 

PHP签名:

1)从包含公私钥的pfx证书中取得.key私钥:于C#的证书一致

2)公钥生成:

F:\openssl-0.9.8k_WIN32\bin>openssl pkcs12 -in f:\certs\zhuo.pfx -out f:\certs\zhuo.pem

 

3)签名及验签:

/*
签名数据:
data:utf-8编码的订单原文,
privatekeyFile:私钥路径
passphrase:私钥密码
返回:base64转码的签名数据
*/
function sign($data, $privatekeyFile,$passphrase)
{ 
  $signature = '';
	$privatekey = openssl_pkey_get_private(file_get_contents($privatekeyFile), $passphrase);
  $res=openssl_get_privatekey($privatekey);
  openssl_sign($data, $signature, $res);
  openssl_free_key($res);  

  return base64_encode($signature);
}

/*
验证签名:
data:原文
signature:签名
publicKeyPath:公钥路径
返回:签名结果,true为验签成功,false为验签失败
*/
function verity($data, $signature, $publicKeyPath)
{
	$pubKey = file_get_contents('D:/certs/test.pem');
	$res = openssl_get_publickey($pubKey);
	$result = (bool)openssl_verify($data, base64_decode($signature), $res);
	openssl_free_key($res);

	return $result;
}

 * PHP需要注意版本和一些包的导入,如果有报错再google了~~

 

 

 

 

 

 

分享到:
评论

相关推荐

    C# 实现与JAVA互通 加签/验签,RSA加密/解密

    * RSA数字签名-俗称加签验签:私钥加签,公钥验签。  * RSA加密解密:私钥解密,公钥加密。 * RSA数字签名-俗称加签验签:私钥加签,公钥验签。  * RSA加密解密:私钥解密,公钥加密。 * RSA数字签名-俗称加...

    C#与java平台RSA加密解密签名验签互通案例

    在这个案例中,"Test"和"Javaworkspace"可能是包含代码示例或者测试数据的文件夹,可能包含C#和Java的实现代码,用于演示如何处理上述步骤,以实现RSA加密解密和签名验签的互通。 在实际应用中,还需要考虑其他因素...

    .net与java中的互操作(rsa签名与验签、加密与解密)

    在这个场景下,我们将探讨如何在.NET环境中使用C#进行RSA签名和解密,以及在Java环境中进行RSA验证和加密。 首先,让我们关注.NET中的RSA签名。在C#中,我们可以使用`System.Security.Cryptography....

    C#RSA加密解密签名和验证签名的小例子

    C#RSA加密解密签名和验证签名的小例子,代码都加了注释,可以很容易看懂.如果应用到消息收发,发送方用公钥加密,接收方用私钥解密.如果是应用到软件注册方面,则需要客户端保留公钥,程序开发者保留私钥.使用签名和验证...

    PKCS7标准签名与验签

    `P7Verify_CSharp`可能是一个包含示例代码或库的压缩文件,它可能提供了更具体的操作步骤和示例,帮助开发者在C#环境中进行PKCS#7签名和验证。通过研究和理解这些代码,你可以更好地理解和应用PKCS#7签名机制,确保...

    C# RSA加密、解密、加签、验签、支持JAVA格式公钥私钥、PEM格式公钥私钥、.NET格式公钥私钥

    C# RSA加密、解密、加签、验签、支持JAVA格式公钥私钥、PEM格式公钥私钥、.NET格式公钥私钥 对应文章: http://blog.csdn.net/gzy11/article/details/54573973

    C# pkcs # 7 签名 验签

    在.NET平台上,C#语言提供了丰富的库和API来处理各种加密和签名操作,其中包括PKCS #7标准。PKCS(Public Key Cryptography Standards)是由RSA安全公司提出的公钥加密标准,其中的第7号标准(PKCS #7)定义了数据的...

    C#通过安全证书生成签名和验签辅助类.rar

    本资源"通过安全证书生成签名和验签辅助类"是针对C#编程语言的一个工具集,它可以帮助开发者方便地实现数字签名和验证签名的功能。 在C#中,我们可以使用.NET框架提供的System.Security.Cryptography命名空间中的类...

    RSA加密JAVA转C# JAVA转PHP,C#转JAVA

    本工具提供了在不同编程语言间进行RSA密钥的互换,包括JAVA转C#、JAVA转PHP以及C#转JAVA的转换功能。 在JAVA中,RSA的实现主要依赖于`java.security`包,其中`KeyPairGenerator`用于生成公钥和私钥,`Cipher`用于...

    C#通过 N、E和D(模数、公钥指数和私钥指数)三个参数来RSA加解密及签名和验签

    C#通过 n、e和d(模数、公钥指数和私钥指数)三个参数来RSA加解密及签名和验签。如果只是公钥解密和验证签名,那么可以不需要知道私钥指数(D),这在某些时候对方传过来N和E来解密和验签的时候非常管用(验证签名的...

    RSA加密解密、签名验签Demo

    在C#中实现RSA加密解密和签名验签,我们可以利用.NET框架提供的System.Security.Cryptography命名空间中的相关类。 1. RSA加密原理: RSA基于数论中的大数因子分解难题,即给定一个大合数N,找到它的两个素数因子p...

    C#SM2加密-解密-签名-验签源码+Demo已与JAVA联调

    在"TEST"这个压缩包文件中,可能包含了一个C#实现的SM2加密解密和签名验签的Demo项目,以及与Java联调的相关示例代码。通过这些示例,开发者可以学习如何在实际项目中运用SM2算法,确保数据在C#和Java应用之间的安全...

    C# RSA读取密钥文件pfx cer 签名验签加密解密帮助类

    C#作为.NET框架的主要编程语言,提供了丰富的库来支持加密和签名操作,其中RSA算法是一种广泛应用的非对称加密技术。本篇文章将深入探讨如何在C#中使用RSA算法处理pfx和cer密钥文件,进行签名验证、加密和解密,并...

    C# BouncyCastle实现带原文数据PKCS#7 签名、验签

    在IT领域,安全性和可信性是至关重要的,特别是在网络...文件`BouncyCastlePCKS7`可能包含了实现这个过程的示例代码,通过阅读和理解这些代码,你可以更深入地了解如何在C#中操作BouncyCastle库进行签名和验签操作。

    C#和Java实现互通的RSA&DES加解密算法

    C#和Java中都有内置的类库支持RSA加密,如C#的System.Security.Cryptography.RSACryptoServiceProvider和Java的java.security.KeyPairGenerator与java.security.Signature等。 接下来,我们讨论DES(Data ...

    RSA在C#和java中的应用

    本篇将详细讲解RSA在C#和Java中的应用,以及如何实现公钥加密和私钥解密的过程。 在RSA算法中,每一对密钥由一个公钥和一个私钥组成。公钥可以公开,用于加密信息;而私钥必须保密,用于解密信息。这样的设计使得...

    百度小程序支付签名与验签代码(C#)

    本文将详细介绍如何在C#环境中实现百度小程序的支付签名与验签功能,主要以订单创建和支付回调通知这两个关键场景为例。 首先,我们需要理解签名的概念。在支付系统中,签名是一种非对称加密技术,用于验证消息的...

    使用.net2.0 的 MD5加密/SM3加密/RSA加密/RSA签名, 用 java解密或签名验签代码

    文件"Crypt-.NETToJava-Framework2.0-master"很可能包含了一个完整的示例项目,展示了如何在.NET 2.0中执行加密和签名,然后在Java环境中解密和验签。这个项目可能包括了必要的.NET和Java代码,以及必要的数据转换...

    C#和Java关于RSA非对称加密互通类

    本篇将深入探讨C#和Java之间如何实现RSA非对称加密的互通,并详细讲解涉及的类和方法。 首先,RSA的核心概念是基于两个不同的密钥:公钥和私钥。公钥用于加密,而私钥用于解密。这样,即使加密后的数据被第三方获取...

    C# RSA加密、支持JAVA格式公钥私钥

    C#和Java作为两种常见的编程语言,都提供了实现RSA算法的库和接口。这个压缩包中的内容看起来是针对C#环境的一个RSA工具包,能够处理Java格式的公钥和私钥,这在跨平台的系统交互中非常有用。 1. **RSA算法原理**:...

Global site tag (gtag.js) - Google Analytics