예제 #1
0
        public void ShouldDeriveKey(ProviderType providerType)
        {
            // TODO: VipNet does not support this feature - https://infotecs.ru/forum/topic/10142-oshibka-pri-sozdanii-klyucha-shifrovaniya-na-osnove-dannyih-polzovatelya-cryptderivekey/
            if (providerType.IsVipNet())
            {
                Assert.Ignore("VipNet does not support this feature");
            }

            // Given
            var initKey = new Gost_28147_89_SymmetricAlgorithm(providerType);

            // When

            Gost_28147_89_SymmetricAlgorithmBase randomKey1;
            Gost_28147_89_SymmetricAlgorithmBase randomKey2;
            Gost_28147_89_SymmetricAlgorithmBase randomKey3;

            using (var prf = new Gost_R3411_2012_512_PRF(initKey, Label, Seed))
            {
                randomKey1 = prf.DeriveKey();
                randomKey2 = prf.DeriveKey();
                randomKey3 = prf.DeriveKey();
            }

            // Then
            Assert.IsNotNull(randomKey1);
            Assert.IsNotNull(randomKey2);
            Assert.IsNotNull(randomKey3);
            AssertKeyIsValid(randomKey1);
            AssertKeyIsValid(randomKey2);
            AssertKeyIsValid(randomKey3);
            AssertKeysAreNotEqual(randomKey1, randomKey2);
            AssertKeysAreNotEqual(randomKey1, randomKey3);
            AssertKeysAreNotEqual(randomKey2, randomKey3);
        }
예제 #2
0
        private Gost_R3411_PRF(ProviderType providerType, Gost_28147_89_SymmetricAlgorithm key, byte[] label, byte[] seed) : base(providerType)
        {
            if (label == null)
            {
                throw ExceptionUtility.ArgumentNull(nameof(label));
            }

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

            _key  = key;
            _hmac = CreateHMAC(key);

            var labelAndSeed = new byte[label.Length + seed.Length];

            label.CopyTo(labelAndSeed, 0);
            seed.CopyTo(labelAndSeed, label.Length);

            _labelAndSeed = labelAndSeed;
            _buffer       = new byte[labelAndSeed.Length + (_hmac.HashSize / 8)];

            _value    = labelAndSeed;
            _keyIndex = 0;
        }
        public new EncryptedData Encrypt(XmlElement element, X509Certificate2 certificate)
        {
            if (element == null || certificate == null || !certificate.IsGost())
            {
                return(base.Encrypt(element, certificate));
            }

            var publicKey     = (GostAsymmetricAlgorithm)certificate.GetPublicKeyAlgorithm();
            var encryptionKey = new Gost_28147_89_SymmetricAlgorithm(publicKey.ProviderType);

            var encryptedKey = new EncryptedKey();

            encryptedKey.KeyInfo.AddClause(new KeyInfoX509Data(certificate));
            encryptedKey.EncryptionMethod       = new EncryptionMethod(publicKey.KeyExchangeAlgorithm);
            encryptedKey.CipherData.CipherValue = EncryptKey(encryptionKey, publicKey);

            var encryptedData = new EncryptedData
            {
                Type             = XmlEncElementUrl,
                EncryptionMethod = new EncryptionMethod(encryptionKey.AlgorithmName)
            };

            encryptedData.KeyInfo.AddClause(new KeyInfoEncryptedKey(encryptedKey));
            encryptedData.CipherData.CipherValue = EncryptData(element, encryptionKey, false);

            return(encryptedData);
        }
예제 #4
0
        public void ShouldDeriveBytes(ProviderType providerType)
        {
            // Given
            var initKey = new Gost_28147_89_SymmetricAlgorithm(providerType);

            // When

            byte[] randomBytes1;
            byte[] randomBytes2;
            byte[] randomBytes3;

            using (var prf = new Gost_R3411_94_PRF(initKey, Label, Seed))
            {
                randomBytes1 = prf.DeriveBytes();
                randomBytes2 = prf.DeriveBytes();
                randomBytes3 = prf.DeriveBytes();
            }

            // Then
            Assert.IsNotNull(randomBytes1);
            Assert.IsNotNull(randomBytes2);
            Assert.IsNotNull(randomBytes3);
            Assert.AreEqual(256, 8 * randomBytes1.Length);
            Assert.AreEqual(256, 8 * randomBytes2.Length);
            Assert.AreEqual(256, 8 * randomBytes3.Length);
            CollectionAssert.AreNotEqual(randomBytes1, randomBytes2);
            CollectionAssert.AreNotEqual(randomBytes1, randomBytes3);
            CollectionAssert.AreNotEqual(randomBytes2, randomBytes3);
        }
