1 public classRsa2 {3 /** 默认编码字符集*/
4 private static string DEFAULT_CHARSET = "UTF-8";5 ///
6 ///RSA公钥加密7 ///
8 ///
9 ///
10 ///
11 ///
12 public static string RSAEncrypt(string content, string publicKeyPem, string charset= "UTF-8")13 {14 RSACryptoServiceProvider rsa = newRSACryptoServiceProvider();15 rsa.PersistKeyInCsp = false;16 RSACryptoServiceProviderExtension.LoadPublicKeyPEM(rsa, publicKeyPem);17 if (string.IsNullOrEmpty(charset))18 {19 charset =DEFAULT_CHARSET;20 }21 byte[] data =Encoding.GetEncoding(charset).GetBytes(content);22 int maxBlockSize = rsa.KeySize / 8 - 11; //加密块最大长度限制
23 if (data.Length <=maxBlockSize)24 {25 byte[] cipherbytes = rsa.Encrypt(data, true);26 returnConvert.ToBase64String(cipherbytes);27 }28 MemoryStream plaiStream = newMemoryStream(data);29 MemoryStream crypStream = newMemoryStream();30 Byte[] buffer = newByte[maxBlockSize];31 int blockSize = plaiStream.Read(buffer, 0, maxBlockSize);32 while (blockSize > 0)33 {34 Byte[] toEncrypt = newByte[blockSize];35 Array.Copy(buffer, 0, toEncrypt, 0, blockSize);36 Byte[] cryptograph = rsa.Encrypt(toEncrypt, false);37 crypStream.Write(cryptograph, 0, cryptograph.Length);38 blockSize = plaiStream.Read(buffer, 0, maxBlockSize);39 }40
41 returnConvert.ToBase64String(crypStream.ToArray(), Base64FormattingOptions.None);42 }43 }44 /// Extension method for initializing a RSACryptoServiceProvider from PEM data string.
45 public static classRSACryptoServiceProviderExtension46 {47 #region Methods
48
49 /// Extension method which initializes an RSACryptoServiceProvider from a DER public key blob.
50 public static void LoadPublicKeyDER(this RSACryptoServiceProvider provider, byte[] DERData)51 {52 byte[] RSAData =RSACryptoServiceProviderExtension.GetRSAFromDER(DERData);53 byte[] publicKeyBlob =RSACryptoServiceProviderExtension.GetPublicKeyBlobFromRSA(RSAData);54 provider.ImportCspBlob(publicKeyBlob);55 }56
57 /// Extension method which initializes an RSACryptoServiceProvider from a DER private key blob.
58 public static void LoadPrivateKeyDER(this RSACryptoServiceProvider provider, byte[] DERData)59 {60 byte[] privateKeyBlob =RSACryptoServiceProviderExtension.GetPrivateKeyDER(DERData);61 provider.ImportCspBlob(privateKeyBlob);62 }63
64 /// Extension method which initializes an RSACryptoServiceProvider from a PEM public key string.
65 public static void LoadPublicKeyPEM(this RSACryptoServiceProvider provider, stringsPEM)66 {67 byte[] DERData =RSACryptoServiceProviderExtension.GetDERFromPEM(sPEM);68 RSACryptoServiceProviderExtension.LoadPublicKeyDER(provider, DERData);69 }70
71 /// Extension method which initializes an RSACryptoServiceProvider from a PEM private key string.
72 public static void LoadPrivateKeyPEM(this RSACryptoServiceProvider provider, stringsPEM)73 {74 byte[] DERData =RSACryptoServiceProviderExtension.GetDERFromPEM(sPEM);75 RSACryptoServiceProviderExtension.LoadPrivateKeyDER(provider, DERData);76 }77
78 /// Returns a public key blob from an RSA public key.
79 internal static byte[] GetPublicKeyBlobFromRSA(byte[] RSAData)80 {81 byte[] data = null;82 UInt32 dwCertPublicKeyBlobSize = 0;83 if (RSACryptoServiceProviderExtension.CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING |CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING,84 new IntPtr((int)CRYPT_OUTPUT_TYPES.RSA_CSP_PUBLICKEYBLOB), RSAData, (UInt32)RSAData.Length, CRYPT_DECODE_FLAGS.NONE,85 data, refdwCertPublicKeyBlobSize))86 {87 data = new byte[dwCertPublicKeyBlobSize];88 if (!RSACryptoServiceProviderExtension.CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING |CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING,89 new IntPtr((int)CRYPT_OUTPUT_TYPES.RSA_CSP_PUBLICKEYBLOB), RSAData, (UInt32)RSAData.Length, CRYPT_DECODE_FLAGS.NONE,90 data, refdwCertPublicKeyBlobSize))91 throw newWin32Exception(Marshal.GetLastWin32Error());92 }93 else
94 throw newWin32Exception(Marshal.GetLastWin32Error());95 returndata;96 }97
98 /// Converts DER binary format to a CAPI CRYPT_PRIVATE_KEY_INFO structure.
99 internal static byte[] GetPrivateKeyDER(byte[] DERData)100 {101 byte[] data = null;102 UInt32 dwRSAPrivateKeyBlobSize = 0;103 IntPtr pRSAPrivateKeyBlob =IntPtr.Zero;104 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),105 DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, refdwRSAPrivateKeyBlobSize))106 {107 data = new byte[dwRSAPrivateKeyBlobSize];108 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),109 DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, refdwRSAPrivateKeyBlobSize))110 throw newWin32Exception(Marshal.GetLastWin32Error());111 }112 else
113 throw newWin32Exception(Marshal.GetLastWin32Error());114 returndata;115 }116
117 /// Converts DER binary format to a CAPI CERT_PUBLIC_KEY_INFO structure containing an RSA key.
118 internal static byte[] GetRSAFromDER(byte[] DERData)119 {120 byte[] data = null;121 byte[] publicKey = null;122 CERT_PUBLIC_KEY_INFO info;123 UInt32 dwCertPublicKeyInfoSize = 0;124 IntPtr pCertPublicKeyInfo =IntPtr.Zero;125 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),126 DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, refdwCertPublicKeyInfoSize))127 {128 data = new byte[dwCertPublicKeyInfoSize];129 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),130 DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, refdwCertPublicKeyInfoSize))131 {132 GCHandle handle =GCHandle.Alloc(data, GCHandleType.Pinned);133 try
134 {135 info = (CERT_PUBLIC_KEY_INFO)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(CERT_PUBLIC_KEY_INFO));136 publicKey = new byte[info.PublicKey.cbData];137 Marshal.Copy(info.PublicKey.pbData, publicKey, 0, publicKey.Length);138 }139 finally
140 {141 handle.Free();142 }143 }144 else
145 throw newWin32Exception(Marshal.GetLastWin32Error());146 }147 else
148 throw newWin32Exception(Marshal.GetLastWin32Error());149 returnpublicKey;150 }151
152 /// Extracts the binary data from a PEM file.
153 internal static byte[] GetDERFromPEM(stringsPEM)154 {155 UInt32 dwSkip, dwFlags;156 UInt32 dwBinarySize = 0;157
158 if (!RSACryptoServiceProviderExtension.CryptStringToBinary(sPEM, (UInt32)sPEM.Length, CRYPT_STRING_FLAGS.CRYPT_STRING_BASE64HEADER, null, ref dwBinarySize, out dwSkip, outdwFlags))159 throw newWin32Exception(Marshal.GetLastWin32Error());160
161 byte[] decodedData = new byte[dwBinarySize];162 if (!RSACryptoServiceProviderExtension.CryptStringToBinary(sPEM, (UInt32)sPEM.Length, CRYPT_STRING_FLAGS.CRYPT_STRING_BASE64HEADER, decodedData, ref dwBinarySize, out dwSkip, outdwFlags))163 throw newWin32Exception(Marshal.GetLastWin32Error());164 returndecodedData;165 }166
167 #endregion Methods
168
169 #region P/Invoke Constants
170
171 /// Enumeration derived from Crypto API.
172 internal enum CRYPT_ACQUIRE_CONTEXT_FLAGS : uint
173 {174 CRYPT_NEWKEYSET = 0x8,175 CRYPT_DELETEKEYSET = 0x10,176 CRYPT_MACHINE_KEYSET = 0x20,177 CRYPT_SILENT = 0x40,178 CRYPT_DEFAULT_CONTAINER_OPTIONAL = 0x80,179 CRYPT_VERIFYCONTEXT = 0xF0000000
180 }181
182 /// Enumeration derived from Crypto API.
183 internal enum CRYPT_PROVIDER_TYPE : uint
184 {185 PROV_RSA_FULL = 1
186 }187
188 /// Enumeration derived from Crypto API.
189 internal enum CRYPT_DECODE_FLAGS : uint
190 {191 NONE = 0,192 CRYPT_DECODE_ALLOC_FLAG = 0x8000
193 }194
195 /// Enumeration derived from Crypto API.
196 internal enum CRYPT_ENCODING_FLAGS : uint
197 {198 PKCS_7_ASN_ENCODING = 0x00010000,199 X509_ASN_ENCODING = 0x00000001,200 }201
202 /// Enumeration derived from Crypto API.
203 internal enum CRYPT_OUTPUT_TYPES : int
204 {205 X509_PUBLIC_KEY_INFO = 8,206 RSA_CSP_PUBLICKEYBLOB = 19,207 PKCS_RSA_PRIVATE_KEY = 43,208 PKCS_PRIVATE_KEY_INFO = 44
209 }210
211 /// Enumeration derived from Crypto API.
212 internal enum CRYPT_STRING_FLAGS : uint
213 {214 CRYPT_STRING_BASE64HEADER = 0,215 CRYPT_STRING_BASE64 = 1,216 CRYPT_STRING_BINARY = 2,217 CRYPT_STRING_BASE64REQUESTHEADER = 3,218 CRYPT_STRING_HEX = 4,219 CRYPT_STRING_HEXASCII = 5,220 CRYPT_STRING_BASE64_ANY = 6,221 CRYPT_STRING_ANY = 7,222 CRYPT_STRING_HEX_ANY = 8,223 CRYPT_STRING_BASE64X509CRLHEADER = 9,224 CRYPT_STRING_HEXADDR = 10,225 CRYPT_STRING_HEXASCIIADDR = 11,226 CRYPT_STRING_HEXRAW = 12,227 CRYPT_STRING_NOCRLF = 0x40000000,228 CRYPT_STRING_NOCR = 0x80000000
229 }230
231 #endregion P/Invoke Constants
232
233 #region P/Invoke Structures
234
235 /// Structure from Crypto API.
236 [StructLayout(LayoutKind.Sequential)]237 internal structCRYPT_OBJID_BLOB238 {239 internalUInt32 cbData;240 internalIntPtr pbData;241 }242
243 /// Structure from Crypto API.
244 [StructLayout(LayoutKind.Sequential)]245 internal structCRYPT_ALGORITHM_IDENTIFIER246 {247 internalIntPtr pszObjId;248 internalCRYPT_OBJID_BLOB Parameters;249 }250
251 /// Structure from Crypto API.
252 [StructLayout(LayoutKind.Sequential)]253 structCRYPT_BIT_BLOB254 {255 internalUInt32 cbData;256 internalIntPtr pbData;257 internalUInt32 cUnusedBits;258 }259
260 /// Structure from Crypto API.
261 [StructLayout(LayoutKind.Sequential)]262 structCERT_PUBLIC_KEY_INFO263 {264 internalCRYPT_ALGORITHM_IDENTIFIER Algorithm;265 internalCRYPT_BIT_BLOB PublicKey;266 }267
268 #endregion P/Invoke Structures
269
270 #region P/Invoke Functions
271
272 /// Function for Crypto API.
273 [DllImport("advapi32.dll", SetLastError = true)]274 [return: MarshalAs(UnmanagedType.Bool)]275 internal static extern boolCryptDestroyKey(IntPtr hKey);276
277 /// Function for Crypto API.
278 [DllImport("advapi32.dll", SetLastError = true)]279 [return: MarshalAs(UnmanagedType.Bool)]280 internal static extern bool CryptImportKey(IntPtr hProv, byte[] pbKeyData, UInt32 dwDataLen, IntPtr hPubKey, UInt32 dwFlags, refIntPtr hKey);281
282 /// Function for Crypto API.
283 [DllImport("advapi32.dll", SetLastError = true)]284 [return: MarshalAs(UnmanagedType.Bool)]285 internal static extern boolCryptReleaseContext(IntPtr hProv, Int32 dwFlags);286
287 /// Function for Crypto API.
288 [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]289 [return: MarshalAs(UnmanagedType.Bool)]290 internal static extern bool CryptAcquireContext(ref IntPtr hProv, string pszContainer, stringpszProvider, CRYPT_PROVIDER_TYPE dwProvType, CRYPT_ACQUIRE_CONTEXT_FLAGS dwFlags);291
292 /// Function from Crypto API.
293 [DllImport("crypt32.dll", SetLastError = true, CharSet =CharSet.Auto)]294 [return: MarshalAs(UnmanagedType.Bool)]295 internal static extern bool CryptStringToBinary(string sPEM, UInt32 sPEMLength, CRYPT_STRING_FLAGS dwFlags, [Out] byte[] pbBinary, ref UInt32 pcbBinary, out UInt32 pdwSkip, outUInt32 pdwFlags);296
297 /// Function from Crypto API.
298 [DllImport("crypt32.dll", SetLastError = true)]299 [return: MarshalAs(UnmanagedType.Bool)]300 internal static extern bool CryptDecodeObjectEx(CRYPT_ENCODING_FLAGS dwCertEncodingType, IntPtr lpszStructType, byte[] pbEncoded, UInt32 cbEncoded, CRYPT_DECODE_FLAGS dwFlags, IntPtr pDecodePara, ref byte[] pvStructInfo, refUInt32 pcbStructInfo);301
302 /// Function from Crypto API.
303 [DllImport("crypt32.dll", SetLastError = true)]304 [return: MarshalAs(UnmanagedType.Bool)]305 internal static extern bool CryptDecodeObject(CRYPT_ENCODING_FLAGS dwCertEncodingType, IntPtr lpszStructType, byte[] pbEncoded, UInt32 cbEncoded, CRYPT_DECODE_FLAGS flags, [In, Out] byte[] pvStructInfo, refUInt32 cbStructInfo);306
307 #endregion P/Invoke Functions
308 }