本文为原创,转载请注明出处
JAVA/PHP/C#版RSA验签
本文是上一篇文章的兄弟篇,上篇文章介绍了客户端的sdk中如何基于JAVA/PHP/C#使用RSA私钥签名,然后服务端基于JAVA使用RSA公钥验签,客户端签名/服务端验签的模式只能帮助服务端检查客户端来的请求数据是否被篡改,同样的,客户端也需要对服务端的返回结果检查是否被篡改,因此就引出了本片文章。
Java版的验签和加签均已在上一篇文章中分析过,客户端和服务端的逻辑是一样的,此处不再赘述。下面重点分析如何基于RSA的PEM文件,使用php和c#进行验签。
1、php验签:
function verify($data, $sign, $rsaPublicKeyFilePath) { //读取公钥文件 $pubKey = file_get_contents($rsaPublicKeyFilePath); //转换为openssl格式密钥 $res = openssl_get_publickey($pubKey); //调用openssl内置方法验签,返回bool值 $result = (bool)openssl_verify($data, base64_decode($sign), $res); //释放资源 openssl_free_key($res); //返回资源是否成功 return $result; }
注意:$ rsaPublicKeyFilePath为pem公钥文件路径
2、 c#验签
public static bool VerifySignedHash(string str_DataToVerify, string str_SignedData, string str_publicKeyFilePath) { byte[] SignedData = Convert.FromBase64String(str_SignedData); ASCIIEncoding ByteConverter = new ASCIIEncoding(); byte[] DataToVerify = ByteConverter.GetBytes(str_DataToVerify); try { string sPublicKeyPEM = File.ReadAllText(str_publicKeyFilePath); RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.PersistKeyInCsp = false; rsa.LoadPublicKeyPEM(sPublicKeyPEM); return rsa.VerifyData(DataToVerify, new SHA1CryptoServiceProvider(), SignedData); } catch (CryptographicException e) { Console.WriteLine(e.Message); return false; } }
注:str_publicKeyFilePath为RSA公钥文件路径
此处用到了c#的Extension methods,需要对RSACryptoServiceProvider进行扩展,扩展类为RSACryptoServiceProviderExtension
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using System.Runtime.InteropServices; using System.Security.Cryptography; namespace sdk { /// <summary>Extension method for initializing a RSACryptoServiceProvider from PEM data string.</summary> public static class RSACryptoServiceProviderExtension { #region Methods /// <summary>Extension method which initializes an RSACryptoServiceProvider from a DER public key blob.</summary> public static void LoadPublicKeyDER(this RSACryptoServiceProvider provider, byte[] DERData) { byte[] RSAData = RSACryptoServiceProviderExtension.GetRSAFromDER(DERData); byte[] publicKeyBlob = RSACryptoServiceProviderExtension.GetPublicKeyBlobFromRSA(RSAData); provider.ImportCspBlob(publicKeyBlob); } /// <summary>Extension method which initializes an RSACryptoServiceProvider from a DER private key blob.</summary> public static void LoadPrivateKeyDER(this RSACryptoServiceProvider provider, byte[] DERData) { byte[] privateKeyBlob = RSACryptoServiceProviderExtension.GetPrivateKeyDER(DERData); provider.ImportCspBlob(privateKeyBlob); } /// <summary>Extension method which initializes an RSACryptoServiceProvider from a PEM public key string.</summary> public static void LoadPublicKeyPEM(this RSACryptoServiceProvider provider, string sPEM) { byte[] DERData = RSACryptoServiceProviderExtension.GetDERFromPEM(sPEM); RSACryptoServiceProviderExtension.LoadPublicKeyDER(provider, DERData); } /// <summary>Extension method which initializes an RSACryptoServiceProvider from a PEM private key string.</summary> public static void LoadPrivateKeyPEM(this RSACryptoServiceProvider provider, string sPEM) { byte[] DERData = RSACryptoServiceProviderExtension.GetDERFromPEM(sPEM); RSACryptoServiceProviderExtension.LoadPrivateKeyDER(provider, DERData); } /// <summary>Returns a public key blob from an RSA public key.</summary> internal static byte[] GetPublicKeyBlobFromRSA(byte[] RSAData) { byte[] data = null; UInt32 dwCertPublicKeyBlobSize = 0; if (RSACryptoServiceProviderExtension.CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING, new IntPtr((int)CRYPT_OUTPUT_TYPES.RSA_CSP_PUBLICKEYBLOB), RSAData, (UInt32)RSAData.Length, CRYPT_DECODE_FLAGS.NONE, data, ref dwCertPublicKeyBlobSize)) { data = new byte[dwCertPublicKeyBlobSize]; if (!RSACryptoServiceProviderExtension.CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING, new IntPtr((int)CRYPT_OUTPUT_TYPES.RSA_CSP_PUBLICKEYBLOB), RSAData, (UInt32)RSAData.Length, CRYPT_DECODE_FLAGS.NONE, data, ref dwCertPublicKeyBlobSize)) throw new Win32Exception(Marshal.GetLastWin32Error()); } else throw new Win32Exception(Marshal.GetLastWin32Error()); return data; } /// <summary>Converts DER binary format to a CAPI CRYPT_PRIVATE_KEY_INFO structure.</summary> internal static byte[] GetPrivateKeyDER(byte[] DERData) { byte[] data = null; UInt32 dwRSAPrivateKeyBlobSize = 0; IntPtr pRSAPrivateKeyBlob = IntPtr.Zero; if (RSACryptoServiceProviderExtension.CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING, new IntPtr((int)CRYPT_OUTPUT_TYPES.PKCS_RSA_PRIVATE_KEY), DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, ref dwRSAPrivateKeyBlobSize)) { data = new byte[dwRSAPrivateKeyBlobSize]; if (!RSACryptoServiceProviderExtension.CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING, new IntPtr((int)CRYPT_OUTPUT_TYPES.PKCS_RSA_PRIVATE_KEY), DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, ref dwRSAPrivateKeyBlobSize)) throw new Win32Exception(Marshal.GetLastWin32Error()); } else throw new Win32Exception(Marshal.GetLastWin32Error()); return data; } /// <summary>Converts DER binary format to a CAPI CERT_PUBLIC_KEY_INFO structure containing an RSA key.</summary> internal static byte[] GetRSAFromDER(byte[] DERData) { byte[] data = null; byte[] publicKey = null; CERT_PUBLIC_KEY_INFO info; UInt32 dwCertPublicKeyInfoSize = 0; IntPtr pCertPublicKeyInfo = IntPtr.Zero; if (RSACryptoServiceProviderExtension.CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING, new IntPtr((int)CRYPT_OUTPUT_TYPES.X509_PUBLIC_KEY_INFO), DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, ref dwCertPublicKeyInfoSize)) { data = new byte[dwCertPublicKeyInfoSize]; if (RSACryptoServiceProviderExtension.CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING, new IntPtr((int)CRYPT_OUTPUT_TYPES.X509_PUBLIC_KEY_INFO), DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, ref dwCertPublicKeyInfoSize)) { GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); try { info = (CERT_PUBLIC_KEY_INFO)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(CERT_PUBLIC_KEY_INFO)); publicKey = new byte[info.PublicKey.cbData]; Marshal.Copy(info.PublicKey.pbData, publicKey, 0, publicKey.Length); } finally { handle.Free(); } } else throw new Win32Exception(Marshal.GetLastWin32Error()); } else throw new Win32Exception(Marshal.GetLastWin32Error()); return publicKey; } /// <summary>Extracts the binary data from a PEM file.</summary> internal static byte[] GetDERFromPEM(string sPEM) { UInt32 dwSkip, dwFlags; UInt32 dwBinarySize = 0; if (!RSACryptoServiceProviderExtension.CryptStringToBinary(sPEM, (UInt32)sPEM.Length, CRYPT_STRING_FLAGS.CRYPT_STRING_BASE64HEADER, null, ref dwBinarySize, out dwSkip, out dwFlags)) throw new Win32Exception(Marshal.GetLastWin32Error()); byte[] decodedData = new byte[dwBinarySize]; if (!RSACryptoServiceProviderExtension.CryptStringToBinary(sPEM, (UInt32)sPEM.Length, CRYPT_STRING_FLAGS.CRYPT_STRING_BASE64HEADER, decodedData, ref dwBinarySize, out dwSkip, out dwFlags)) throw new Win32Exception(Marshal.GetLastWin32Error()); return decodedData; } #endregion Methods #region P/Invoke Constants /// <summary>Enumeration derived from Crypto API.</summary> internal enum CRYPT_ACQUIRE_CONTEXT_FLAGS : uint { CRYPT_NEWKEYSET = 0x8, CRYPT_DELETEKEYSET = 0x10, CRYPT_MACHINE_KEYSET = 0x20, CRYPT_SILENT = 0x40, CRYPT_DEFAULT_CONTAINER_OPTIONAL = 0x80, CRYPT_VERIFYCONTEXT = 0xF0000000 } /// <summary>Enumeration derived from Crypto API.</summary> internal enum CRYPT_PROVIDER_TYPE : uint { PROV_RSA_FULL = 1 } /// <summary>Enumeration derived from Crypto API.</summary> internal enum CRYPT_DECODE_FLAGS : uint { NONE = 0, CRYPT_DECODE_ALLOC_FLAG = 0x8000 } /// <summary>Enumeration derived from Crypto API.</summary> internal enum CRYPT_ENCODING_FLAGS : uint { PKCS_7_ASN_ENCODING = 0x00010000, X509_ASN_ENCODING = 0x00000001, } /// <summary>Enumeration derived from Crypto API.</summary> internal enum CRYPT_OUTPUT_TYPES : int { X509_PUBLIC_KEY_INFO = 8, RSA_CSP_PUBLICKEYBLOB = 19, PKCS_RSA_PRIVATE_KEY = 43, PKCS_PRIVATE_KEY_INFO = 44 } /// <summary>Enumeration derived from Crypto API.</summary> internal enum CRYPT_STRING_FLAGS : uint { CRYPT_STRING_BASE64HEADER = 0, CRYPT_STRING_BASE64 = 1, CRYPT_STRING_BINARY = 2, CRYPT_STRING_BASE64REQUESTHEADER = 3, CRYPT_STRING_HEX = 4, CRYPT_STRING_HEXASCII = 5, CRYPT_STRING_BASE64_ANY = 6, CRYPT_STRING_ANY = 7, CRYPT_STRING_HEX_ANY = 8, CRYPT_STRING_BASE64X509CRLHEADER = 9, CRYPT_STRING_HEXADDR = 10, CRYPT_STRING_HEXASCIIADDR = 11, CRYPT_STRING_HEXRAW = 12, CRYPT_STRING_NOCRLF = 0x40000000, CRYPT_STRING_NOCR = 0x80000000 } #endregion P/Invoke Constants #region P/Invoke Structures /// <summary>Structure from Crypto API.</summary> [StructLayout(LayoutKind.Sequential)] internal struct CRYPT_OBJID_BLOB { internal UInt32 cbData; internal IntPtr pbData; } /// <summary>Structure from Crypto API.</summary> [StructLayout(LayoutKind.Sequential)] internal struct CRYPT_ALGORITHM_IDENTIFIER { internal IntPtr pszObjId; internal CRYPT_OBJID_BLOB Parameters; } /// <summary>Structure from Crypto API.</summary> [StructLayout(LayoutKind.Sequential)] struct CRYPT_BIT_BLOB { internal UInt32 cbData; internal IntPtr pbData; internal UInt32 cUnusedBits; } /// <summary>Structure from Crypto API.</summary> [StructLayout(LayoutKind.Sequential)] struct CERT_PUBLIC_KEY_INFO { internal CRYPT_ALGORITHM_IDENTIFIER Algorithm; internal CRYPT_BIT_BLOB PublicKey; } #endregion P/Invoke Structures #region P/Invoke Functions /// <summary>Function for Crypto API.</summary> [DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CryptDestroyKey(IntPtr hKey); /// <summary>Function for Crypto API.</summary> [DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CryptImportKey(IntPtr hProv, byte[] pbKeyData, UInt32 dwDataLen, IntPtr hPubKey, UInt32 dwFlags, ref IntPtr hKey); /// <summary>Function for Crypto API.</summary> [DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CryptReleaseContext(IntPtr hProv, Int32 dwFlags); /// <summary>Function for Crypto API.</summary> [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CryptAcquireContext(ref IntPtr hProv, string pszContainer, string pszProvider, CRYPT_PROVIDER_TYPE dwProvType, CRYPT_ACQUIRE_CONTEXT_FLAGS dwFlags); /// <summary>Function from Crypto API.</summary> [DllImport("crypt32.dll", SetLastError = true, CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CryptStringToBinary(string sPEM, UInt32 sPEMLength, CRYPT_STRING_FLAGS dwFlags, [Out] byte[] pbBinary, ref UInt32 pcbBinary, out UInt32 pdwSkip, out UInt32 pdwFlags); /// <summary>Function from Crypto API.</summary> [DllImport("crypt32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CryptDecodeObjectEx(CRYPT_ENCODING_FLAGS dwCertEncodingType, IntPtr lpszStructType, byte[] pbEncoded, UInt32 cbEncoded, CRYPT_DECODE_FLAGS dwFlags, IntPtr pDecodePara, ref byte[] pvStructInfo, ref UInt32 pcbStructInfo); /// <summary>Function from Crypto API.</summary> [DllImport("crypt32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CryptDecodeObject(CRYPT_ENCODING_FLAGS dwCertEncodingType, IntPtr lpszStructType, byte[] pbEncoded, UInt32 cbEncoded, CRYPT_DECODE_FLAGS flags, [In, Out] byte[] pvStructInfo, ref UInt32 cbStructInfo); #endregion P/Invoke Functions } }
相关推荐
java aes128/256 对称加密解密,rsa对称加密解密验签实现,php java通用aes加密 支持任何形式的aes加密,文件,字符,字节等,内含php代码,可以与php平台实现aes加密,而且包含rsa非对称加密签名验签实现,都是对...
本文件包括了demo和安装对应的环境、安装教程、简单易懂,正常php的rsa签名是使用openssl_sign,但是对应java中CFCASignature.signature的签名的签名时候对不上,要使用扩展php_com_dotnet并且对应安装签名的环境 ...
`RSA2Util.java`这个文件很可能包含了一个工具类,提供了以下功能: 1. **密钥对生成**:工具类可能会包含一个方法来生成RSA的公钥和私钥。这通常涉及使用Java的`KeyPairGenerator`类,设置RSA算法,并通过`...
"java_PHP翼支付签名验签.zip"这个压缩包文件包含的是关于Java和PHP如何实现翼支付平台的签名验证和证书认证的相关示例代码。这涉及到网络安全、数据加密以及支付接口的安全通信等多个关键知识点。 1. **签名验签...
在Delphi编程环境中,可以实现RSA的加密、解密和签名功能,与其他编程语言如C、Java和PHP具有良好的兼容性,确保跨平台的信息安全交互。 首先,理解RSA的核心概念: 1. **公钥和私钥**:RSA的核心在于一对密钥,即...
本篇文章将深入探讨Delphi (从delphi7到XE版本)中的RSA实现,以及如何与其他编程语言如C、Java、PHP进行跨平台的加解密和签名操作。 1. RSA原理: RSA基于数论中的大数因子分解难题,由Ron Rivest、Adi Shamir和...
总结来说,"使用RSA、MD5对参数生成签名及接收方验签"是一个典型的数字签名应用场景,结合了非对称加密和哈希函数的优点,实现了数据传输的安全性。在实际操作中,根据安全性需求,可以选择更安全的替代算法,如使用...
在IT行业中,尤其是在网络安全和支付领域,签名和验签是至关重要的步骤,它们确保了数据的完整性和不可篡改性。这里的"中行PHP签名验签demo"是为中国银行(中行)的支付系统设计的一个PHP示例,它利用了SHA256和PKCS...
主要介绍了PHP SHA1withRSA加密生成签名及验签,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
总的来说,这个压缩包提供了一套工具,用于生成和操作RSA算法的密钥,包括1024位和2048位的密钥,同时支持Java和PHP环境,以及提供了一套基础的操作流程。使用这些工具时,需要注意密钥的保护,私钥应妥善保管,防止...
在Java和PHP这样的编程语言中,通常使用非对称加密算法,如RSA,来实现这一过程。非对称加密算法拥有公钥和私钥两部分,私钥用于加签,公钥用于验签。 在给定的实例中,我们看到PHP和Java之间进行加签验签时,涉及...
在PHP中,RSA的加密、解密、签名和验签过程是实现安全通信的关键步骤,特别是当与使用不同编程语言(如Java)的第三方系统进行交互时。下面将详细介绍这些过程以及如何在PHP中实现它们。 首先,我们需要准备RSA密钥...
这个项目的描述表明它是一个基于Java开发的系统,且已成功调通并投入实际使用,意味着该系统已经在处理授权、支付等相关功能。 在深入探讨这个项目涉及的技术知识点之前,我们先来了解一下Java开发语言。Java是一种...
验签失败是请求我们web接口时,签名异常。 3.2.1、待签名串格式不正确,我们这把请求数据中的所有元素(除sign本身)按照“key值=value值”的格式拼接起来,若顺序或者格式不正确的话,就会包错。 注:请求时字段...
C#版SDK通常会依赖System.Net命名空间中的HttpClient类进行网络请求。 5. **ASP接口**:对于经典的ASP环境,开发者可能需要使用XMLHttpRequest对象或者ServerXMLHTTP对象来发送HTTP请求,并处理返回的结果。ASP接口...
2. **RSA签名与验签**:为了确保交易的安全性,支付宝使用了非对称加密算法RSA进行签名和验签。开发者需要使用自己的私钥进行签名,支付宝使用公钥验证签名的有效性,反之亦然,支付宝使用其私钥签名,开发者用公钥...
开发者需要正确实现签名算法,通常是RSA或RSA2。 3. **请求支付接口**:根据业务需求,调用相应的API,如即时到账、担保交易等,构建并发送请求数据。 4. **处理支付结果**:当用户完成支付后,支付宝会回调商户设定...
2. **多语言支持**:OpenSSL库不仅支持C语言,还通过提供API接口,使得其他编程语言可以方便地调用其功能,例如Python、PHP、Java等。 3. **SSL/TLS 协议支持**:此版本支持SSLv3、TLSv1.0、TLSv1.1和TLSv1.2,不过...