public override DSAParameters ExportParameters(bool includePrivateParameters) { byte[] cspBlob = ExportCspBlob(includePrivateParameters); byte[] cspPublicBlob = null; if (includePrivateParameters) { byte bVersion = CapiHelper.GetKeyBlobHeaderVersion(cspBlob); if (bVersion <= 2) { // Since DSSPUBKEY is used for either public or private key, we got X // but not Y. To get Y, do another export and ask for public key blob. cspPublicBlob = ExportCspBlob(false); } } return(cspBlob.ToDSAParameters(includePrivateParameters, cspPublicBlob)); }
/// <summary> /// Импорт параметров алгоритма ГОСТ Р 34.10-2012 256. /// </summary> /// /// <param name="rawData">Байтовый массив, содержащий ключ и параметры /// алгоритма ГОСТ Р 34.10-2012 256.</param>. /// /// <remarks><para>Импорт секретного ключа не поддерживается. /// </para></remarks> /// /// <exception cref="CryptographicException">При экспорте секретного /// ключа.</exception> public void ImportCspBlob(byte[] rawData) { SafeKeyHandle safeKeyHandle; //Права на экспорт / импорт проверять бесполезно // CSP все равно не поддерживает.Бесполезно да же эмулировать: // сделать с этим BLOB потом ничего нельзя. // Это открытый ключ, поэтому можно его export // в verify context. // Нет обращения к секретному ключу, поэтому // не создаем контейнер без надобности. if (IsPublic(rawData)) { SafeProvHandle safeProvHandleTemp = AcquireSafeProviderHandle(); CapiHelper.ImportKeyBlob( safeProvHandleTemp, CspProviderFlags.NoFlags, false, //? rawData, out safeKeyHandle); // The property set will take care of releasing any already-existing resources. _safeProvHandle = safeProvHandleTemp; } else { throw new CryptographicException(SR.CspParameter_invalid, "Cryptography_UserExportBulkBlob"); } // The property set will take care of releasing any already-existing resources. _safeKeyHandle = safeKeyHandle; if (_parameters != null) { _parameters.KeyNumber = _safeKeyHandle.KeySpec; } // Эмулируем MS HANDLE _publicOnly = true; //throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_CAPI_Required, nameof(CspKeyContainerInfo))); }
/// <summary> /// Retreives the key pair /// </summary> private void GetKeyPair() { if (_safeKeyHandle == null) { lock (this) { if (_safeKeyHandle == null) { // We only attempt to generate a random key on desktop runtimes because the CoreCLR // RSA surface area is limited to simply verifying signatures. Since generating a // random key to verify signatures will always lead to failure (unless we happend to // win the lottery and randomly generate the signing key ...), there is no need // to add this functionality to CoreCLR at this point. CapiHelper.GetKeyPairHelper(CapiHelper.CspAlgorithmType.Rsa, _parameters, _randomKeyContainer, _keySize, ref _safeProvHandle, ref _safeKeyHandle); } } } }
/// <summary> /// Decrypt raw data, generally used for decrypting symmetric key material /// </summary> /// <param name="rgb">encrypted data</param> /// <param name="fOAEP">true to use OAEP padding (PKCS #1 v2), false to use PKCS #1 type 2 padding</param> /// <returns>decrypted data</returns> public byte[] Decrypt(byte[] rgb, bool fOAEP) { if (rgb == null) { throw new ArgumentNullException(nameof(rgb)); } // Save the KeySize value to a local because it has non-trivial cost. int keySize = KeySize; // size check -- must be at most the modulus size if (rgb.Length > (keySize / 8)) { throw new CryptographicException(SR.Format(SR.Cryptography_Padding_DecDataTooBig, Convert.ToString(keySize / 8))); } byte[] decryptedKey; CapiHelper.DecryptKey(SafeKeyHandle, rgb, rgb.Length, fOAEP, out decryptedKey); return(decryptedKey); }
/// <summary> /// Imports a blob that represents DSA key information. /// </summary> /// <param name="keyBlob">A byte array that represents a DSA key blob.</param> public void ImportCspBlob(byte[] keyBlob) { SafeKeyHandle safeKeyHandle; if (IsPublic(keyBlob)) { SafeProvHandle safeProvHandleTemp = AcquireSafeProviderHandle(); CapiHelper.ImportKeyBlob(safeProvHandleTemp, (CspProviderFlags)0, false, keyBlob, out safeKeyHandle); // The property set will take care of releasing any already-existing resources. SafeProvHandle = safeProvHandleTemp; } else { CapiHelper.ImportKeyBlob(SafeProvHandle, _parameters.Flags, false, keyBlob, out safeKeyHandle); } // The property set will take care of releasing any already-existing resources. SafeKeyHandle = safeKeyHandle; }
/// <summary> /// Decrypt raw data, generally used for decrypting symmetric key material /// </summary> /// <param name="rgb">encrypted data</param> /// <param name="fOAEP">true to use OAEP padding (PKCS #1 v2), false to use PKCS #1 type 2 padding</param> /// <returns>decrypted data</returns> public byte[] Decrypt(byte[] rgb, bool fOAEP) { if (rgb == null) { throw new ArgumentNullException(nameof(rgb)); } // Save the KeySize value to a local because it has non-trivial cost. int keySize = KeySize; // size check -- must be exactly the modulus size if (rgb.Length != (keySize / 8)) { throw new CryptographicException(SR.Cryptography_RSA_DecryptWrongSize); } byte[] decryptedKey; CapiHelper.DecryptKey(SafeKeyHandle, rgb, rgb.Length, fOAEP, out decryptedKey); return(decryptedKey); }
/// <summary> /// Encrypt raw data, generally used for encrypting symmetric key material. /// </summary> /// <remarks> /// This method can only encrypt (keySize - 88 bits) of data, so should not be used for encrypting /// arbitrary byte arrays. Instead, encrypt a symmetric key with this method, and use the symmetric /// key to encrypt the sensitive data. /// </remarks> /// <param name="rgb">raw data to encrypt</param> /// <param name="fOAEP">true to use OAEP padding (PKCS #1 v2), false to use PKCS #1 type 2 padding</param> /// <returns>Encrypted key</returns> public byte[] Encrypt(byte[] rgb, bool fOAEP) { ArgumentNullException.ThrowIfNull(rgb); if (fOAEP) { int rsaSize = (KeySize + 7) / 8; const int OaepSha1Overhead = 20 + 20 + 2; // Normalize the Windows 7 and Windows 8.1+ exception if (rsaSize - OaepSha1Overhead < rgb.Length) { const int NTE_BAD_LENGTH = unchecked ((int)0x80090004); throw NTE_BAD_LENGTH.ToCryptographicException(); } } byte[]? encryptedKey = null; CapiHelper.EncryptKey(SafeKeyHandle, rgb, rgb.Length, fOAEP, ref encryptedKey); return(encryptedKey); }
/// <summary> /// Verifies the specified signature data by comparing it to the signature computed for the specified hash value. /// </summary> /// <param name="rgbHash">The hash value of the data to be signed.</param> /// <param name="str">The name of the hash algorithm used to create the hash value of the data.</param> /// <param name="rgbSignature">The signature data to be verified.</param> /// <returns>true if the signature verifies as valid; otherwise, false.</returns> public bool VerifyHash(byte[] rgbHash, string str, byte[] rgbSignature) { if (rgbHash == null) { throw new ArgumentNullException(nameof(rgbHash)); } if (rgbSignature == null) { throw new ArgumentNullException(nameof(rgbSignature)); } int calgHash = CapiHelper.NameOrOidToHashAlgId(str, OidGroup.HashAlgorithm); return(CapiHelper.VerifySign( SafeProvHandle, SafeKeyHandle, CapiHelper.CALG_DSS_SIGN, calgHash, rgbHash, rgbSignature)); }
protected override bool ReleaseHandle() { // Make sure not to delete a key that we want to keep in the key container or an ephemeral key if (!_fPersistKeyInCsp && 0 == (_flags & (uint)CapiHelper.CryptAcquireContextFlags.CRYPT_VERIFYCONTEXT)) { // Delete the key container. uint flags = (_flags & (uint)CapiHelper.CryptAcquireContextFlags.CRYPT_MACHINE_KEYSET) | (uint)CapiHelper.CryptAcquireContextFlags.CRYPT_DELETEKEYSET; SafeProvHandle hIgnoredProv; bool ignoredSuccess = CapiHelper.CryptAcquireContext(out hIgnoredProv, _containerName, _providerName, _type, flags); // Ignoring success result code as CryptAcquireContext is being called to delete a key container rather than acquire a context. // If it fails, we can't do anything about it anyway as we're in a dispose method. } bool successfullyFreed = CapiHelper.CryptReleaseContext(handle, 0); Debug.Assert(successfullyFreed); SetHandle(IntPtr.Zero); return(successfullyFreed); }
/// <summary> /// Импорт параметров <see cref="Gost3410Parameters"/> /// алгоритма ГОСТ Р 34.10-2012 256. /// </summary> /// /// <param name="parameters">Параметры алгоритма /// ГОСТ Р 34.10-2012 256</param> /// /// <doc-sample path="Simple\DocBlock" name="ImportParameters" /// region="ImportParameters" /> /// /// <exception cref="CryptographicException">При импорте секретного /// ключа.</exception> /// /// <remarks> /// <if notdefined="userimp"><para>В данной сборке при импорте /// секретного ключа всегда возбуждает исключение /// <see cref="CryptographicException"/>.</para></if> /// </remarks> /// /// <containerperm flag="Open">Для открытия существующего /// контейнера.</containerperm> /// <containerperm flag="Create">Для создания контейнера с заданным /// (не случайным именем).</containerperm> /// <containerperm flag="Import">Для импорта секретного ключа. /// </containerperm> public override void ImportParameters(Gost3410Parameters parameters) { Gost3410CspObject pubKey = new Gost3410CspObject(parameters); if ((_safeKeyHandle != null) && !_safeKeyHandle.IsClosed) { _safeKeyHandle.Dispose(); } _safeKeyHandle = SafeKeyHandle.InvalidHandle; if (Gost3410_2012_256CryptoServiceProvider.IsPublic(parameters)) { SafeKeyHandle safeKeyHandle; // Это открытый ключ, поэтому можно его export // в verify context. // Нет обращения к секретному ключу, поэтому // не создаем контейнер без надобности. var safeProvHandleTemp = AcquireSafeProviderHandle(); if (pubKey == null) { throw new ArgumentNullException(nameof(pubKey)); } byte[] keyBlob = AsnHelper.EncodePublicBlob(pubKey, CspAlgorithmType.Gost2012_256); CapiHelper.ImportKeyBlob( safeProvHandleTemp, CspProviderFlags.NoFlags, false, keyBlob, out safeKeyHandle); _safeKeyHandle = safeKeyHandle; _publicOnly = true; return; } throw new CryptographicException(SR.CspParameter_invalid, "Cryptography_UserExportBulkBlob"); //throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_CAPI_Required, nameof(CspKeyContainerInfo))); }
/// <summary> /// Read a parameter from the current key using CRYPT_SILENT, to avoid any potential UI prompts. /// </summary> private object?ReadKeyParameterSilent(CapiHelper.ClrPropertyId keyParam, bool throwOnNotFound = true) { const uint SilentFlags = (uint)Interop.Advapi32.CryptAcquireContextFlags.CRYPT_SILENT; SafeProvHandle safeProvHandle; int hr = CapiHelper.OpenCSP(_parameters, SilentFlags, out safeProvHandle); using (safeProvHandle) { if (hr != CapiHelper.S_OK) { if (throwOnNotFound) { throw new CryptographicException(SR.Cryptography_CSP_NotFound); } return(null); } object retVal = CapiHelper.GetProviderParameter(safeProvHandle, _parameters.KeyNumber, keyParam); return(retVal); } }
/// <summary> /// Импортирует (дешифрует) секретный ключ. /// </summary> /// <param name="wrapped">Зашифрованный секретный ключ.</param> /// <param name="method">Алгоритм экспорта ключа.</param> public override SymmetricAlgorithm Unwrap(byte[] wrapped, GostKeyWrapMethod method) { GostWrappedKeyObject gwk = new GostWrappedKeyObject(); gwk.SetByXmlWrappedKey(wrapped); int calg = GostConstants.CALG_SIMPLE_EXPORT; if (method == GostKeyWrapMethod.CryptoProKeyWrap) { calg = GostConstants.CALG_PRO_EXPORT; } else if (method == GostKeyWrapMethod.CryptoPro12KeyWrap) { calg = GostConstants.CALG_PRO12_EXPORT; } else if (method != GostKeyWrapMethod.GostKeyWrap) { throw new ArgumentOutOfRangeException("method"); } SymmetricAlgorithm ret = null; // Сохраняем состояние algid GOST12147 using (SafeKeyHandle hExpKey = CapiHelper.DuplicateKey( SafeKeyHandle.DangerousGetHandle(), SafeProvHandle)) { CapiHelper.SetKeyParamDw(hExpKey, GostConstants.KP_ALGID, calg); SafeKeyHandle simmKey = SafeKeyHandle.InvalidHandle; CapiHelper.AcquireCsp(_parameters, out SafeProvHandle hProv); CapiHelper.ImportSessionWrappedKey( hProv, CspProviderFlags.NoFlags, gwk, hExpKey, ref simmKey); ret = new Gost28147CryptoServiceProvider(simmKey, hProv); } return(ret); }
/// <summary> /// Расшифрование симметричного ключа по /// по <see cref="GostKeyWrapMethod.CryptoProKeyWrap"/>. /// </summary> /// /// <param name="wrapped">Зашифрованный секретный ключ.</param> /// <param name="calgProExport">OID алгоритма экспорта</param> /// <returns>Объект класса <see cref="SymmetricAlgorithm"/>, /// содержащий расшифрованный закрытый ключ.</returns> /// /// <exception cref="CryptographicException">При ошибках /// на managed уровне.</exception> private SymmetricAlgorithm CryptoProUnwrap(byte[] wrapped, int calgProExport) { if (calgProExport != GostConstants.CALG_PRO_EXPORT && calgProExport != GostConstants.CALG_PRO12_EXPORT) { throw new ArgumentOutOfRangeException("calgProExport"); } GostWrappedKeyObject gwk = new GostWrappedKeyObject(); gwk.SetByXmlWrappedKey(wrapped); SafeKeyHandle simmKey = SafeKeyHandle.InvalidHandle; SafeKeyHandle hExpKey = SafeKeyHandle.InvalidHandle; try { CapiHelper.ImportAndMakeSharedSecret(_safeProvHandle, CspProviderFlags.NoFlags, _publicObject, _safeKeyHandle, ref hExpKey, _algType); CapiHelper.SetKeyParamDw(hExpKey, GostConstants.KP_ALGID, calgProExport); CapiHelper.ImportSessionWrappedKey(_safeProvHandle, CspProviderFlags.NoFlags, gwk, hExpKey, ref simmKey); } finally { if (!hExpKey.IsClosed) { hExpKey.Close(); } } return(new Gost28147CryptoServiceProvider(simmKey, _safeProvHandle)); }
/// <summary> /// Computes the signature for the specified hash value by encrypting it with the private key. /// </summary> /// <param name="rgbHash">The hash value of the data to be signed.</param> /// <param name="str">The name of the hash algorithm used to create the hash value of the data.</param> /// <returns>The DSA signature for the specified hash value.</returns> public byte[] SignHash(byte[] rgbHash, string?str) { ArgumentNullException.ThrowIfNull(rgbHash); if (PublicOnly) { throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); } int calgHash = CapiHelper.NameOrOidToHashAlgId(str, OidGroup.HashAlgorithm); if (rgbHash.Length != SHA1.HashSizeInBytes) { throw new CryptographicException(SR.Format(SR.Cryptography_InvalidHashSize, "SHA1", SHA1.HashSizeInBytes)); } return(CapiHelper.SignValue( SafeProvHandle, SafeKeyHandle, _parameters.KeyNumber, CapiHelper.CALG_DSS_SIGN, calgHash, rgbHash)); }
private RSACryptoServiceProvider(int keySize, CspParameters?parameters, bool useDefaultKeySize) { if (keySize < 0) { throw new ArgumentOutOfRangeException("dwKeySize", "ArgumentOutOfRange_NeedNonNegNum"); } _parameters = CapiHelper.SaveCspParameters( CapiHelper.CspAlgorithmType.Rsa, parameters, s_useMachineKeyStore, out _randomKeyContainer); _keySize = useDefaultKeySize ? 1024 : keySize; // If this is not a random container we generate, create it eagerly // in the constructor so we can report any errors now. if (!_randomKeyContainer) { // Force-read the SafeKeyHandle property, which will summon it into existence. SafeCapiKeyHandle localHandle = SafeKeyHandle; Debug.Assert(localHandle != null); } }
private ICryptoTransform CreateTransform(bool encrypting) { // При обращении к KeyHandle возможна генерация ключа. SafeKeyHandle hDupKey = CapiHelper.DuplicateKey( SafeKeyHandle.DangerousGetHandle(), SafeProvHandle); // Добавляем ссылку на провайдер bool success = false; SafeProvHandle.DangerousAddRef(ref success); // При обращении к IV возможна генерация синхропосылки. return(CreateTransformCore( SafeProvHandle, hDupKey, base.ModeValue, base.PaddingValue, IV, base.BlockSizeValue, base.FeedbackSizeValue, encrypting)); }
public void ImportCspBlob(byte[] keyBlob) { RSAParameters parameters = CapiHelper.ToRSAParameters(keyBlob, !IsPublic(keyBlob)); ImportParameters(parameters); }
/// <summary> ///Exports a blob containing the key information associated with an RSACryptoServiceProvider object. /// </summary> public byte[] ExportCspBlob(bool includePrivateParameters) { return(CapiHelper.ExportKeyBlob(includePrivateParameters, SafeKeyHandle)); }
/// <summary> /// Сброс внутреннего состояния <see cref="GostCryptoAPITransform"/> /// в начальное, для проведения другой операции шифрования. /// </summary> /// /// <remarks> /// Метод <c>Reset</c> вызывается автоматически при вызове /// <see cref="TransformFinalBlock"/>. /// Метод <c>Reset</c> не вызывается, когда, например, полученные /// данные не могут быть расшифрованы. В этом случае вызывается /// исключение, а метод <c>Reset</c> необходимо вызвать вручную. /// </remarks> public void Reset() { depadBuffer_ = null; CapiHelper.EndCrypt(safeKeyHandle_, _encrypting); }
/// <summary> /// Вывод диалогового окна выбора контейнера и получение /// имени выбранного контейнера /// </summary> /// /// <param name="fullyQualifiedContainerName">Вернуть полностью /// кваллифицированное имя контейнера.</param> /// <param name="machine">Использовать локальное хранилище /// компьютера (<see langword="true"/>) или пользователя /// (<see langword="true"/>).</param> /// <param name="parent">HWND родительского окна или IntPtr.Zero, /// для выдачи окна без родителя.</param> /// /// <returns>Строку имени контейнера.</returns> public static string SelectContainer(bool fullyQualifiedContainerName, bool machine, IntPtr parent) { return(CapiHelper.SelectContainer(fullyQualifiedContainerName, machine, parent, GostConstants.PROV_GOST_2012_256)); }
/// <summary> /// Шифрование (зашифрование или расшифрование) заключительного /// массива байтов. /// </summary> /// /// <param name="inputBuffer">Входной массив байтов.</param> /// <param name="inputOffset">Смещение от начала входного /// массива.</param> /// <param name="inputCount">Число обрабатываемых байтов входного /// массива.</param> /// /// <returns>Зашифрованный или расшифрованный оконечный /// блок.</returns> /// /// <argnull name="inputBuffer" /> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="inputOffset"/> меньше нуля.</exception> /// <exception cref="ArgumentException"> /// <paramref name="inputCount"/> меньше нуля или /// входной блок выходит за границы массива.</exception> /// <exception cref="CryptographicException">При расшифровании /// в блочном режиме массива байтов с разером не кратным /// размеру блока.</exception> public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) { if (inputBuffer == null) { throw new ArgumentNullException("inputBuffer"); } if (inputOffset < 0) { throw new ArgumentOutOfRangeException("inputOffset", SR.ArgumentOutOfRange_NeedNonNegNum); } if ((inputCount < 0) || (inputCount > inputBuffer.Length)) { throw new ArgumentException( SR.Argument_InvalidValue); } if ((inputBuffer.Length - inputCount) < inputOffset) { throw new ArgumentException(SR.Argument_InvalidValue); } if (_encrypting) { byte[] buffer1 = null; CapiHelper.EncryptDataCp(_safeProvHandle, safeKeyHandle_, inputBuffer, inputOffset, inputCount, ref buffer1, 0, _paddingValue, true, _isStream); Reset(); return(buffer1); } // На поточных алгоритмах не проверяем соответствие длин. if (_isStream) { byte[] buffer2 = null; CapiHelper.DecryptDataCp(safeKeyHandle_, inputBuffer, inputOffset, inputCount, ref buffer2, 0, _paddingValue, true); Reset(); return(buffer2); } if ((inputCount % InputBlockSize) != 0) { throw new CryptographicException(SR.Argument_InvalidValue); } if (depadBuffer_ == null) { byte[] buffer2 = null; CapiHelper.DecryptDataCp(safeKeyHandle_, inputBuffer, inputOffset, inputCount, ref buffer2, 0, _paddingValue, true); Reset(); return(buffer2); } byte[] buffer3 = new byte[depadBuffer_.Length + inputCount]; Array.Copy(depadBuffer_, 0, buffer3, 0, depadBuffer_.Length); Array.Copy(inputBuffer, inputOffset, buffer3, depadBuffer_.Length, inputCount); byte[] buffer4 = null; CapiHelper.DecryptDataCp(safeKeyHandle_, buffer3, 0, buffer3.Length, ref buffer4, 0, _paddingValue, true); Reset(); return(buffer4); }
/// <summary> /// Шифрование (зашифрование или расшифрование) /// заданной области входного массива байтов и в заданную /// область выходного массива байтов. /// </summary> /// /// <param name="inputBuffer">Входной массив байтов.</param> /// <param name="inputOffset">Смещение от начала входного /// массива.</param> /// <param name="inputCount">Число обрабатываемых байтов входного /// массива.</param> /// <param name="outputBuffer">Выходной массив байтов.</param> /// <param name="outputOffset">Смещение от начала выходного /// массива.</param> /// /// <returns>Количество записанных байтов.</returns> /// /// <argnull name="inputBuffer" /> /// <argnull name="outputBuffer" /> /// /// <exception cref="ArgumentException">Длина входного массива меньше /// суммы смещения от его начала и числа обрабатываемых /// байтов.</exception> /// /// <exception cref="ArgumentOutOfRangeException">Если начальное /// смещение отрицательно.</exception> public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { if (inputBuffer == null) { throw new ArgumentNullException("inputBuffer"); } if (outputBuffer == null) { throw new ArgumentNullException("outputBuffer"); } if (inputOffset < 0) { throw new ArgumentOutOfRangeException("inputOffset", SR.ArgumentOutOfRange_NeedNonNegNum); } if (((inputCount <= 0) || ((inputCount % InputBlockSize) != 0)) || (inputCount > inputBuffer.Length)) { throw new ArgumentException(SR.Argument_InvalidValue); } if ((inputBuffer.Length - inputCount) < inputOffset) { throw new ArgumentException(SR.Argument_InvalidValue); } if (_encrypting) { return(CapiHelper.EncryptDataCp(_safeProvHandle, safeKeyHandle_, inputBuffer, inputOffset, inputCount, ref outputBuffer, outputOffset, _paddingValue, false, _isStream)); } if ((_paddingValue == PaddingMode.Zeros) || (_paddingValue == PaddingMode.None)) { return(CapiHelper.DecryptDataCp(safeKeyHandle_, inputBuffer, inputOffset, inputCount, ref outputBuffer, outputOffset, _paddingValue, false)); } if (depadBuffer_ == null) { depadBuffer_ = new byte[InputBlockSize]; int num1 = inputCount - InputBlockSize; Array.Copy(inputBuffer, inputOffset + num1, depadBuffer_, 0, InputBlockSize); return(CapiHelper.DecryptDataCp(safeKeyHandle_, inputBuffer, inputOffset, num1, ref outputBuffer, outputOffset, _paddingValue, false)); } int num2 = CapiHelper.DecryptDataCp(safeKeyHandle_, depadBuffer_, 0, depadBuffer_.Length, ref outputBuffer, outputOffset, _paddingValue, false); outputOffset += OutputBlockSize; int num3 = inputCount - InputBlockSize; Array.Copy(inputBuffer, inputOffset + num3, depadBuffer_, 0, InputBlockSize); num2 = CapiHelper.DecryptDataCp(safeKeyHandle_, inputBuffer, inputOffset, num3, ref outputBuffer, outputOffset, _paddingValue, false); return(OutputBlockSize + num2); }
internal GostCryptoAPITransform( int cArgs, int[] rgArgIds, object[] rgArgValues, SafeKeyHandle hKey, SafeProvHandle hProv, PaddingMode padding, CipherMode cipherChainingMode, int blockSize, bool encrypting) { _blockSizeValue = blockSize; _modeValue = cipherChainingMode; _isStream = _modeValue == CipherMode.OFB || _modeValue == CipherMode.CFB; _paddingValue = padding; this._encrypting = encrypting; int[] numArray1 = new int[rgArgIds.Length]; Array.Copy(rgArgIds, numArray1, rgArgIds.Length); object[] objArray1 = new object[rgArgValues.Length]; for (int num2 = 0; num2 < rgArgValues.Length; num2++) { if (rgArgValues[num2] is byte[]) { byte[] buffer2 = (byte[])rgArgValues[num2]; byte[] buffer3 = new byte[buffer2.Length]; Array.Copy(buffer2, buffer3, buffer2.Length); objArray1[num2] = buffer3; } else if (rgArgValues[num2] is int) { objArray1[num2] = (int)rgArgValues[num2]; } else if (rgArgValues[num2] is CipherMode) { objArray1[num2] = (int)rgArgValues[num2]; } else if (rgArgValues[num2] is PaddingMode) { objArray1[num2] = (int)rgArgValues[num2]; } } safeKeyHandle_ = hKey; _safeProvHandle = hProv; for (int num3 = 0; num3 < cArgs; num3++) { switch (rgArgIds[num3]) { case GostConstants.KP_SV: { _ivValue = (byte[])objArray1[num3]; byte[] buffer1 = _ivValue; CapiHelper.SetKeyParameter(safeKeyHandle_, numArray1[num3], buffer1); break; } case GostConstants.KP_PADDING: { CapiHelper.SetKeyParameter(safeKeyHandle_, numArray1[num3], BitConverter.GetBytes((int)objArray1[num3])); break; } case GostConstants.KP_MODE: { CapiHelper.SetKeyParameter(safeKeyHandle_, numArray1[num3], BitConverter.GetBytes((int)objArray1[num3])); break; } default: { throw new CryptographicException(SR.Argument_InvalidValue); } } } }
public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]?rgbIV) => _impl.CreateDecryptor(rgbKey, CapiHelper.TrimLargeIV(rgbIV, BlockSize));
/// <summary> /// This method helps Acquire the default CSP and avoids the need for static SafeProvHandle /// in CapiHelper class /// </summary> private SafeProvHandle AcquireSafeProviderHandle() { SafeProvHandle safeProvHandle; CapiHelper.AcquireCsp(new CspParameters(CapiHelper.DefaultRsaProviderType), out safeProvHandle); return safeProvHandle; }
/// <summary> /// Verifies the signature of a hash value. /// </summary> private bool VerifyHash(byte[] rgbHash, int calgHash, byte[] rgbSignature) { GetKeyPair(); return(CapiHelper.VerifySign(_safeProvHandle, _safeKeyHandle, CapiHelper.CALG_RSA_SIGN, calgHash, rgbHash, rgbSignature)); }
/// <summary> /// Computes the hash value of a subset of the specified byte array using the specified hash algorithm, and signs the resulting hash value. /// </summary> /// <param name="rgbHash">The input data for which to compute the hash</param> /// <param name="calgHash">The hash algorithm to use to create the hash value. </param> /// <returns>The RSA signature for the specified data.</returns> private byte[] SignHash(byte[] rgbHash, int calgHash) { Debug.Assert(rgbHash != null); GetKeyPair(); return(CapiHelper.SignValue(_safeProvHandle, _safeKeyHandle, _parameters.KeyNumber, CapiHelper.CALG_RSA_SIGN, calgHash, rgbHash)); }
/// <summary> /// This method helps Acquire the default CSP and avoids the need for static SafeProvHandle /// in CapiHelper class /// </summary> /// <param name="safeProvHandle"> SafeProvHandle. Intialized if successful</param> /// <returns>does not return. AcquireCSP throw exception</returns> private void AcquireSafeProviderHandle(ref SafeProvHandle safeProvHandle) { CapiHelper.AcquireCsp(new CspParameters(CapiHelper.DefaultRsaProviderType), ref safeProvHandle); }
private static ICryptoTransform CreateTransformCore( SafeProvHandle hProv, SafeKeyHandle hKey, CipherMode mode, PaddingMode padding, byte[] rgbIV, int blockSize, int feedbackSize, bool encrypting) { //#Q_ ToDo выжечь огнём этот ад с двумя масивами для передачи параметров в GostCryptoAPITransform // переделать на словарь, или в идеале просто явно передавать параметры через структуру, но не этот ужас int num1 = 0; int[] numArray1 = new int[10]; object[] objArray1 = new object[10]; // Не поддерживаем CTS. Выдаем приличное исключение. if (mode == CipherMode.CTS) { throw new ArgumentException( SR.Argument_InvalidValue, nameof(mode)); //SR.Cryptography_CSP_CTSNotSupported } // Поддерживаем только правильные пары Padding - mode if (mode == CipherMode.OFB || mode == CipherMode.CFB) { if (padding != PaddingMode.None) { throw new CryptographicException( SR.Cryptography_InvalidPaddingMode); } } // Сбрасываем Pading, мы сами его поддерживаем. numArray1[num1] = GostConstants.KP_PADDING; objArray1[num1] = GostConstants.WINCRYPT_PADDING_ZERO; num1++; // Поддерживаем только CFB с feedback по ГОСТ. if ((mode == CipherMode.CFB) && (feedbackSize != DefFeedbackSize)) { throw new ArgumentException(SR.Argument_InvalidValue, nameof(feedbackSize)); } // Нет ключа, генерим. if (hKey == null) { CapiHelper.GenerateKey(hProv, GostConstants.CALG_G28147, CspProviderFlags.NoFlags, GostConstants.G28147_KEYLEN * BitsPerByte, out hKey); } // Ключ приходит как Handle, поэтому длины не проверяем. // Mode ставим всегда, так как при создании ключа по Handle // он может быть другим. numArray1[num1] = GostConstants.KP_MODE; objArray1[num1] = mode; num1++; // Для всех mode кроме ECB требуется синхропосылка. Устанавливаем. if (mode != CipherMode.ECB) { // Если ее нет, то генерим. if (rgbIV == null) { if (!encrypting) { // при расшифровании IV должен быть задан throw new CryptographicException(SR.Cryptography_MissingIV); } // Не используем GenerateIV: классовая и переданная // IV могут отличаться. rgbIV = new byte[IVSize / 8]; using (var rng = new GostRngCryptoServiceProvider(hProv)) { rng.GetBytes(rgbIV); } } // проверяем достаточность по длине. if (rgbIV.Length < IVSize / BitsPerByte) { throw new CryptographicException( SR.Cryptography_InvalidIVSize); } numArray1[num1] = GostConstants.KP_SV; objArray1[num1] = rgbIV; num1++; } // Можно еще установить для CFB количество бит зацепления, но // оно всегда равно 64 и его установка не поддерживается CSP. return(new GostCryptoAPITransform(num1, numArray1, objArray1, hKey, hProv, padding, mode, blockSize, encrypting)); }