⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rsacryptoserviceprovider.cs

📁 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的
💻 CS
📖 第 1 页 / 共 2 页
字号:
/* * RSACryptoServiceProvider.cs - Implementation of the *		"System.Security.Cryptography.RSACryptoServiceProvider" class. * * Copyright (C) 2002  Southern Storm Software, Pty Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */namespace System.Security.Cryptography{#if CONFIG_CRYPTOusing System;using System.IO;using Platform;// Note: this class assumes that the RSA parameters can be accessed// in main memory.  This may not necessarily be the case if the// system is using smart cards or some other kind of crypto dongle.// We will modify this class when and if that becomes an issue.//// This implementation is based on the RSA description in PKCS #1 v2.1,// available from "http://www.rsa.com/".public sealed class RSACryptoServiceProvider : RSA{	// Internal state.	private bool persistKey;	private static bool useMachineKeyStore;	private RSAParameters rsaParams;	// Constructors.	public RSACryptoServiceProvider()			: this(0, null) {}	public RSACryptoServiceProvider(CspParameters parameters)			: this(0, parameters) {}	public RSACryptoServiceProvider(int dwKeySize)			: this(dwKeySize, null) {}	public RSACryptoServiceProvider(int dwKeySize, CspParameters parameters)			{				byte[] key;				int result;				// See "DSACryptoServiceProvider" for explainatory comments.				if(parameters != null && parameters.KeyContainerName != null)				{					// Attempt to get an RSA key from the user's keychain.					key = CryptoMethods.GetKey(CryptoMethods.RSAEncrypt,											   parameters.KeyContainerName,											   parameters.Flags,											   out result);					if(key != null)					{						// The "ASN1ToPublic" method will determine if						// the key is X.509, bare public, or private.						rsaParams.ASN1ToPublic(key, 0, key.Length);						Array.Clear(key, 0, key.Length);						persistKey = true;					}					else if(result == CryptoMethods.UnknownKey)					{						throw new CryptographicException							(_("Crypto_UnknownKey"),							 parameters.KeyContainerName);					}					else if(result == CryptoMethods.NotPermitted)					{						throw new CryptographicException							(_("Crypto_NoKeyAccess"),							 parameters.KeyContainerName);					}					else if(result == CryptoMethods.GenerateKey)					{						// Generate a new key for the user.						// TODO					}				}			}	// Destructor.	~RSACryptoServiceProvider()			{				Dispose(false);			}	// Dispose this algorithm instance.	protected override void Dispose(bool disposing)			{				rsaParams.Clear();			}	// Get the name of the key exchange algorithm.	public override String KeyExchangeAlgorithm			{				get				{					return "RSA-PKCS1-KeyEx";				}			}	// Get or set the size of the key modulus, in bits.	public override int KeySize			{				get				{					return KeySizeValue;				}				set				{					base.KeySize = value;				}			}	// Determine if the key should be persisted in the CSP.	public bool PersistKeyInCsp			{				get				{					return persistKey;				}				set				{					persistKey = value;				}			}	// Get the name of the signature algorithm.	public override String SignatureAlgorithm			{				get				{					// W3C identifier for the RSA-SHA1 algorithm.					return "http://www.w3.org/2000/09/xmldsig#rsa-sha1";				}			}	// Determine if we should use the machine key store.	public static bool UseMachineKeyStore			{				get				{					return useMachineKeyStore;				}				set				{					useMachineKeyStore = value;				}			}	// Apply the public key to a value.	private byte[] ApplyPublic(byte[] value)			{				if(rsaParams.Modulus == null)				{					throw new CryptographicException						(_("Crypto_RSAParamsNotSet"));				}				return CryptoMethods.NumPow(value, rsaParams.Exponent,											rsaParams.Modulus);			}	// Apply the private key to a value.	private byte[] ApplyPrivate(byte[] value)			{				if(rsaParams.P != null)				{					// Use the Chinese Remainder Theorem exponents.					// Based on the description in PKCS #1.					byte[] m1   = CryptoMethods.NumPow(value, rsaParams.DP,													   rsaParams.P);					byte[] m2   = CryptoMethods.NumPow(value, rsaParams.DQ,													   rsaParams.Q);					byte[] diff = CryptoMethods.NumSub(m1, m2, null);					byte[] h    = CryptoMethods.NumMul(diff,													   rsaParams.InverseQ,													   rsaParams.P);					byte[] prod = CryptoMethods.NumMul(rsaParams.Q, h, null);					byte[] m    = CryptoMethods.NumAdd(m2, prod, null);					// Clear all temporary values.					Array.Clear(m1, 0, m1.Length);					Array.Clear(m2, 0, m2.Length);					Array.Clear(diff, 0, diff.Length);					Array.Clear(h, 0, h.Length);					Array.Clear(prod, 0, prod.Length);										// Return the decrypted message.					return m;				}				else if(rsaParams.D != null)				{					// Use the private exponent directly.					return CryptoMethods.NumPow(value, rsaParams.D,												rsaParams.Modulus);				}				else				{					// Insufficient parameters for private key operations.					throw new CryptographicException						(_("Crypto_RSAParamsNotSet"));				}			}	// Decrypt a value using the RSA private key and OAEP padding.	internal byte[] DecryptOAEP(byte[] rgb)			{				// Check the data against null.				if(rgb == null)				{					throw new ArgumentNullException("rgb");				}				// Make sure that we have sufficient RSA parameters.				if(rsaParams.Modulus == null)				{					throw new CryptographicException						(_("Crypto_RSAParamsNotSet"));				}				// Check the length of the incoming value.				int k = rsaParams.Modulus.Length;				if(k < (2 * 20 + 2))				{					throw new CryptographicException						(_("Crypto_RSAKeyTooShort"));				}				// Decrypt the incoming value, and expand to k octets,				// as the big number routines in the engine may have				// stripped leading zeroes from the value.				byte[] decrypted = ApplyPrivate(rgb);				if(decrypted.Length > k)				{					Array.Clear(decrypted, 0, decrypted.Length);					throw new CryptographicException						(_("Crypto_RSAInvalidCiphertext"));				}				byte[] msg = new byte [k];				Array.Copy(decrypted, 0, msg, k - decrypted.Length,						   decrypted.Length);				// Acquire a mask generation method, based on SHA-1.				MaskGenerationMethod maskGen = new PKCS1MaskGenerationMethod();				// Extract the non-seed part of the decrypted message.				byte[] maskedMsg = new byte [k - 20 - 1];				Array.Copy(msg, 0, maskedMsg, 0, k - 20 - 1);				// Decrypt the seed value.				byte[] seedMask = maskGen.GenerateMask(maskedMsg, 20);				byte[] seed = new byte [20];				int index;				for(index = 0; index < 20; ++index)				{					seed[index] = (byte)(msg[index + 1] ^ seedMask[index]);				}				// Decrypt the non-seed part of the decrypted message.				byte[] msgMask = maskGen.GenerateMask(seed, maskedMsg.Length);				for(index = 0; index < maskedMsg.Length; ++index)				{					maskedMsg[index] ^= msgMask[index];				}				// Validate the format of the unmasked message.  We do this				// carefully, to prevent attackers from performing timing				// attacks on the algorithm.  See PKCS #1 for details.				int error = msg[0];				for(index = 0; index < 20; ++index)				{					error |= (maskedMsg[index] ^ label[index]);				}				for(index = 20; index < (k - 20 - 2); ++index)				{					// Question: is this careful enough to prevent					// timing attacks?  May need revisiting later.					if(maskedMsg[index] != 0)					{						break;					}				}				error |= (maskedMsg[index] ^ 0x01);				if(error != 0)				{					// Something is wrong with the decrypted padding data.					Array.Clear(decrypted, 0, decrypted.Length);					Array.Clear(msg, 0, msg.Length);					Array.Clear(maskedMsg, 0, maskedMsg.Length);					Array.Clear(seedMask, 0, seedMask.Length);					Array.Clear(seed, 0, seed.Length);					Array.Clear(msgMask, 0, msgMask.Length);					throw new CryptographicException						(_("Crypto_RSAInvalidCiphertext"));				}				++index;				// Extract the final decrypted message.				byte[] finalMsg = new byte [maskedMsg.Length - index];				Array.Copy(maskedMsg, index, finalMsg, 0,						   maskedMsg.Length - index);				// Destroy sensitive values.				Array.Clear(decrypted, 0, decrypted.Length);				Array.Clear(msg, 0, msg.Length);				Array.Clear(maskedMsg, 0, maskedMsg.Length);				Array.Clear(seedMask, 0, seedMask.Length);				Array.Clear(seed, 0, seed.Length);				Array.Clear(msgMask, 0, msgMask.Length);				// Done.				return finalMsg;			}	// Decrypt a value using the RSA private key and PKCS1 decoding.	internal byte[] DecryptPKCS1(byte[] rgb)			{				// Check the data against null.				if(rgb == null)				{					throw new ArgumentNullException("rgb");				}				// Make sure that we have sufficient RSA parameters.				if(rsaParams.Modulus == null)				{					throw new CryptographicException						(_("Crypto_RSAParamsNotSet"));				}				// Check the length of the incoming value.				int k = rsaParams.Modulus.Length;				if(k < 11)				{					throw new CryptographicException						(_("Crypto_RSAKeyTooShort"));				}				// Decrypt the incoming value, and expand to k octets,				// as the big number routines in the engine may have				// stripped leading zeroes from the value.				byte[] decrypted = ApplyPrivate(rgb);				if(decrypted.Length > k)				{					Array.Clear(decrypted, 0, decrypted.Length);					throw new CryptographicException						(_("Crypto_RSAInvalidCiphertext"));				}				byte[] msg = new byte [k];				Array.Copy(decrypted, 0, msg, k - decrypted.Length,						   decrypted.Length);				// Check the format of the padding data.  We need to				// harden this against timing attacks.  It is hard to				// do so since we don't know the expected length of				// the final message.				int error = msg[0] | (msg[1] ^ 0x02);				int index = 2;				while(index < (msg.Length - 1) && msg[index] != 0x00)				{					++index;				}				error |= msg[index];				if(error != 0)				{					Array.Clear(decrypted, 0, decrypted.Length);					Array.Clear(msg, 0, msg.Length);					throw new CryptographicException						(_("Crypto_RSAInvalidCiphertext"));				}				++index;				// Extract the final message.				byte[] finalMsg = new byte [msg.Length - index];				Array.Copy(msg, index, finalMsg, 0, finalMsg.Length);				// Destroy sensitive values.				Array.Clear(decrypted, 0, decrypted.Length);				Array.Clear(msg, 0, msg.Length);				// Done.				return finalMsg;			}	// Decrypt a value using the RSA private key and optional OAEP padding.	public byte[] Decrypt(byte[] rgb, bool fOAEP)			{				if(fOAEP)				{					return DecryptOAEP(rgb);				}				else				{					return DecryptPKCS1(rgb);				}			}	// Decrypt a value using the RSA private key.	public override byte[] DecryptValue(byte[] rgb)			{				return DecryptPKCS1(rgb);			}	// Label value for OAEP encryption.  SHA-1 hash of the empty string.	private static readonly byte[] label =			{(byte)0xDA, (byte)0x39, (byte)0xA3, (byte)0xEE,			 (byte)0x5E, (byte)0x6B, (byte)0x4B, (byte)0x0D,			 (byte)0x32, (byte)0x55, (byte)0xBF, (byte)0xEF,			 (byte)0x95, (byte)0x60, (byte)0x18, (byte)0x90,			 (byte)0xAF, (byte)0xD8, (byte)0x07, (byte)0x09};	// Encrypt a value using a specified OAEP padding array.	// The array may be null to pad with zeroes.	internal byte[] EncryptOAEP(byte[] rgb, byte[] padding,								RandomNumberGenerator rng)			{				// Check the data against null.				if(rgb == null)				{					throw new ArgumentNullException("rgb");				}				// Make sure that we have sufficient RSA parameters.				if(rsaParams.Modulus == null)				{					throw new CryptographicException						(_("Crypto_RSAParamsNotSet"));				}				// Format the label, padding string, and rgb into a message.				int k = rsaParams.Modulus.Length;				if(rgb.Length > (k - 2 * 20 - 2))				{					throw new CryptographicException						(_("Crypto_RSAMessageTooLong"));				}				byte[] msg = new byte [k - 20 - 1];				int posn = 0;				Array.Copy(label, 0, msg, posn, 20);				posn += 20;				int padlen = k - rgb.Length - 2 * 20 - 2;				if(padlen > 0 && padding != null)				{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -