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));
        }
Пример #2
0
        /// <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);
             }
         }
     }
 }
Пример #4
0
        /// <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));
        }
Пример #9
0
        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);
        }
Пример #10
0
        /// <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)));
        }
Пример #11
0
        /// <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);
            }
        }
Пример #12
0
        /// <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);
        }
Пример #13
0
        /// <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));
        }
Пример #14
0
        /// <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));
        }
Пример #15
0
        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);
            }
        }
Пример #16
0
        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));
        }
Пример #17
0
 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));
 }
Пример #19
0
 /// <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);
 }
Пример #20
0
 /// <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));
 }
Пример #21
0
        /// <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);
        }
Пример #22
0
        /// <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);
        }
Пример #23
0
        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);
                }
                }
            }
        }
Пример #24
0
 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);
 }
Пример #29
0
        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));
        }