Example #1
0
        public static byte[] GetKeyParameter(SafeKeyHandleImpl keyHandle, uint keyParamId)
        {
            uint dataLength = 0;

            if (!CryptoApi.CryptGetKeyParam(keyHandle, keyParamId, null, ref dataLength, 0))
            {
                throw CreateWin32Error();
            }

            var dataBytes = new byte[dataLength];

            if (!CryptoApi.CryptGetKeyParam(keyHandle, keyParamId, dataBytes, ref dataLength, 0))
            {
                throw CreateWin32Error();
            }

            return(dataBytes);
        }
Example #2
0
        private static SafeHashHandleImpl CreateHashHMAC(SafeProvHandleImpl providerHandle, SafeKeyHandleImpl symKeyHandle, int hmacAlgId)
        {
            var hashHmacHandle = SafeHashHandleImpl.InvalidHandle;

            if (!CryptoApi.CryptCreateHash(providerHandle, (uint)hmacAlgId, symKeyHandle, 0, ref hashHmacHandle))
            {
                var errorCode = Marshal.GetLastWin32Error();

                if (errorCode == Constants.NTE_BAD_ALGID)
                {
                    throw ExceptionUtility.CryptographicException(Resources.AlgorithmNotAvailable);
                }

                throw ExceptionUtility.CryptographicException(errorCode);
            }

            return(hashHmacHandle);
        }
Example #3
0
        public static byte[] EndHashData(SafeHashHandleImpl hashHandle)
        {
            uint dataLength = 0;

            if (!CryptoApi.CryptGetHashParam(hashHandle, Constants.HP_HASHVAL, null, ref dataLength, 0))
            {
                throw CreateWin32Error();
            }

            var data = new byte[dataLength];

            if (!CryptoApi.CryptGetHashParam(hashHandle, Constants.HP_HASHVAL, data, ref dataLength, 0))
            {
                throw CreateWin32Error();
            }

            return(data);
        }
Example #4
0
        public static SafeProvHandleImpl AcquireProvider(CspParameters providerParameters)
        {
            var providerHandle = SafeProvHandleImpl.InvalidHandle;

            var dwFlags = Constants.CRYPT_VERIFYCONTEXT;

            if ((providerParameters.Flags & CspProviderFlags.UseMachineKeyStore) != CspProviderFlags.NoFlags)
            {
                dwFlags |= Constants.CRYPT_MACHINE_KEYSET;
            }

            if (!CryptoApi.CryptAcquireContext(ref providerHandle, providerParameters.KeyContainerName, providerParameters.ProviderName, (uint)providerParameters.ProviderType, dwFlags))
            {
                throw CreateWin32Error();
            }

            return(providerHandle);
        }
Example #5
0
        public static int GetKeyParameterInt32(SafeKeyHandleImpl keyHandle, uint keyParamId)
        {
            const int doubleWordSize = 4;

            uint dwDataLength = doubleWordSize;
            var  dwDataBytes  = new byte[doubleWordSize];

            if (!CryptoApi.CryptGetKeyParam(keyHandle, keyParamId, dwDataBytes, ref dwDataLength, 0))
            {
                throw CreateWin32Error();
            }

            if (dwDataLength != doubleWordSize)
            {
                throw ExceptionUtility.CryptographicException(Constants.NTE_BAD_DATA);
            }

            return(BitConverter.ToInt32(dwDataBytes, 0));
        }
Example #6
0
        private static void SetHashValue(SafeHashHandleImpl hashHandle, byte[] hashValue)
        {
            uint hashLength = 0;

            if (!CryptoApi.CryptGetHashParam(hashHandle, Constants.HP_HASHVAL, null, ref hashLength, 0))
            {
                throw CreateWin32Error();
            }

            if (hashValue.Length != hashLength)
            {
                throw ExceptionUtility.CryptographicException(Constants.NTE_BAD_HASH);
            }

            if (!CryptoApi.CryptSetHashParam(hashHandle, Constants.HP_HASHVAL, hashValue, 0))
            {
                throw CreateWin32Error();
            }
        }
