public override byte[] ComputeHash(HashAlgorithm hash)
        {
            SafeHashHandleImpl hashHandle;

            if (hash is Gost3411HashAlgorithm)
            {
                hashHandle = ((Gost3411HashAlgorithm)hash).InternalHashHandle;
            }
            else if (hash is Gost3411Hmac)
            {
                hashHandle = ((Gost3411Hmac)hash).InternalHashHandle;
            }
            else if (hash is Gost28147ImitHashAlgorithm)
            {
                hashHandle = ((Gost28147ImitHashAlgorithm)hash).InternalHashHandle;
            }
            else if (hash is Gost3411_2012_256HashAlgorithm)
            {
                hashHandle = ((Gost3411_2012_256HashAlgorithm)hash).InternalHashHandle;
            }
            else if (hash is Gost3411_2012_512HashAlgorithm)
            {
                hashHandle = ((Gost3411_2012_512HashAlgorithm)hash).InternalHashHandle;
            }
            else
            {
                throw ExceptionUtility.Argument("hash", Resources.RequiredGostHash);
            }

            CryptoApiHelper.HashKeyExchange(hashHandle, InternalKeyHandle);

            return(CryptoApiHelper.EndHashData(hashHandle));
        }
Ejemplo n.º 2
0
        private static void ValidateProviderParameters(CspProviderFlags flags)
        {
            // Ели информацию о провайдере нужно взять из текущего ключа
            if ((flags & CspProviderFlags.UseExistingKey) != CspProviderFlags.NoFlags)
            {
                const CspProviderFlags notExpectedFlags = CspProviderFlags.UseUserProtectedKey
                                                          | CspProviderFlags.UseArchivableKey
                                                          | CspProviderFlags.UseNonExportableKey;

                if ((flags & notExpectedFlags) != CspProviderFlags.NoFlags)
                {
                    throw ExceptionUtility.Argument("flags", Resources.InvalidCspProviderFlags);
                }
            }

            // Если пользователь должен сам выбрать ключ (например, в диалоге)
            if ((flags & CspProviderFlags.UseUserProtectedKey) != CspProviderFlags.NoFlags)
            {
                if (!Environment.UserInteractive)
                {
                    throw ExceptionUtility.CryptographicException(Resources.UserInteractiveNotSupported);
                }

                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
            }
        }
Ejemplo n.º 3
0
        private static string GetHashAlgorithmOid(object hashAlg)
        {
            string hashAlgOid = null;

            if (hashAlg is string)
            {
                hashAlgOid = GostCryptoConfig.MapNameToOID((string)hashAlg);

                if (string.IsNullOrEmpty(hashAlgOid))
                {
                    hashAlgOid = (string)hashAlg;
                }
            }
            else if (hashAlg is HashAlgorithm)
            {
                hashAlgOid = GostCryptoConfig.MapNameToOID(hashAlg.GetType().ToString());
            }
            else if (hashAlg is Type)
            {
                hashAlgOid = GostCryptoConfig.MapNameToOID(hashAlg.ToString());
            }

            if (string.IsNullOrEmpty(hashAlgOid))
            {
                throw ExceptionUtility.Argument("hashAlg", Resources.InvalidHashAlgorithm);
            }

            return(hashAlgOid);
        }
