本文是上一篇文章的兄弟篇,上篇文章介绍了客户端的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 = ;
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 = ;
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 = ;
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, , 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 = ; 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 =
} /// <summary>Enumeration derived from Crypto API.</summary>
internal enum CRYPT_DECODE_FLAGS : uint
{
NONE = ,
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 = ,
RSA_CSP_PUBLICKEYBLOB = ,
PKCS_RSA_PRIVATE_KEY = ,
PKCS_PRIVATE_KEY_INFO =
} /// <summary>Enumeration derived from Crypto API.</summary>
internal enum CRYPT_STRING_FLAGS : uint
{
CRYPT_STRING_BASE64HEADER = ,
CRYPT_STRING_BASE64 = ,
CRYPT_STRING_BINARY = ,
CRYPT_STRING_BASE64REQUESTHEADER = ,
CRYPT_STRING_HEX = ,
CRYPT_STRING_HEXASCII = ,
CRYPT_STRING_BASE64_ANY = ,
CRYPT_STRING_ANY = ,
CRYPT_STRING_HEX_ANY = ,
CRYPT_STRING_BASE64X509CRLHEADER = ,
CRYPT_STRING_HEXADDR = ,
CRYPT_STRING_HEXASCIIADDR = ,
CRYPT_STRING_HEXRAW = ,
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
}
}

原文地址:http://xw-z1985.iteye.com/blog/1929931

JAVA/PHP/C#版RSA验签--转的更多相关文章

  1. java/php/c#版rsa签名以及java验签实现--转

    在开放平台领域,需要给isv提供sdk,签名是Sdk中需要提供的功能之一.由于isv使用的开发语言不是单一的,因此sdk需要提供多种语言的版本.譬如java.php.c#.另外,在电子商务尤其是支付领 ...

  2. java/php/c#版rsa签名以及验签实现

    本文为转载,请转载请注明地址: 原文地址为        http://xw-z1985.iteye.com/blog/1837376 在开放平台领域,需要给isv提供sdk,签名是Sdk中需要提供的 ...

  3. ios RSA 验签加密解密

    关于公钥和私钥的生成,网上有很多本地生产的方法,我遇到的问题是,按照网上生产的方式生成7个文件,本地使用没有问题,但是和后台交互就不行了. 发现生成公钥和私钥的没有那么麻烦,使用在线生产工具就能使用, ...

  4. java RSA验签

    这几天在跟一个php的小哥哥联调接口,遇到了一些问题记录下来, 直接上代码吧,亲测有效 import org.slf4j.Logger; import org.slf4j.LoggerFactory; ...

  5. 【加密】RSA验签及加密

    通过OpenSSL生成公私钥文件(如果没有OpenSSL工具建议下载Cmder工具自带OpenSSL指令) 1.生成RSA密钥的方法 genrsa -out private-rsa.key 2048 ...

  6. .NET Core RSA 签名和验签(密钥为 16 进制编码)

    使用 OpenSSL 生成公私钥对,命令: $ openssl genrsa -out rsa_1024_priv.pem $ openssl pkcs8 -topk8 -inform PEM -in ...

  7. RSA加密、解密、签名、验签的原理及方法

    一.RSA加密简介 RSA加密是一种非对称加密.可以在不直接传递密钥的情况下,完成解密.这能够确保信息的安全性,避免了直接传递密钥所造成的被破解的风险.是由一对密钥来进行加解密的过程,分别称为公钥和私 ...

  8. RSA后台签名前台验签的应用(前台采用jsrsasign库)

    写在前面 安全测试需要, 为防止后台响应数据返给前台过程中被篡改前台再拿被篡改后的数据进行接下来的操作影响正常业务, 决定采用RSA对响应数据进行签名和验签, 于是有了这篇<RSA后台签名前台验 ...

  9. js rsa sign使用笔记(加密,解密,签名,验签)

    你将会收获: js如何加密, 解密 js如何签名, 验签 js和Java交互如何相互解密, 验签(重点) 通过谷歌, 发现jsrsasign库使用者较多. 查看api发现这个库功能很健全. 本文使用方 ...

随机推荐

  1. MFC框架类、文档类、视图类相互访问的方法

    1.获取应用程序指针 CMyApp* pApp=(CMyApp*)AfxGetApp(); 2.获取主框架指针 CWinApp 中的公有成员变量 m_pMainWnd 就是主框架的指针 CMainFr ...

  2. vi文本编辑器

    vi文本编辑器分为3个模式: 命令模式 插入模式 ex模式 在命令模式下我们可以使用一下功能 o 插入新的行 u 撤销 n yy  复制n行 p 粘贴 / 查找 i 进入插入模式 exc到命令模式 e ...

  3. 用 javascript 判断 IE 版本号

    原文地址: http://julying.com/blog/determine-the-version-number-of-ie-with-javascript/ var _IE = (functio ...

  4. 使用Code::Blocks配置Python编译环境

    1.先在CodeBlock中新建C或C++工程. CodeBlock新建工程步骤:File——New——Project——Console applications——C或C++都可——Project所 ...

  5. Python 可变对象和不可变对象

    具体可以看这里:http://thomaschen2011.iteye.com/blog/1441254 不可变对象:int,string,float,tuple 可变对象   :list,dicti ...

  6. Ubiquitous Religions

    http://poj.org/problem?id=2524 这道题就是并查集. #include<cstdio> #include<cstring> #include< ...

  7. 使用Windows 系统性能监控来报警磁盘空间不足

    http://blog.csdn.net/jiangxinyu/article/details/4370288

  8. mysqldump 一些参数体验

    mysqldump -uroot -p'xxx' -R --single-transaction --master-data=2 zjzc>$TODAY_DIR/zjzc/zjzc_${TODA ...

  9. 【HDOJ】4325 Flowers

    树状数组+离散化的题目,一直在思考为什么结果不一样,后来才发现花开了就是开了不会再谢了. /* 4325 */ #include <iostream> #include <cstdi ...

  10. 【HDOJ】4278 Faulty Odomete

    水题. /* 4278 */ #include <cstdio> #include <cstring> #include <cstdlib> #define MAX ...