예제 #5
0
        private void InitDefaults(Gost_28147_89_SymmetricAlgorithm keyAlgorithm)
        {
            HashName = typeof(THash).Name;

            _keyAlgorithm = keyAlgorithm;
            _hmacHandle   = CreateHashHMAC(keyAlgorithm.ProviderType, CryptoApiHelper.GetProviderHandle(keyAlgorithm.ProviderType), keyAlgorithm.GetSafeHandle());
        }
예제 #6
0
        public void ShouldDeriveKey(ProviderType providerType)
        {
            // Given
            var initKey = new Gost_28147_89_SymmetricAlgorithm(providerType);

            // When

            Gost_28147_89_SymmetricAlgorithmBase randomKey1;
            Gost_28147_89_SymmetricAlgorithmBase randomKey2;
            Gost_28147_89_SymmetricAlgorithmBase randomKey3;

            using (var prf = new Gost_R3411_94_PRF(initKey, Label, Seed))
            {
                randomKey1 = prf.DeriveKey();
                randomKey2 = prf.DeriveKey();
                randomKey3 = prf.DeriveKey();
            }

            // Then
            Assert.IsNotNull(randomKey1);
            Assert.IsNotNull(randomKey2);
            Assert.IsNotNull(randomKey3);
            AssertKeyIsValid(randomKey1);
            AssertKeyIsValid(randomKey2);
            AssertKeyIsValid(randomKey3);
            AssertKeysAreNotEqual(randomKey1, randomKey2);
            AssertKeysAreNotEqual(randomKey1, randomKey3);
            AssertKeysAreNotEqual(randomKey2, randomKey3);
        }
예제 #7
0
        private static XmlDocument EncryptXmlDocument(XmlDocument xmlDocument, Gost_28147_89_SymmetricAlgorithm sharedKey)
        {
            // Создание объекта для шифрации XML
            var encryptedXml = new GostEncryptedXml(sharedKey.ProviderType);

            // Поиск элементов для шифрации
            var elements = xmlDocument.SelectNodes("//SomeElement[@Encrypt='true']");

            if (elements != null)
            {
                foreach (XmlElement element in elements)
                {
                    // Шифрация элемента
                    var encryptedData = encryptedXml.EncryptData(element, sharedKey, false);

                    // Формирование элемента EncryptedData
                    var elementEncryptedData = new EncryptedData();
                    elementEncryptedData.Type                   = EncryptedXml.XmlEncElementUrl;
                    elementEncryptedData.EncryptionMethod       = new EncryptionMethod(sharedKey.AlgorithmName);
                    elementEncryptedData.CipherData.CipherValue = encryptedData;

                    // Замена элемента его зашифрованным представлением
                    GostEncryptedXml.ReplaceElement(element, elementEncryptedData, false);
                }
            }

            return(xmlDocument);
        }
        private static Stream SendEncryptedDataStream(GostAsymmetricAlgorithm publicKey, Stream dataStream, out byte[] iv, out byte[] sessionKey)
        {
            var encryptedDataStream = new MemoryStream();

            // Отправитель создает случайный сессионный ключ для шифрации данных
            using (var senderSessionKey = new Gost_28147_89_SymmetricAlgorithm(publicKey.ProviderType))
            {
                // Отправитель передает получателю вектор инициализации
                iv = senderSessionKey.IV;

                // Отправитель шифрует сессионный ключ и передает его получателю
                var formatter = publicKey.CreateKeyExchangeFormatter();
                sessionKey = formatter.CreateKeyExchangeData(senderSessionKey);

                // Отправитель шифрует данные с использованием сессионного ключа
                using (var encryptor = senderSessionKey.CreateEncryptor())
                {
                    var cryptoStream = new CryptoStream(encryptedDataStream, encryptor, CryptoStreamMode.Write);
                    dataStream.CopyTo(cryptoStream);
                    cryptoStream.FlushFinalBlock();
                }
            }

            encryptedDataStream.Position = 0;

            return(encryptedDataStream);
        }