Example #7
0
        public static SafeKeyHandleImpl GenerateDhEphemeralKey(ProviderType providerType, SafeProvHandleImpl providerHandle, int algId, string digestParamSet, string publicKeyParamSet)
        {
            var keyHandle = SafeKeyHandleImpl.InvalidHandle;
            var dwFlags   = MapCspKeyFlags(CspProviderFlags.NoFlags) | Constants.CRYPT_PREGEN;

            if (!CryptoApi.CryptGenKey(providerHandle, (uint)algId, dwFlags, ref keyHandle))
            {
                throw CreateWin32Error();
            }

            if (!providerType.IsVipNet())
            {
                SetKeyParameterString(keyHandle, Constants.KP_HASHOID, digestParamSet);
            }

            SetKeyParameterString(keyHandle, Constants.KP_DHOID, publicKeyParamSet);
            SetKeyParameter(keyHandle, Constants.KP_X, null);

            return(keyHandle);
        }
Example #8
0
        public static SafeHashHandleImpl CreateHashHmac(SafeProvHandleImpl providerHandle, SafeKeyHandleImpl symKeyHandle)
        {
            var hashHmacHandle = SafeHashHandleImpl.InvalidHandle;

            var hmacAlgId = (GostCryptoConfig.ProviderType == ProviderTypes.VipNet) ? Constants.CALG_GR3411_HMAC34 : Constants.CALG_GR3411_HMAC;

            if (!CryptoApi.CryptCreateHash(providerHandle, (uint)hmacAlgId, symKeyHandle, 0, ref hashHmacHandle))
            {
                var errorCode = Marshal.GetLastWin32Error();

                if (errorCode == Constants.NTE_BAD_ALGID)
                {
                    throw ExceptionUtility.CryptographicException(Resources.AlgorithmNotAvailable);
                }

                throw ExceptionUtility.CryptographicException(errorCode);
            }

            return(hashHmacHandle);
        }
Example #9
0
        public static void EndCrypt(SafeKeyHandleImpl symKeyHandle, Gost28147CryptoTransformMode transformMode)
        {
            bool success;
            uint dataLength = 0;

            if (transformMode == Gost28147CryptoTransformMode.Encrypt)
            {
                var data = new byte[32];
                success = CryptoApi.CryptEncrypt(symKeyHandle, SafeHashHandleImpl.InvalidHandle, true, 0, data, ref dataLength, (uint)data.Length);
            }
            else
            {
                var data = new byte[0];
                success = CryptoApi.CryptDecrypt(symKeyHandle, SafeHashHandleImpl.InvalidHandle, true, 0, data, ref dataLength) || (GostCryptoConfig.ProviderType == ProviderTypes.VipNet);
            }

            if (!success)
            {
                throw CreateWin32Error();
            }
        }
Example #10
0
        public static int OpenProvider(CspParameters providerParameters, ref SafeProvHandleImpl hProv)
        {
            uint dwFlags = MapCspProviderFlags(providerParameters.Flags);

            if (!CryptoApi.CryptAcquireContext(ref hProv, providerParameters.KeyContainerName, providerParameters.ProviderName, (uint)providerParameters.ProviderType, dwFlags))
            {
                return(Marshal.GetLastWin32Error());
            }
            return(0);


            //var providerHandle = SafeProvHandleImpl.InvalidHandle;
            //var dwFlags = MapCspProviderFlags(providerParameters.Flags);

            //if (!CryptoApi.CryptAcquireContext(ref providerHandle, providerParameters.KeyContainerName, providerParameters.ProviderName, (uint)providerParameters.ProviderType, dwFlags))
            //{
            //             throw CreateWin32Error();
            //}

            //return providerHandle;
        }
Example #11
0
        public static byte[] SignValue(SafeProvHandleImpl providerHandle, SafeHashHandleImpl hashHandle, int keyNumber, byte[] hashValue)
        {
            SetHashValue(hashHandle, hashValue);

            uint signatureLength = 0;

            // Вычисление размера подписи
            if (!CryptoApi.CryptSignHash(hashHandle, (uint)keyNumber, null, 0, null, ref signatureLength))
            {
                throw CreateWin32Error();
            }

            var signatureValue = new byte[signatureLength];

            // Вычисление значения подписи
            if (!CryptoApi.CryptSignHash(hashHandle, (uint)keyNumber, null, 0, signatureValue, ref signatureLength))
            {
                throw CreateWin32Error();
            }

            return(signatureValue);
        }