Ejemplo n.º 4
0
        public static byte[] DecodeBase64Array(byte[] srcArray)
        {
            var num = srcArray.Length / 4;

            if ((4 * num) != srcArray.Length)
            {
                throw ExceptionUtility.Argument("srcArray", Resources.Asn1InvalidEncodedDataLength);
            }

            var num2 = 0;
            var num3 = num;

            if (srcArray.Length != 0)
            {
                if (srcArray[srcArray.Length - 1] == 0x3d)
                {
                    num2++;
                    num3--;
                }
                if (srcArray[srcArray.Length - 2] == 0x3d)
                {
                    num2++;
                }
            }

            var buffer = new byte[(3 * num) - num2];
            var num4   = 0;
            var num5   = 0;

            for (var i = 0; i < num3; i++)
            {
                var num7  = DecodeBase64Char(srcArray[num4++]);
                var num8  = DecodeBase64Char(srcArray[num4++]);
                var num9  = DecodeBase64Char(srcArray[num4++]);
                var num10 = DecodeBase64Char(srcArray[num4++]);

                buffer[num5++] = (byte)((num7 << 2) | (num8 >> 4));
                buffer[num5++] = (byte)((num8 << 4) | (num9 >> 2));
                buffer[num5++] = (byte)((num9 << 6) | num10);
            }

            if (num2 != 0)
            {
                var num11 = DecodeBase64Char(srcArray[num4++]);
                var num12 = DecodeBase64Char(srcArray[num4++]);

                buffer[num5++] = (byte)((num11 << 2) | (num12 >> 4));

                if (num2 == 1)
                {
                    var num13 = DecodeBase64Char(srcArray[num4++]);
                    buffer[num5++] = (byte)((num12 << 4) | (num13 >> 2));
                }
            }

            return(buffer);
        }
        internal Gost28147SymmetricAlgorithm(SafeProvHandleImpl provHandle, SafeKeyHandleImpl keyHandle) : this()
        {
            _provHandle = provHandle.DangerousAddRef();
            _keyHandle  = CryptoApiHelper.DuplicateKey(keyHandle);

            if (CryptoApiHelper.GetKeyParameterInt32(_keyHandle, Constants.KP_ALGID) != Constants.CALG_G28147)
            {
                throw ExceptionUtility.Argument("keyHandle", Resources.RequiredGost28147);
            }
        }
        public Gost28147SymmetricAlgorithm(IntPtr provHandle, IntPtr keyHandle) : this()
        {
            _provHandle = new SafeProvHandleImpl(provHandle, true);
            _keyHandle  = CryptoApiHelper.DuplicateKey(keyHandle);

            if (CryptoApiHelper.GetKeyParameterInt32(_keyHandle, Constants.KP_ALGID) != Constants.CALG_G28147)
            {
                throw ExceptionUtility.Argument("keyHandle", Resources.RequiredGost28147);
            }
        }
        internal Gost_28147_89_SymmetricAlgorithm(ProviderType providerType, SafeProvHandleImpl providerHandle, SafeKeyHandleImpl keyHandle) : base(providerType)
        {
            InitDefaults();
            _providerHandle = providerHandle.DangerousAddRef();
            _keyHandle      = CryptoApiHelper.DuplicateKey(keyHandle);

            if (CryptoApiHelper.GetKeyParameterInt32(_keyHandle, Constants.KP_ALGID) != Constants.CALG_G28147)
            {
                throw ExceptionUtility.Argument(nameof(keyHandle), Resources.RequiredGost28147);
            }
        }
Ejemplo n.º 8
0
        private static int DecodeBase64Char(byte c)
        {
            var num = (c < 0x80) ? Base64DecodeTable[c - 40] : -1;

            if (num < 0)
            {
                throw ExceptionUtility.Argument("c", Resources.Asn1IllegalCharacter, c);
            }

            return(num);
        }
        public override byte[] ComputeHash(HashAlgorithm hash)
        {
            if (!(hash is ISafeHandleProvider <SafeHashHandleImpl> hashHadnleProvider))
            {
                throw ExceptionUtility.Argument(nameof(hash), Resources.RequiredGostHash);
            }

            var hashHandle = hashHadnleProvider.SafeHandle;

            CryptoApiHelper.HashKeyExchange(hashHandle, this.GetSafeHandle());

            return(CryptoApiHelper.EndHashData(hashHandle));
        }
Ejemplo n.º 10
0
        private static HashAlgorithm CreateHashAlgorithm(object hashAlg)
        {
            if (hashAlg == null)
            {
                throw ExceptionUtility.ArgumentNull("hashAlg");
            }

            if (!GetHashAlgorithmOid(hashAlg).Equals(Constants.OID_GR3411_12_512, StringComparison.OrdinalIgnoreCase))
            {
                throw ExceptionUtility.Argument("hashAlg", Resources.RequiredGost3411);
            }

            HashAlgorithm hashAlgorithm = null;

            if (_objToHashAlgorithmMethod == null)
            {
                lock (ObjToHashAlgorithmMethodSync)
                {
                    if (_objToHashAlgorithmMethod == null)
                    {
                        var utilsType = Type.GetType("System.Security.Cryptography.Utils");

                        if (utilsType != null)
                        {
                            _objToHashAlgorithmMethod = utilsType.GetMethod("ObjToHashAlgorithm", BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(object) }, null);
                        }
                    }
                }
            }

            if (_objToHashAlgorithmMethod != null)
            {
                try
                {
                    hashAlgorithm = _objToHashAlgorithmMethod.Invoke(null, new[] { hashAlg }) as HashAlgorithm;
                }
                catch (TargetInvocationException exception)
                {
                    if (exception.InnerException != null)
                    {
                        throw exception.InnerException;
                    }

                    throw;
                }
            }

            return(hashAlgorithm);
        }