예제 #9
0
        public Gost_28147_89_SymmetricAlgorithmBase DeriveKey()
        {
            var randomPassword = GenerateNextBytes();

            using (var hmac = CreateHMAC(_key))
            {
                return(Gost_28147_89_SymmetricAlgorithm.CreateFromPassword(hmac, randomPassword));
            }
        }
예제 #10
0
        protected Gost_R3411_HMAC(Gost_28147_89_SymmetricAlgorithmBase keyAlgorithm, int hashSize) : base(keyAlgorithm.ProviderType, hashSize)
        {
            if (keyAlgorithm == null)
            {
                throw ExceptionUtility.ArgumentNull(nameof(keyAlgorithm));
            }

            InitDefaults(Gost_28147_89_SymmetricAlgorithm.CreateFromKey(keyAlgorithm));
        }
        private static XmlDocument EncryptXmlDocument(XmlDocument xmlDocument, IEnumerable <X509Certificate2> certificates)
        {
            // Создание объекта для шифрации XML
            var encryptedXml = new GostEncryptedXml();

            // Поиск элементов для шифрации
            var elements = xmlDocument.SelectNodes("//SomeElement[@Encrypt='true']");

            if (elements != null)
            {
                var elementIndex = 0;

                foreach (XmlElement element in elements)
                {
                    // Формирование элемента EncryptedData
                    var elementEncryptedData = new EncryptedData();
                    elementEncryptedData.Id      = "EncryptedElement" + elementIndex++;
                    elementEncryptedData.Type    = EncryptedXml.XmlEncElementUrl;
                    elementEncryptedData.KeyInfo = new KeyInfo();

                    using (var sessionKey = new Gost_28147_89_SymmetricAlgorithm())
                    {
                        elementEncryptedData.EncryptionMethod = new EncryptionMethod(sessionKey.AlgorithmName);

                        // Шифрация элемента с использованием симметричного ключа
                        var encryptedElement = encryptedXml.EncryptData(element, sessionKey, false);

                        foreach (var certificate in certificates)
                        {
                            // Шифрация сессионного ключа с использованием открытого ключа сертификата
                            var encryptedSessionKeyData = GostEncryptedXml.EncryptKey(sessionKey, (GostAsymmetricAlgorithm)certificate.GetPublicKeyAlgorithm());

                            // Формирование информации о зашифрованном сессионном ключе
                            var encryptedSessionKey = new EncryptedKey();
                            encryptedSessionKey.CipherData       = new CipherData(encryptedSessionKeyData);
                            encryptedSessionKey.EncryptionMethod = new EncryptionMethod(GostEncryptedXml.XmlEncGostCryptoProKeyExportUrl);
                            encryptedSessionKey.AddReference(new DataReference {
                                Uri = "#" + elementEncryptedData.Id
                            });
                            encryptedSessionKey.KeyInfo.AddClause(new KeyInfoX509Data(certificate));

                            // Добавление ссылки на зашифрованный ключ, используемый при шифровании данных
                            elementEncryptedData.KeyInfo.AddClause(new KeyInfoEncryptedKey(encryptedSessionKey));
                        }

                        // Установка зашифрованных данных у объекта EncryptedData
                        elementEncryptedData.CipherData.CipherValue = encryptedElement;
                    }

                    // Замена элемента его зашифрованным представлением
                    GostEncryptedXml.ReplaceElement(element, elementEncryptedData, false);
                }
            }

            return(xmlDocument);
        }