Example #12
0
        public static byte[] SignValue(SafeProvHandleImpl hProv, int keyNumber, byte[] hashValue)
        {
            using (var hashHandle = SetupHashAlgorithm(hProv, hashValue))
            {
                uint signatureLength = 0;

                // Вычисление размера подписи
                if (!CryptoApi.CryptSignHash(hashHandle, (uint)keyNumber, null, 0, null, ref signatureLength))
                {
                    throw CreateWin32Error();
                }

                var signatureValue = new byte[signatureLength];

                // Вычисление значения подписи
                if (!CryptoApi.CryptSignHash(hashHandle, (uint)keyNumber, null, 0, signatureValue, ref signatureLength))
                {
                    throw CreateWin32Error();
                }

                return(signatureValue);
            }
        }
Example #13
0
        public static byte[] SignValue(SafeProvHandleImpl hProv, int keyNumber, byte[] hashValue, GostAlgorithmType alg)
        {
            using (var hashHandle = SetupHashAlgorithm(hProv, hashValue, alg))
            {
                int signatureLength = 0;

                // Вычисление размера подписи
                if (!CryptoApi.CryptSignHash(hashHandle, (int)keyNumber, null, 0, null, ref signatureLength))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                var signatureValue = new byte[signatureLength];

                // Вычисление значения подписи
                if (!CryptoApi.CryptSignHash(hashHandle, (int)keyNumber, null, 0, signatureValue, ref signatureLength))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                return(signatureValue);
            }
        }
Example #14
0
        private static SafeHashHandleImpl SetupHashAlgorithm(SafeProvHandleImpl providerHandle, byte[] hashValue)
        {
            var hashHandle = CreateHash_3411_94(providerHandle);

            uint hashLength = 0;

            if (!CryptoApi.CryptGetHashParam(hashHandle, Constants.HP_HASHVAL, null, ref hashLength, 0))
            {
                throw CreateWin32Error();
            }

            if (hashValue.Length != hashLength)
            {
                throw ExceptionUtility.CryptographicException(Constants.NTE_BAD_HASH);
            }

            if (!CryptoApi.CryptSetHashParam(hashHandle, Constants.HP_HASHVAL, hashValue, 0))
            {
                throw CreateWin32Error();
            }

            return(hashHandle);
        }
Example #15
0
        /// <summary>
        /// Возвращает сертификат X.509 для указанного ключа.
        /// </summary>
        /// <param name="keyHandle">Дескриптор ключа сертификата.</param>
        public static X509Certificate2 GetKeyCertificate(SafeKeyHandleImpl keyHandle)
        {
            uint certDataLength = 0;

            if (!CryptoApi.CryptGetKeyParam(keyHandle, Constants.KP_CERTIFICATE, null, ref certDataLength, 0))
            {
                if (Marshal.GetLastWin32Error() != Constants.ERROR_NO_SUCH_CERTIFICATE)
                {
                    throw CreateWin32Error();
                }

                return(null);
            }

            var certData = new byte[certDataLength];

            if (!CryptoApi.CryptGetKeyParam(keyHandle, Constants.KP_CERTIFICATE, certData, ref certDataLength, 0))
            {
                throw CreateWin32Error();
            }

            return(new X509Certificate2(certData));
        }
Example #16
0
        public static void SetProviderParameter(SafeProvHandleImpl providerHandle, int keyNumber, uint keyParamId, IntPtr keyParamValue)
        {
            if ((keyParamId == Constants.PP_KEYEXCHANGE_PIN) || (keyParamId == Constants.PP_SIGNATURE_PIN))
            {
                if (keyNumber == Constants.AT_KEYEXCHANGE)
                {
                    keyParamId = Constants.PP_KEYEXCHANGE_PIN;
                }
                else if (keyNumber == Constants.AT_SIGNATURE)
                {
                    keyParamId = Constants.PP_SIGNATURE_PIN;
                }
                else
                {
                    throw ExceptionUtility.NotSupported(Resources.KeyAlgorithmNotSupported);
                }
            }

            if (!CryptoApi.CryptSetProvParam(providerHandle, keyParamId, keyParamValue, 0))
            {
                throw CreateWin32Error();
            }
        }