Ejemplo n.º 11
0
        public GostExternalAsymmetricAlgorithm(AsymmetricAlgorithm algorithm) : base(default(ProviderType), algorithm.KeySize)
        {
            var createSignatureMethod = algorithm.GetType().GetMethod(nameof(CreateSignature), new[] { typeof(byte[]) });
            var verifySignatureMethod = algorithm.GetType().GetMethod(nameof(VerifySignature), new[] { typeof(byte[]), typeof(byte[]) });

            if ((createSignatureMethod == null || createSignatureMethod.ReturnType != typeof(byte[])) ||
                (verifySignatureMethod == null || verifySignatureMethod.ReturnType != typeof(bool)))
            {
                throw ExceptionUtility.Argument(nameof(algorithm), Resources.ShouldSupportGost3410);
            }

            _algorithm       = algorithm;
            _createSignature = hash => (byte[])createSignatureMethod.Invoke(algorithm, new object[] { hash });
            _verifySignature = (hash, signature) => (bool)verifySignatureMethod.Invoke(algorithm, new object[] { hash, signature });
        }
Ejemplo n.º 12
0
        public override byte[] EncodeKeyExchange(SymmetricAlgorithm keyExchangeAlgorithm, GostKeyExchangeExportMethod keyExchangeExportMethod)
        {
            if (keyExchangeAlgorithm is Gost28147SymmetricAlgorithm)
            {
                return(EncodeKeyExchangeInternal((Gost28147SymmetricAlgorithm)keyExchangeAlgorithm, keyExchangeExportMethod));
            }

            if (keyExchangeAlgorithm is Gost28147SymmetricAlgorithmBase)
            {
                using (var gostKeyExchangeAlgorithm = new Gost28147SymmetricAlgorithm())
                {
                    return(gostKeyExchangeAlgorithm.EncodePrivateKey((Gost28147SymmetricAlgorithmBase)keyExchangeAlgorithm, keyExchangeExportMethod));
                }
            }

            throw ExceptionUtility.Argument("keyExchangeAlgorithm", Resources.RequiredGost28147);
        }
        public override byte[] EncodeKeyExchange(SymmetricAlgorithm keyExchangeAlgorithm, GostKeyExchangeExportMethod keyExchangeExportMethod)
        {
            if (keyExchangeAlgorithm is Gost_28147_89_SymmetricAlgorithm symAlg)
            {
                return(EncodeKeyExchangeInternal(symAlg, keyExchangeExportMethod));
            }

            if (keyExchangeAlgorithm is Gost_28147_89_SymmetricAlgorithmBase symAlgBase)
            {
                using (var gostKeyExchangeAlgorithm = new Gost_28147_89_SymmetricAlgorithm(symAlgBase.ProviderType))
                {
                    return(gostKeyExchangeAlgorithm.EncodePrivateKey(symAlgBase, keyExchangeExportMethod));
                }
            }

            throw ExceptionUtility.Argument(nameof(keyExchangeAlgorithm), Resources.RequiredGost28147);
        }
Ejemplo n.º 14
0
        public void ImportCspBlob(byte[] importedKeyBytes)
        {
            if (importedKeyBytes == null)
            {
                throw ExceptionUtility.ArgumentNull("importedKeyBytes");
            }

            if (!IsPublicKeyBlob(importedKeyBytes))
            {
                throw ExceptionUtility.Argument("importedKeyBytes", Resources.UserImportBulkBlob);
            }

            _keyHandleFunc = () =>
            {
                SafeKeyHandleImpl hKey;
                _providerParameters.KeyNumber = CryptoApiHelper.ImportCspBlob(importedKeyBytes, _providerHandle, SafeKeyHandleImpl.InvalidHandle, out hKey);
                return(hKey);
            };
        }
        public static Gost_28147_89_SymmetricAlgorithm CreateFromSessionKey(ProviderType providerType, byte[] sessionKey)
        {
            if (sessionKey == null)
            {
                throw ExceptionUtility.ArgumentNull(nameof(sessionKey));
            }

            if (sessionKey.Length != 32)
            {
                throw ExceptionUtility.Argument(nameof(sessionKey), Resources.InvalidHashSize, 32);
            }

            var providerHandle        = CryptoApiHelper.GetProviderHandle(providerType);
            var randomNumberGenerator = CryptoApiHelper.GetRandomNumberGenerator(providerType);

            using (var keyHandle = CryptoApiHelper.ImportBulkSessionKey(providerType, providerHandle, sessionKey, randomNumberGenerator))
            {
                return(new Gost_28147_89_SymmetricAlgorithm(providerType, providerHandle, keyHandle));
            }
        }