예제 #12
0
        private static XmlDocument EncryptXmlDocument(XmlDocument xmlDocument, GostAsymmetricAlgorithm publicKey)
        {
            // Создание объекта для шифрации XML
            var encryptedXml = new GostEncryptedXml(publicKey.ProviderType);

            // Поиск элементов для шифрации
            var elements = xmlDocument.SelectNodes("//SomeElement[@Encrypt='true']");

            if (elements != null)
            {
                var elementIndex = 0;

                foreach (XmlElement element in elements)
                {
                    // Создание случайного сессионного ключа
                    using (var sessionKey = new Gost_28147_89_SymmetricAlgorithm(publicKey.ProviderType))
                    {
                        // Шифрация элемента
                        var encryptedData = encryptedXml.EncryptData(element, sessionKey, false);

                        // Шифрация сессионного ключа с использованием публичного асимметричного ключа
                        var encryptedSessionKeyData = GostEncryptedXml.EncryptKey(sessionKey, publicKey);

                        // Формирование элемента EncryptedData
                        var elementEncryptedData = new EncryptedData();
                        elementEncryptedData.Id                     = "EncryptedElement" + elementIndex++;
                        elementEncryptedData.Type                   = EncryptedXml.XmlEncElementUrl;
                        elementEncryptedData.EncryptionMethod       = new EncryptionMethod(sessionKey.AlgorithmName);
                        elementEncryptedData.CipherData.CipherValue = encryptedData;
                        elementEncryptedData.KeyInfo                = new KeyInfo();

                        // Формирование информации о зашифрованном сессионном ключе
                        var encryptedSessionKey = new EncryptedKey();
                        encryptedSessionKey.CipherData       = new CipherData(encryptedSessionKeyData);
                        encryptedSessionKey.EncryptionMethod = new EncryptionMethod(publicKey.KeyExchangeAlgorithm);
                        encryptedSessionKey.AddReference(new DataReference {
                            Uri = "#" + elementEncryptedData.Id
                        });
                        encryptedSessionKey.KeyInfo.AddClause(new KeyInfoName {
                            Value = "KeyName1"
                        });

                        // Добавление ссылки на зашифрованный ключ, используемый при шифровании данных
                        elementEncryptedData.KeyInfo.AddClause(new KeyInfoEncryptedKey(encryptedSessionKey));

                        // Замена элемента его зашифрованным представлением
                        GostEncryptedXml.ReplaceElement(element, elementEncryptedData, false);
                    }
                }
            }

            return(xmlDocument);
        }
        private byte[] EncodeKeyExchangeInternal(Gost_28147_89_SymmetricAlgorithm keyExchangeAlgorithm, GostKeyExchangeExportMethod keyExchangeExportMethod)
        {
            switch (keyExchangeExportMethod)
            {
            case GostKeyExchangeExportMethod.GostKeyExport:
                return(EncodeKeyExchangeInternal(keyExchangeAlgorithm, Constants.CALG_SIMPLE_EXPORT));

            case GostKeyExchangeExportMethod.CryptoProKeyExport:
                return(EncodeKeyExchangeInternal(keyExchangeAlgorithm, Constants.CALG_PRO_EXPORT));
            }

            throw ExceptionUtility.ArgumentOutOfRange(nameof(keyExchangeExportMethod));
        }
        public void ShouldEncryptAndDecrypt(ProviderType providerType)
        {
            // Given
            var sharedKey  = new Gost_28147_89_SymmetricAlgorithm(providerType);
            var dataStream = CreateDataStream();

            // When
            var encryptedDataStream = EncryptDataStream(sharedKey, dataStream);
            var decryptedDataStream = DecryptDataStream(sharedKey, encryptedDataStream);

            // Then
            Assert.That(dataStream, Is.EqualTo(decryptedDataStream));
        }
예제 #15
0
        public void ShouldComputeHMAC(ProviderType providerType)
        {
            // Given
            var dataStream = CreateDataStream();
            var sharedKey  = new Gost_28147_89_SymmetricAlgorithm(providerType);

            // When
            var hmacDataStream        = CreateHmacDataStream(sharedKey, dataStream);
            var isValidHmacDataStream = VerifyHmacDataStream(sharedKey, hmacDataStream);

            // Then
            Assert.IsTrue(isValidHmacDataStream);
        }
        /// <inheritdoc />
        public override byte[] CreateKeyExchange(byte[] keyExchangeData)
        {
            if (keyExchangeData == null)
            {
                throw ExceptionUtility.ArgumentNull(nameof(keyExchangeData));
            }

            using (var keyExchangeAlgorithm = new Gost_28147_89_SymmetricAlgorithm(_publicKey.ProviderType))
            {
                keyExchangeAlgorithm.Key = keyExchangeData;

                return(CreateKeyExchangeData(keyExchangeAlgorithm));
            }
        }