Example #17
0
        private static SafeHashHandleImpl SetupHashAlgorithm(SafeProvHandleImpl providerHandle, byte[] hashValue, GostAlgorithmType alg)
        {
            SafeHashHandleImpl hashHandle;

            if (alg == GostAlgorithmType.Gost2012_256)
            {
                hashHandle = CreateHash_3411_2012_256(providerHandle);
            }
            else if (alg == GostAlgorithmType.Gost2012_512)
            {
                hashHandle = CreateHash_3411_2012_512(providerHandle);
            }
            else
            {
                hashHandle = CreateHash_3411_94(providerHandle);
            }

            //uint hashLength = 0;

            //if (!CryptoApi.CryptGetHashParam(hashHandle, Constants.HP_HASHVAL, null, ref hashLength, 0))
            //{
            //	throw CreateWin32Error();
            //}

            //if (hashValue.Length != hashLength)
            //{
            //	throw ExceptionUtility.CryptographicException(Constants.NTE_BAD_HASH);
            //}

            if (!CryptoApi.CryptSetHashParam(hashHandle, Constants.HP_HASHVAL, hashValue, 0))
            {
                throw CreateWin32Error();
            }

            return(hashHandle);
        }
Example #18
0
 protected override bool ReleaseHandle()
 {
     CryptoApi.CryptDestroyHash(handle);
     return(true);
 }
Example #19
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);
        }
Example #20
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);
        }
Example #21
0
        public static SafeKeyHandleImpl ImportBulkSessionKey(ProviderType providerType, SafeProvHandleImpl providerHandle, byte[] bulkSessionKey, RNGCryptoServiceProvider randomNumberGenerator)
        {
            if (bulkSessionKey == null)
            {
                throw ExceptionUtility.ArgumentNull(nameof(bulkSessionKey));
            }

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

            var hSessionKey = SafeKeyHandleImpl.InvalidHandle;

            if (!CryptoApi.CryptGenKey(providerHandle, Constants.CALG_G28147, 0, ref hSessionKey))
            {
                throw CreateWin32Error();
            }

            var keyWrap = new Gost_28147_89_KeyExchangeInfo {
                EncryptedKey = new byte[32]
            };

            Array.Copy(bulkSessionKey, keyWrap.EncryptedKey, 32);
            SetKeyParameterInt32(hSessionKey, Constants.KP_MODE, Constants.CRYPT_MODE_ECB);
            SetKeyParameterInt32(hSessionKey, Constants.KP_ALGID, Constants.CALG_G28147);
            SetKeyParameterInt32(hSessionKey, Constants.KP_PADDING, Constants.ZERO_PADDING);

            uint sessionKeySize = 32;

            if (!CryptoApi.CryptEncrypt(hSessionKey, SafeHashHandleImpl.InvalidHandle, true, 0, keyWrap.EncryptedKey, ref sessionKeySize, sessionKeySize))
            {
                throw CreateWin32Error();
            }

            SetKeyParameterInt32(hSessionKey, Constants.KP_MODE, Constants.CRYPT_MODE_CFB);

            var hashHandle = CreateHashImit(providerHandle, hSessionKey);

            keyWrap.Ukm = new byte[8];
            randomNumberGenerator.GetBytes(keyWrap.Ukm);

            if (!CryptoApi.CryptSetHashParam(hashHandle, Constants.HP_HASHSTARTVECT, keyWrap.Ukm, 0))
            {
                throw CreateWin32Error();
            }

            if (!CryptoApi.CryptHashData(hashHandle, bulkSessionKey, 32, 0))
            {
                throw CreateWin32Error();
            }

            keyWrap.Mac = EndHashData(hashHandle);
            keyWrap.EncryptionParamSet = GetKeyParameterString(hSessionKey, Constants.KP_CIPHEROID);

            SetKeyExchangeExportAlgId(providerType, hSessionKey, Constants.CALG_SIMPLE_EXPORT);
            SetKeyParameterInt32(hSessionKey, Constants.KP_MODE, Constants.CRYPT_MODE_ECB);
            SetKeyParameterInt32(hSessionKey, Constants.KP_PADDING, Constants.ZERO_PADDING);

            return(ImportKeyExchange(providerHandle, keyWrap, hSessionKey));
        }
Example #22
0
        public static bool VerifySign(SafeProvHandleImpl providerHandle, SafeHashHandleImpl hashHandle, SafeKeyHandleImpl keyHandle, byte[] hashValue, byte[] signatureValue)
        {
            SetHashValue(hashHandle, hashValue);

            return(CryptoApi.CryptVerifySignature(hashHandle, signatureValue, (uint)signatureValue.Length, keyHandle, null, 0));
        }