Ejemplo n.º 16
0
        public Gost3411Prf(byte[] key, byte[] label, byte[] seed) : this(label, seed)
        {
            if (key == null)
            {
                throw ExceptionUtility.ArgumentNull("key");
            }

            if (key.Length != 32)
            {
                throw ExceptionUtility.Argument("key", Resources.InvalidHashSize);
            }

            _hashHmacHandle = SafeHashHandleImpl.InvalidHandle;
            _buffer         = new byte[_labelAndSeed.Length + 32];

            using (var keyHandle = CryptoApiHelper.ImportBulkSessionKey(CryptoApiHelper.ProviderHandle, key, CryptoApiHelper.RandomNumberGenerator))
            {
                _key = new Gost28147SymmetricAlgorithm(CryptoApiHelper.ProviderHandle, keyHandle);
            }
        }
Ejemplo n.º 17
0
        public void ImportCspBlob(byte[] importedKeyBytes)
        {
            if (importedKeyBytes == null)
            {
                throw ExceptionUtility.ArgumentNull(nameof(importedKeyBytes));
            }

            if (!IsPublicKeyBlob(importedKeyBytes))
            {
                throw ExceptionUtility.Argument(nameof(importedKeyBytes), Resources.UserImportBulkBlob);
            }

            var hProv = CryptoApiHelper.GetProviderHandle(ProviderType);

            _providerParameters.KeyNumber = CryptoApiHelper.ImportCspBlob(importedKeyBytes, hProv, SafeKeyHandleImpl.InvalidHandle, out var hKey);
            _providerHandle = hProv;
            _keyHandle      = hKey;

            _isPublicKeyOnly = true;
        }
Ejemplo n.º 18
0
        public static int DecryptData(SafeKeyHandleImpl symKeyHandle, byte[] data, int dataOffset, int dataLength, ref byte[] decryptedData, int decryptedDataOffset, PaddingMode paddingMode, bool isDone)
        {
            if (dataOffset < 0)
            {
                throw ExceptionUtility.ArgumentOutOfRange(nameof(dataOffset));
            }

            if (dataLength < 0)
            {
                throw ExceptionUtility.ArgumentOutOfRange(nameof(dataLength));
            }

            if ((dataOffset > data.Length) || ((dataOffset + dataLength) > data.Length))
            {
                throw ExceptionUtility.ArgumentOutOfRange(nameof(dataOffset), Resources.InvalidDataOffset);
            }

            // Выровненные данные
            var dataAlignLength = (uint)dataLength;
            var dataAlign       = new byte[dataAlignLength];

            Array.Copy(data, dataOffset, dataAlign, 0L, dataAlignLength);

            // Расшифровка данных
            if (!CryptoApi.CryptDecrypt(symKeyHandle, SafeHashHandleImpl.InvalidHandle, false, 0, dataAlign, ref dataAlignLength))
            {
                throw CreateWin32Error();
            }

            var length = (int)dataAlignLength;

            if (isDone)
            {
                byte dataPaddingSize = 0;

                // Удаление дополнения данных в зависимости от настроек
                if (((paddingMode == PaddingMode.PKCS7) || (paddingMode == PaddingMode.ANSIX923)) || (paddingMode == PaddingMode.ISO10126))
                {
                    if (dataAlignLength < 8)
                    {
                        throw ExceptionUtility.CryptographicException(Constants.NTE_BAD_DATA);
                    }

                    // Размер дополнения находится в последнем байте
                    dataPaddingSize = dataAlign[(int)((IntPtr)(dataAlignLength - 1))];

                    if (dataPaddingSize > 8)
                    {
                        throw ExceptionUtility.CryptographicException(Constants.NTE_BAD_DATA);
                    }

                    // Проверка корректности дополнения данных
                    if (paddingMode == PaddingMode.PKCS7)
                    {
                        for (var paddingIndex = dataAlignLength - dataPaddingSize; paddingIndex < (dataAlignLength - 1); paddingIndex++)
                        {
                            if (dataAlign[paddingIndex] != dataPaddingSize)
                            {
                                throw ExceptionUtility.CryptographicException(Constants.NTE_BAD_DATA);
                            }
                        }
                    }
                    else if (paddingMode == PaddingMode.ANSIX923)
                    {
                        for (var paddingIndex = dataAlignLength - dataPaddingSize; paddingIndex < (dataAlignLength - 1); paddingIndex++)
                        {
                            if (dataAlign[paddingIndex] != 0)
                            {
                                throw ExceptionUtility.CryptographicException(Constants.NTE_BAD_DATA);
                            }
                        }
                    }
                }
                else if ((paddingMode != PaddingMode.None) && (paddingMode != PaddingMode.Zeros))
                {
                    throw ExceptionUtility.Argument(nameof(paddingMode), Resources.InvalidPaddingMode);
                }

                length -= dataPaddingSize;
            }

            if (decryptedData == null)
            {
                decryptedData = new byte[length];

                Array.Copy(dataAlign, 0, decryptedData, 0, length);
            }
            else
            {
                if (decryptedDataOffset < 0)
                {
                    throw ExceptionUtility.ArgumentOutOfRange(nameof(decryptedDataOffset));
                }

                if ((decryptedData.Length < length) || ((decryptedData.Length - length) < decryptedDataOffset))
                {
                    throw ExceptionUtility.ArgumentOutOfRange(nameof(decryptedData), Resources.InvalidDataOffset);
                }

                Array.Copy(dataAlign, 0, decryptedData, decryptedDataOffset, length);
            }

            return(length);
        }