예제 #17
0
        public void ShouldEncryptXml(ProviderType providerType)
        {
            // Given
            var sharedKey   = new Gost_28147_89_SymmetricAlgorithm(providerType);
            var xmlDocument = CreateXmlDocument();
            var expectedXml = xmlDocument.OuterXml;

            // When
            var encryptedXmlDocument = EncryptXmlDocument(xmlDocument, sharedKey);
            var decryptedXmlDocument = DecryptXmlDocument(encryptedXmlDocument, sharedKey);
            var actualXml            = decryptedXmlDocument.OuterXml;

            // Then
            Assert.AreEqual(expectedXml, actualXml);
        }
        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);
        }
        private byte[] EncodeKeyExchangeInternal(Gost_28147_89_SymmetricAlgorithm keyExchangeAlgorithm, int keyExchangeExportAlgId)
        {
            Gost_28147_89_KeyExchangeInfo keyExchangeInfo;

            SafeKeyHandleImpl keyExchangeHandle = null;

            try
            {
                var importedKeyBytes = CryptoApiHelper.EncodePublicBlob(_keyExchangeParameters, _keySize, _signatureAlgId);
                CryptoApiHelper.ImportCspBlob(importedKeyBytes, _provHandle, _keyHandle, out keyExchangeHandle);
                CryptoApiHelper.SetKeyExchangeExportAlgId(ProviderType, keyExchangeHandle, keyExchangeExportAlgId);

                var symKeyHandle = keyExchangeAlgorithm.GetSafeHandle();
                keyExchangeInfo = CryptoApiHelper.ExportKeyExchange(symKeyHandle, keyExchangeHandle);
            }
            finally
            {
                keyExchangeHandle.TryDispose();
            }

            return(keyExchangeInfo.Encode());
        }
예제 #20
0
 protected abstract THMAC CreateHMAC(Gost_28147_89_SymmetricAlgorithm key);
예제 #21
0
        private static XmlDocument DecryptXmlDocument(XmlDocument encryptedXmlDocument, Gost_28147_89_SymmetricAlgorithm sharedKey)
        {
            // Создание объекта для дешифрации XML
            var encryptedXml = new GostEncryptedXml(sharedKey.ProviderType, encryptedXmlDocument);

            var nsManager = new XmlNamespaceManager(encryptedXmlDocument.NameTable);

            nsManager.AddNamespace("enc", EncryptedXml.XmlEncNamespaceUrl);

            // Поиск всех зашифрованных XML-элементов
            var encryptedDataList = encryptedXmlDocument.SelectNodes("//enc:EncryptedData", nsManager);

            if (encryptedDataList != null)
            {
                foreach (XmlElement encryptedData in encryptedDataList)
                {
                    // Загрузка элемента EncryptedData
                    var elementEncryptedData = new EncryptedData();
                    elementEncryptedData.LoadXml(encryptedData);

                    // Расшифровка элемента EncryptedData
                    var decryptedData = encryptedXml.DecryptData(elementEncryptedData, sharedKey);

                    // Замена элемента EncryptedData его расшифрованным представлением
                    encryptedXml.ReplaceData(encryptedData, decryptedData);
                }
            }

            return(encryptedXmlDocument);
        }
예제 #22
0
 protected Gost_R3411_PRF(Gost_28147_89_SymmetricAlgorithmBase key, byte[] label, byte[] seed)
     : this(key.ProviderType, Gost_28147_89_SymmetricAlgorithm.CreateFromKey(key), label, seed)
 {
 }
 protected override Gost_R3411_2012_256_HMAC CreateHMAC(Gost_28147_89_SymmetricAlgorithm key)
 {
     return(new Gost_R3411_2012_256_HMAC(key));
 }
예제 #24
0
 protected Gost_R3411_PRF(ProviderType providerType, byte[] key, byte[] label, byte[] seed)
     : this(providerType, Gost_28147_89_SymmetricAlgorithm.CreateFromSessionKey(providerType, key), label, seed)
 {
 }