Code:
/ FXUpdate3074 / FXUpdate3074 / 1.1 / untmp / whidbey / QFE / ndp / clr / src / BCL / System / Security / Cryptography / RSACryptoServiceProvider.cs / 3 / RSACryptoServiceProvider.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== // // RSACryptoServiceProvider.cs // // CSP-based implementation of RSA // namespace System.Security.Cryptography { using System; using System.IO; using System.Security.Cryptography.X509Certificates; using System.Security.Permissions; using System.Globalization; // Object layout of the RSAParameters structure internal class RSACspObject { internal byte[] Exponent; internal byte[] Modulus; internal byte[] P; internal byte[] Q; internal byte[] DP; internal byte[] DQ; internal byte[] InverseQ; internal byte[] D; } [System.Runtime.InteropServices.ComVisible(true)] public sealed class RSACryptoServiceProvider : RSA, ICspAsymmetricAlgorithm { private int _dwKeySize; private CspParameters _parameters; private bool _randomKeyContainer; private SafeProvHandle _safeProvHandle; private SafeKeyHandle _safeKeyHandle; private static CspProviderFlags s_UseMachineKeyStore = 0; // // public constructors // public RSACryptoServiceProvider() : this(0, new CspParameters(Utils.DefaultRsaProviderType, null, null, s_UseMachineKeyStore), true) { } public RSACryptoServiceProvider(int dwKeySize) : this(dwKeySize, new CspParameters(Utils.DefaultRsaProviderType, null, null, s_UseMachineKeyStore), false) { } public RSACryptoServiceProvider(CspParameters parameters) : this(0, parameters, true) { } public RSACryptoServiceProvider(int dwKeySize, CspParameters parameters) : this(dwKeySize, parameters, false) { } // // private methods // private const uint RandomKeyContainerFlag = 0x80000000; private RSACryptoServiceProvider(int dwKeySize, CspParameters parameters, bool useDefaultKeySize) { if (dwKeySize < 0) throw new ArgumentOutOfRangeException("dwKeySize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); // see if the random key container flag was set, and clear the bit since CAPI will not understand it bool externallyGeneratedRandomKeyContainer = (((uint)parameters.Flags) & RandomKeyContainerFlag) != 0; parameters.Flags = (CspProviderFlags)(((uint)parameters.Flags) & (~RandomKeyContainerFlag)); _parameters = Utils.SaveCspParameters(CspAlgorithmType.Rsa, parameters, s_UseMachineKeyStore, ref _randomKeyContainer); if (_parameters.KeyNumber == Constants.AT_SIGNATURE || Utils.HasEnhProv == 1) { LegalKeySizesValue = new KeySizes[] { new KeySizes(384, 16384, 8) }; if (useDefaultKeySize) _dwKeySize = 1024; } else { // All we have is the base provider LegalKeySizesValue = new KeySizes[] { new KeySizes(384, 512, 8) }; if (useDefaultKeySize) _dwKeySize = 512; } if (!useDefaultKeySize) _dwKeySize = dwKeySize; // If this is not a random container we generate, create it eagerly // in the constructor so we can report any errors now. if (!_randomKeyContainer || Environment.GetCompatibilityFlag(CompatibilityFlag.EagerlyGenerateRandomAsymmKeys)) GetKeyPair(); // if the random key container flag was set, set the random flag so that KeyContainerPermission // demands are bypassed _randomKeyContainer |= externallyGeneratedRandomKeyContainer; return; } private void GetKeyPair () { if (_safeKeyHandle == null) { lock (this) { if (_safeKeyHandle == null) Utils.GetKeyPairHelper(CspAlgorithmType.Rsa, _parameters, _randomKeyContainer, _dwKeySize, ref _safeProvHandle, ref _safeKeyHandle); } } } protected override void Dispose(bool disposing) { if (_safeKeyHandle != null && !_safeKeyHandle.IsClosed) _safeKeyHandle.Dispose(); if (_safeProvHandle != null && !_safeProvHandle.IsClosed) _safeProvHandle.Dispose(); } // // public properties // [System.Runtime.InteropServices.ComVisible(false)] public bool PublicOnly { get { GetKeyPair(); byte[] publicKey = (byte[]) Utils._GetKeyParameter(_safeKeyHandle, Constants.CLR_PUBLICKEYONLY); return (publicKey[0] == 1); } } [System.Runtime.InteropServices.ComVisible(false)] public CspKeyContainerInfo CspKeyContainerInfo { get { GetKeyPair(); return new CspKeyContainerInfo(_parameters, _randomKeyContainer); } } public override int KeySize { get { GetKeyPair(); byte[] keySize = (byte[]) Utils._GetKeyParameter(_safeKeyHandle, Constants.CLR_KEYLEN); _dwKeySize = (keySize[0] | (keySize[1] << 8) | (keySize[2] << 16) | (keySize[3] << 24)); return _dwKeySize; } } public override string KeyExchangeAlgorithm { get { if (_parameters.KeyNumber == Constants.AT_KEYEXCHANGE) return "RSA-PKCS1-KeyEx"; return null; } } public override string SignatureAlgorithm { get { return "http://www.w3.org/2000/09/xmldsig#rsa-sha1"; } } public static bool UseMachineKeyStore { get { return (s_UseMachineKeyStore == CspProviderFlags.UseMachineKeyStore); } set { s_UseMachineKeyStore = (value ? CspProviderFlags.UseMachineKeyStore : 0); } } public bool PersistKeyInCsp { get { if (_safeProvHandle == null) { lock (this) { if (_safeProvHandle == null) _safeProvHandle = Utils.CreateProvHandle(_parameters, _randomKeyContainer); } } return Utils._GetPersistKeyInCsp(_safeProvHandle); } set { bool oldPersistKeyInCsp = this.PersistKeyInCsp; if (value == oldPersistKeyInCsp) return; KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags); if (!value) { KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(_parameters, KeyContainerPermissionFlags.Delete); kp.AccessEntries.Add(entry); } else { KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(_parameters, KeyContainerPermissionFlags.Create); kp.AccessEntries.Add(entry); } kp.Demand(); Utils._SetPersistKeyInCsp(_safeProvHandle, value); } } // // public methods // public override RSAParameters ExportParameters (bool includePrivateParameters) { GetKeyPair(); if (includePrivateParameters) { KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags); KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(_parameters, KeyContainerPermissionFlags.Export); kp.AccessEntries.Add(entry); kp.Demand(); } RSACspObject rsaCspObject = new RSACspObject(); int blobType = includePrivateParameters ? Constants.PRIVATEKEYBLOB : Constants.PUBLICKEYBLOB; // _ExportKey will Utils._ExportKey(_safeKeyHandle, blobType, rsaCspObject); return RSAObjectToStruct(rsaCspObject); } [System.Runtime.InteropServices.ComVisible(false)] public byte[] ExportCspBlob (bool includePrivateParameters) { GetKeyPair(); return Utils.ExportCspBlobHelper(includePrivateParameters, _parameters, _safeKeyHandle); } public override void ImportParameters(RSAParameters parameters) { RSACspObject rsaCspObject = RSAStructToObject(parameters); // Free the current key handle if (_safeKeyHandle != null && !_safeKeyHandle.IsClosed) _safeKeyHandle.Dispose(); _safeKeyHandle = SafeKeyHandle.InvalidHandle; if (IsPublic(parameters)) { // Use our CRYPT_VERIFYCONTEXT handle, CRYPT_EXPORTABLE is not applicable to public only keys, so pass false Utils._ImportKey(Utils.StaticProvHandle, Constants.CALG_RSA_KEYX, (CspProviderFlags) 0, rsaCspObject, ref _safeKeyHandle); } else { KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags); KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(_parameters, KeyContainerPermissionFlags.Import); kp.AccessEntries.Add(entry); kp.Demand(); if (_safeProvHandle == null) _safeProvHandle = Utils.CreateProvHandle(_parameters, _randomKeyContainer); // Now, import the key into the CSP; _ImportKey will Utils._ImportKey(_safeProvHandle, Constants.CALG_RSA_KEYX, _parameters.Flags, rsaCspObject, ref _safeKeyHandle); } } [System.Runtime.InteropServices.ComVisible(false)] public void ImportCspBlob (byte[] keyBlob) { Utils.ImportCspBlobHelper(CspAlgorithmType.Rsa, keyBlob, IsPublic(keyBlob), ref _parameters, _randomKeyContainer, ref _safeProvHandle, ref _safeKeyHandle); } public byte[] SignData(Stream inputStream, Object halg) { string oid = Utils.ObjToOidValue(halg); HashAlgorithm hash = Utils.ObjToHashAlgorithm(halg); byte[] hashVal = hash.ComputeHash(inputStream); return SignHash(hashVal, oid); } public byte[] SignData(byte[] buffer, Object halg) { string oid = Utils.ObjToOidValue(halg); HashAlgorithm hash = Utils.ObjToHashAlgorithm(halg); byte[] hashVal = hash.ComputeHash(buffer); return SignHash(hashVal, oid); } public byte[] SignData(byte[] buffer, int offset, int count, Object halg) { string oid = Utils.ObjToOidValue(halg); HashAlgorithm hash = Utils.ObjToHashAlgorithm(halg); byte[] hashVal = hash.ComputeHash(buffer, offset, count); return SignHash(hashVal, oid); } public bool VerifyData(byte[] buffer, Object halg, byte[] signature) { string oid = Utils.ObjToOidValue(halg); HashAlgorithm hash = Utils.ObjToHashAlgorithm(halg); byte[] hashVal = hash.ComputeHash(buffer); return VerifyHash(hashVal, oid, signature); } public byte[] SignHash(byte[] rgbHash, string str) { if (rgbHash == null) throw new ArgumentNullException("rgbHash"); if (PublicOnly) throw new CryptographicException(Environment.GetResourceString("Cryptography_CSP_NoPrivateKey")); int calgHash = X509Utils.OidToAlgId(str); GetKeyPair(); if (!_randomKeyContainer) { KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags); KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(_parameters, KeyContainerPermissionFlags.Sign); kp.AccessEntries.Add(entry); kp.Demand(); } return Utils._SignValue(_safeKeyHandle, _parameters.KeyNumber, Constants.CALG_RSA_SIGN, calgHash, rgbHash, 0); } public bool VerifyHash(byte[] rgbHash, string str, byte[] rgbSignature) { if (rgbHash == null) throw new ArgumentNullException("rgbHash"); if (rgbSignature == null) throw new ArgumentNullException("rgbSignature"); int calgHash = X509Utils.OidToAlgId(str); GetKeyPair(); return Utils._VerifySign(_safeKeyHandle, Constants.CALG_RSA_SIGN, calgHash, rgbHash, rgbSignature, 0); } // // if fOAEP is true, PKCS#1 v2.0 (OAEP) padding is used for both encryption and decryption, // otherwise PKCS#1 v1.5 padding is used. In both cases, we will first try to use symmetric // key import/export through the exponent-of-one trick. If this fails, we will try to use direct // encryption and decryption (only available in Win2K platforms and above). This is to make // sure key transport of symmetric keys always works regardless of which CSP is used or installed. // public byte[] Encrypt(byte[] rgb, bool fOAEP) { if (rgb == null) throw new ArgumentNullException("rgb"); GetKeyPair(); byte[] result = null; int hr = Constants.S_OK; if (fOAEP) { // this is only available if we have the enhanced provider AND we're on Win2K if (Utils.HasEnhProv != 1 || Utils.Win2KCrypto != 1) throw new CryptographicException(Environment.GetResourceString("Cryptography_Padding_Win2KEnhOnly")); result = Utils._EncryptPKWin2KEnh(_safeKeyHandle, rgb, true, out hr); // true means use CRYPT_OAEP flag if (hr != Constants.S_OK) throw new CryptographicException(hr); } else { // Use PKCS1 v1 type 2 padding here result = Utils._EncryptPKWin2KEnh(_safeKeyHandle, rgb, false, out hr); if (hr != Constants.S_OK) result = Utils._EncryptKey(_safeKeyHandle, rgb); } return result; } public byte [] Decrypt(byte[] rgb, bool fOAEP) { if (rgb == null) throw new ArgumentNullException("rgb"); GetKeyPair(); // size if (rgb.Length > (KeySize / 8)) throw new CryptographicException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Cryptography_Padding_DecDataTooBig"), KeySize / 8)); if (!_randomKeyContainer) { KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags); KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(_parameters, KeyContainerPermissionFlags.Decrypt); kp.AccessEntries.Add(entry); kp.Demand(); } byte[] result = null; int hr = Constants.S_OK; if (fOAEP) { // this is only available if we have the enhanced provider AND we're on Win2K if (Utils.HasEnhProv != 1 || Utils.Win2KCrypto != 1) throw new CryptographicException(Environment.GetResourceString("Cryptography_Padding_Win2KEnhOnly")); result = Utils._DecryptPKWin2KEnh(_safeKeyHandle, rgb, true, out hr); if (hr != Constants.S_OK) throw new CryptographicException(hr); } else { // Use PKCS1 v1 type 2 padding here result = Utils._DecryptPKWin2KEnh(_safeKeyHandle, rgb, false, out hr); if (hr != Constants.S_OK) result = Utils._DecryptKey(_safeKeyHandle, rgb, 0); } return result; } public override byte[] DecryptValue(byte[] rgb) { throw new NotSupportedException(Environment.GetResourceString("NotSupported_Method")); } public override byte[] EncryptValue(byte[] rgb) { throw new NotSupportedException(Environment.GetResourceString("NotSupported_Method")); } // // private static methods // private static RSAParameters RSAObjectToStruct (RSACspObject rsaCspObject) { RSAParameters rsaParams = new RSAParameters(); rsaParams.Exponent = rsaCspObject.Exponent; rsaParams.Modulus = rsaCspObject.Modulus; rsaParams.P = rsaCspObject.P; rsaParams.Q = rsaCspObject.Q; rsaParams.DP = rsaCspObject.DP; rsaParams.DQ = rsaCspObject.DQ; rsaParams.InverseQ = rsaCspObject.InverseQ; rsaParams.D = rsaCspObject.D; return rsaParams; } private static RSACspObject RSAStructToObject (RSAParameters rsaParams) { RSACspObject rsaCspObject = new RSACspObject(); rsaCspObject.Exponent = rsaParams.Exponent; rsaCspObject.Modulus = rsaParams.Modulus; rsaCspObject.P = rsaParams.P; rsaCspObject.Q = rsaParams.Q; rsaCspObject.DP = rsaParams.DP; rsaCspObject.DQ = rsaParams.DQ; rsaCspObject.InverseQ = rsaParams.InverseQ; rsaCspObject.D = rsaParams.D; return rsaCspObject; } // Since P is required, we will assume its presence is synonymous to a private key. private static bool IsPublic (RSAParameters rsaParams) { return (rsaParams.P == null); } // find whether an RSA key blob is public. private static bool IsPublic (byte[] keyBlob) { if (keyBlob == null) throw new ArgumentNullException("keyBlob"); // The CAPI RSA public key representation consists of the following sequence: // - BLOBHEADER // - RSAPUBKEY // The first should be PUBLICKEYBLOB and magic should be RSA_PUB_MAGIC "RSA1" if (keyBlob[0] != Constants.PUBLICKEYBLOB) return false; if (keyBlob[11] != 0x31 || keyBlob[10] != 0x41 || keyBlob[9] != 0x53 || keyBlob[8] != 0x52) return false; return true; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- MarkupCompiler.cs
- TaiwanCalendar.cs
- Configuration.cs
- WebPartVerb.cs
- HtmlObjectListAdapter.cs
- DesignOnlyAttribute.cs
- AccessedThroughPropertyAttribute.cs
- _HeaderInfoTable.cs
- AsyncInvokeContext.cs
- AmbiguousMatchException.cs
- SHA1Managed.cs
- PriorityItem.cs
- DropDownList.cs
- _SecureChannel.cs
- ValidatedControlConverter.cs
- AdornerDecorator.cs
- VScrollProperties.cs
- DataGridState.cs
- ServicesExceptionNotHandledEventArgs.cs
- ToolCreatedEventArgs.cs
- SpeechUI.cs
- ProfileGroupSettings.cs
- ViewBox.cs
- FileUtil.cs
- ObjectDataSourceEventArgs.cs
- ZipIOCentralDirectoryFileHeader.cs
- TdsParserStaticMethods.cs
- Roles.cs
- GotoExpression.cs
- CollectionChangedEventManager.cs
- followingquery.cs
- WebPartExportVerb.cs
- ListDictionaryInternal.cs
- DbMetaDataColumnNames.cs
- SerializationUtility.cs
- ObjectQuery.cs
- TextEffect.cs
- ExtractedStateEntry.cs
- ContentIterators.cs
- InheritedPropertyChangedEventArgs.cs
- EntityDataSourceWrapperCollection.cs
- Int64KeyFrameCollection.cs
- AliasGenerator.cs
- HebrewNumber.cs
- ContainerFilterService.cs
- ClientSession.cs
- ArgIterator.cs
- ExpressionParser.cs
- Color.cs
- RotateTransform3D.cs
- DynamicControl.cs
- XPathSingletonIterator.cs
- CodeDelegateCreateExpression.cs
- ProtocolsSection.cs
- TabItem.cs
- FunctionDescription.cs
- TriggerCollection.cs
- IssuanceLicense.cs
- UnmanagedBitmapWrapper.cs
- LinearGradientBrush.cs
- BufferedStream.cs
- DBBindings.cs
- StrokeSerializer.cs
- KnownTypeAttribute.cs
- FunctionNode.cs
- WMICapabilities.cs
- PointAnimationClockResource.cs
- NavigationEventArgs.cs
- WorkflowOperationContext.cs
- CustomAssemblyResolver.cs
- IntegerValidatorAttribute.cs
- ObjectContext.cs
- AutomationIdentifier.cs
- VariantWrapper.cs
- BCLDebug.cs
- X509CertificateRecipientClientCredential.cs
- CodeDOMUtility.cs
- SourceSwitch.cs
- DataControlCommands.cs
- DataGridPagerStyle.cs
- NumberSubstitution.cs
- Queue.cs
- DrawingContextDrawingContextWalker.cs
- ISFTagAndGuidCache.cs
- prefixendpointaddressmessagefilter.cs
- FlowLayout.cs
- InteropBitmapSource.cs
- SystemBrushes.cs
- SqlStatistics.cs
- PropertyCondition.cs
- AutomationEventArgs.cs
- TextEditorTyping.cs
- safelinkcollection.cs
- GridSplitter.cs
- ImageCodecInfo.cs
- EntityContainerRelationshipSetEnd.cs
- DateBoldEvent.cs
- CodeBlockBuilder.cs
- XmlSchemaParticle.cs
- DecoderFallback.cs