Ejemplo n.º 19
0
        public static int EncryptData(ProviderType providerType, SafeKeyHandleImpl symKeyHandle, byte[] data, int dataOffset, int dataLength, ref byte[] encryptedData, int encryptedDataOffset, PaddingMode paddingMode, bool isDone, bool isStream)
        {
            if (dataOffset < 0)
            {
                throw ExceptionUtility.ArgumentOutOfRange(nameof(dataOffset));
            }

            if (dataLength < 0)
            {
                throw ExceptionUtility.ArgumentOutOfRange(nameof(dataLength));
            }

            if (dataOffset > data.Length)
            {
                throw ExceptionUtility.ArgumentOutOfRange(nameof(dataOffset), Resources.InvalidDataOffset);
            }

            var length = dataLength;

            if (isDone)
            {
                length += 8;
            }

            // Выровненные данные
            var dataAlignLength = (uint)dataLength;
            var dataAlignArray  = new byte[length];

            Array.Clear(dataAlignArray, 0, length);
            Array.Copy(data, dataOffset, dataAlignArray, 0, dataLength);

            if (isDone)
            {
                var dataPadding     = dataLength & 7;
                var dataPaddingSize = (byte)(8 - dataPadding);

                // Добпаление дополнения данных в зависимости от настроек
                switch (paddingMode)
                {
                case PaddingMode.None:
                    if ((dataPadding != 0) && !isStream)
                    {
                        throw ExceptionUtility.CryptographicException(Resources.EncryptInvalidDataSize);
                    }

                    break;

                case PaddingMode.Zeros:
                    if (dataPadding != 0)
                    {
                        dataAlignLength += dataPaddingSize;

                        // Дополнение заполняется нулевыми байтами
                    }

                    break;

                case PaddingMode.PKCS7:
                {
                    dataAlignLength += dataPaddingSize;

                    var paddingIndex = dataLength;

                    // Дополнение заполняется байтами, в каждый из которых записывается размер дополнения
                    while (paddingIndex < dataAlignLength)
                    {
                        dataAlignArray[paddingIndex++] = dataPaddingSize;
                    }
                }
                break;

                case PaddingMode.ANSIX923:
                {
                    dataAlignLength += dataPaddingSize;

                    // Дополнение заполняется нулевыми, кроме последнего - в него записывается размер дополнения
                    dataAlignArray[(int)((IntPtr)(dataAlignLength - 1))] = dataPaddingSize;
                }
                break;

                case PaddingMode.ISO10126:
                {
                    dataAlignLength += dataPaddingSize;

                    // Дополнение заполняется случайными байтами, кроме последнего - в него записывается размер дополнения
                    var randomPadding = new byte[dataPaddingSize - 1];
                    GetRandomNumberGenerator(providerType).GetBytes(randomPadding);
                    randomPadding.CopyTo(dataAlignArray, dataLength);
                    dataAlignArray[(int)((IntPtr)(dataAlignLength - 1))] = dataPaddingSize;
                }
                break;

                default:
                    throw ExceptionUtility.Argument(nameof(paddingMode), Resources.InvalidPaddingMode);
                }
            }

            // Шифрование данных
            if (!CryptoApi.CryptEncrypt(symKeyHandle, SafeHashHandleImpl.InvalidHandle, false, 0, dataAlignArray, ref dataAlignLength, (uint)length))
            {
                throw CreateWin32Error();
            }

            // Копирование результата шифрования данных

            if (encryptedData == null)
            {
                encryptedData = new byte[dataAlignLength];

                Array.Copy(dataAlignArray, 0L, encryptedData, 0L, dataAlignLength);
            }
            else
            {
                if (encryptedDataOffset < 0)
                {
                    throw ExceptionUtility.ArgumentOutOfRange(nameof(encryptedDataOffset));
                }

                if ((encryptedData.Length < dataAlignLength) || ((encryptedData.Length - dataAlignLength) < encryptedDataOffset))
                {
                    throw ExceptionUtility.ArgumentOutOfRange(nameof(encryptedDataOffset), Resources.InvalidDataOffset);
                }

                Array.Copy(dataAlignArray, 0L, encryptedData, encryptedDataOffset, dataAlignLength);
            }

            return((int)dataAlignLength);
        }
        public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
        {
            if (inputBuffer == null)
            {
                throw ExceptionUtility.ArgumentNull(nameof(inputBuffer));
            }

            if (outputBuffer == null)
            {
                throw ExceptionUtility.ArgumentNull(nameof(outputBuffer));
            }

            if (inputOffset < 0)
            {
                throw ExceptionUtility.ArgumentOutOfRange(nameof(inputOffset));
            }

            if ((inputCount <= 0) || ((inputCount % InputBlockSize) != 0) || (inputCount > inputBuffer.Length))
            {
                throw ExceptionUtility.Argument(nameof(inputOffset), Resources.InvalidDataOffset);
            }

            if ((inputBuffer.Length - inputCount) < inputOffset)
            {
                throw ExceptionUtility.Argument(nameof(inputOffset), Resources.InvalidDataOffset);
            }

            if (_transformMode == Gost_28147_89_CryptoTransformMode.Encrypt)
            {
                return(CryptoApiHelper.EncryptData(_providerType, _keyHandle, inputBuffer, inputOffset, inputCount, ref outputBuffer, outputOffset, _paddingValue, false, _isStreamModeValue));
            }

            if ((_paddingValue == PaddingMode.Zeros) || (_paddingValue == PaddingMode.None))
            {
                return(CryptoApiHelper.DecryptData(_keyHandle, inputBuffer, inputOffset, inputCount, ref outputBuffer, outputOffset, _paddingValue, false));
            }

            int dectyptDataLength;

            if (_dataBuffer == null)
            {
                _dataBuffer = new byte[InputBlockSize];

                var length = inputCount - InputBlockSize;
                Array.Copy(inputBuffer, inputOffset + length, _dataBuffer, 0, InputBlockSize);

                dectyptDataLength = CryptoApiHelper.DecryptData(_keyHandle, inputBuffer, inputOffset, length, ref outputBuffer, outputOffset, _paddingValue, false);
            }
            else
            {
                CryptoApiHelper.DecryptData(_keyHandle, _dataBuffer, 0, _dataBuffer.Length, ref outputBuffer, outputOffset, _paddingValue, false);

                outputOffset += OutputBlockSize;

                var length = inputCount - InputBlockSize;
                Array.Copy(inputBuffer, inputOffset + length, _dataBuffer, 0, InputBlockSize);

                dectyptDataLength = OutputBlockSize + CryptoApiHelper.DecryptData(_keyHandle, inputBuffer, inputOffset, length, ref outputBuffer, outputOffset, _paddingValue, false);
            }

            return(dectyptDataLength);
        }