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
- WebServiceHostFactory.cs
- NonBatchDirectoryCompiler.cs
- GlobalAclOperationRequirement.cs
- _BasicClient.cs
- SecurityState.cs
- _LazyAsyncResult.cs
- VirtualDirectoryMapping.cs
- ExtensionWindowResizeGrip.cs
- XamlGridLengthSerializer.cs
- ToolStripSystemRenderer.cs
- Int16AnimationBase.cs
- SrgsText.cs
- VirtualStackFrame.cs
- ClonableStack.cs
- DockPatternIdentifiers.cs
- KnownBoxes.cs
- ConnectionString.cs
- CodeMemberField.cs
- FieldAccessException.cs
- TextUtf8RawTextWriter.cs
- QilCloneVisitor.cs
- PackagePart.cs
- HtmlInputPassword.cs
- DynamicILGenerator.cs
- ImageMetadata.cs
- DeriveBytes.cs
- RefreshEventArgs.cs
- XmlComment.cs
- ModifierKeysValueSerializer.cs
- ProcessInputEventArgs.cs
- PersonalizationProvider.cs
- DataGridViewImageCell.cs
- RuleSettingsCollection.cs
- SQLString.cs
- WindowsHyperlink.cs
- SystemDiagnosticsSection.cs
- ConnectionProviderAttribute.cs
- AdapterDictionary.cs
- DispatchChannelSink.cs
- PointLightBase.cs
- GridViewHeaderRowPresenterAutomationPeer.cs
- WebBrowser.cs
- HtmlInputFile.cs
- GenericsNotImplementedException.cs
- ListDictionaryInternal.cs
- bindurihelper.cs
- CustomSignedXml.cs
- KeySpline.cs
- ConnectionPointCookie.cs
- XmlDataCollection.cs
- SmiXetterAccessMap.cs
- OracleInternalConnection.cs
- CancellationHandler.cs
- ClientScriptManager.cs
- DeadCharTextComposition.cs
- SystemResourceKey.cs
- CodeNamespaceImportCollection.cs
- BooleanToVisibilityConverter.cs
- ActivityInstance.cs
- MetadataArtifactLoaderCompositeResource.cs
- UrlPropertyAttribute.cs
- FixedFlowMap.cs
- StubHelpers.cs
- TrackingServices.cs
- Win32MouseDevice.cs
- TranslateTransform3D.cs
- UriExt.cs
- DiscoveryDocumentLinksPattern.cs
- AdjustableArrowCap.cs
- PeerPresenceInfo.cs
- ConfigXmlSignificantWhitespace.cs
- OleDbEnumerator.cs
- FixedSOMElement.cs
- TaiwanLunisolarCalendar.cs
- WindowsListViewGroup.cs
- Win32PrintDialog.cs
- Animatable.cs
- PageFunction.cs
- MouseCaptureWithinProperty.cs
- IndentedWriter.cs
- Cursors.cs
- AutoSizeToolBoxItem.cs
- XPathDocumentNavigator.cs
- EntityDataSourceColumn.cs
- CompilerInfo.cs
- StorageFunctionMapping.cs
- CornerRadiusConverter.cs
- Convert.cs
- PropertyStore.cs
- VectorCollectionValueSerializer.cs
- XmlSchemaCollection.cs
- DriveInfo.cs
- ResourceAttributes.cs
- Camera.cs
- SkewTransform.cs
- Win32.cs
- LoginUtil.cs
- NextPreviousPagerField.cs
- TdsParserHelperClasses.cs
- EventNotify.cs