Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / clr / src / BCL / System / Security / Cryptography / RSACryptoServiceProvider.cs / 1 / 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 check for failures and throw an exception 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 check for failures. 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 check -- must be at most the modulus 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. // // ==--== // // 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 check for failures and throw an exception 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 check for failures. 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 check -- must be at most the modulus 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.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- FileVersionInfo.cs
- PersonalizableTypeEntry.cs
- ProtectedConfiguration.cs
- MatrixIndependentAnimationStorage.cs
- AutoGeneratedFieldProperties.cs
- ThreadStartException.cs
- _AuthenticationState.cs
- CellTreeSimplifier.cs
- CompilerWrapper.cs
- ClientUrlResolverWrapper.cs
- DurationConverter.cs
- CapabilitiesPattern.cs
- UITypeEditors.cs
- RoutingSection.cs
- PathNode.cs
- TextPointerBase.cs
- QilDataSource.cs
- SelectedCellsCollection.cs
- ReversePositionQuery.cs
- ParagraphVisual.cs
- PrintingPermission.cs
- ServiceControllerDesigner.cs
- InputProviderSite.cs
- HttpProfileGroupBase.cs
- OutOfMemoryException.cs
- HtmlTernaryTree.cs
- XmlCustomFormatter.cs
- WebPartMenu.cs
- ProjectionPath.cs
- ObjectQueryProvider.cs
- TrailingSpaceComparer.cs
- ValueUtilsSmi.cs
- SizeValueSerializer.cs
- HtmlHead.cs
- FunctionNode.cs
- EmptyQuery.cs
- WindowsClaimSet.cs
- CatalogPart.cs
- DataKeyCollection.cs
- SettingsPropertyValue.cs
- DesignerVerb.cs
- InputLanguageManager.cs
- GlobalEventManager.cs
- DoubleCollectionConverter.cs
- TextureBrush.cs
- XmlSchemaAny.cs
- ChunkedMemoryStream.cs
- InlineObject.cs
- VisualTransition.cs
- NameNode.cs
- Freezable.cs
- SqlProviderUtilities.cs
- RemoteWebConfigurationHostStream.cs
- RSAPKCS1KeyExchangeDeformatter.cs
- HttpAsyncResult.cs
- ReliableSessionBindingElementImporter.cs
- PresentationTraceSources.cs
- CheckBoxFlatAdapter.cs
- AppSettingsExpressionEditor.cs
- Knowncolors.cs
- SafeCoTaskMem.cs
- WindowsFormsSynchronizationContext.cs
- LiteralControl.cs
- SecurityChannelListener.cs
- CountdownEvent.cs
- ReferenceEqualityComparer.cs
- NumberFormatter.cs
- panel.cs
- EntitySqlException.cs
- CaseInsensitiveComparer.cs
- PropertyDescriptorGridEntry.cs
- ActivityCodeDomSerializer.cs
- QuadraticEase.cs
- PeerContact.cs
- SingleObjectCollection.cs
- QueryHandler.cs
- CompilerErrorCollection.cs
- ExtensibleClassFactory.cs
- SurrogateEncoder.cs
- DataExpression.cs
- XmlTextReaderImpl.cs
- XmlLangPropertyAttribute.cs
- WeakHashtable.cs
- DelayLoadType.cs
- ExecutorLocksHeldException.cs
- GeometryValueSerializer.cs
- CallbackHandler.cs
- CodeCompileUnit.cs
- ArrayTypeMismatchException.cs
- ApplicationDirectory.cs
- WorkflowOperationBehavior.cs
- EntityViewGenerationConstants.cs
- BindingsCollection.cs
- BitmapEffectGroup.cs
- XpsStructure.cs
- CachedCompositeFamily.cs
- RealizationContext.cs
- EDesignUtil.cs
- UpdateCommandGenerator.cs
- ErrorProvider.cs