Пример #1
0
 public void Encrypt2012_256()
 {
     using (Gost3410_2012_256 gost = GetGost2012_256Provider())
     {
         Encrypt(gost);
     }
 }
Пример #2
0
        public static X509Certificate2 CopyWithPrivateKey(this X509Certificate2 certificate, Gost3410_2012_256 privateKey)
        {
            if (certificate == null)
            {
                throw new ArgumentNullException(nameof(certificate));
            }
            if (privateKey == null)
            {
                throw new ArgumentNullException(nameof(privateKey));
            }

            if (certificate.HasPrivateKey)
            {
                throw new InvalidOperationException(SR.Cryptography_Cert_AlreadyHasPrivateKey);
            }

            using (Gost3410_2012_256 publicKey = GetGost3410_2012_256PublicKey(certificate))
            {
                if (publicKey == null)
                {
                    throw new ArgumentException(SR.Cryptography_PrivateKey_WrongAlgorithm);
                }

                //Gost3410Parameters currentParameters = publicKey.ExportParameters(false);
                //Gost3410Parameters newParameters = privateKey.ExportParameters(false);
            }

            ICertificatePal pal = certificate.Pal.CopyWithPrivateKey(privateKey);

            return(new X509Certificate2(pal));
        }
Пример #3
0
        // Шифрование тестового файла.
        static void EncryptTestFile(
            Gost3410_2012_256 publicKey,
            Gost3410_2012_256CryptoServiceProvider privateKey,
            string fileId = "2012_256")
        {
            // Создаем симметричный ключ.
            Gost28147 symmetric = Gost28147.Create();

            // Открываем ключ отправителя.
            Gost3410Parameters srcPublicKeyParameters = privateKey.ExportParameters(false);

            // Создаем agree ключ
            GostSharedSecretAlgorithm agree = privateKey.CreateAgree(
                publicKey.ExportParameters(false));

            // Зашифровываем симметричный ключ на agree ключе.
            byte[] WrappedKey = agree.Wrap(symmetric,
                                           GostKeyWrapMethod.CryptoPro12KeyWrap);

            // Создаем поток шифратора.
            ICryptoTransform transform = symmetric.CreateEncryptor();

            // Создаем зашифрованный файл.
            using (FileStream ofs = new FileStream(string.Format(EncryptedFileName, fileId), FileMode.Create))
            {
                BinaryWriter bw = new BinaryWriter(ofs);

                // Записываем зашифрованный симметричный ключ.
                bw.Write(WrappedKey.Length);
                bw.Write(WrappedKey);

                // Записываем синхропосылку
                bw.Write(symmetric.IV.Length);
                bw.Write(symmetric.IV);

                // Передаем открытый ключ.
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(ofs, srcPublicKeyParameters);

                // Создаем поток шифрования для записи в файл.
                using (CryptoStream cs = new CryptoStream(ofs, transform, CryptoStreamMode.Write))
                {
                    byte[] data = new byte[4096];
                    // Открываем входной файл.
                    using (FileStream ifs = new FileStream(string.Format(SourceFileName, fileId), FileMode.Open, FileAccess.Read))
                    {
                        // и переписываем содержимое в выходной поток.
                        int length = ifs.Read(data, 0, data.Length);
                        while (length > 0)
                        {
                            cs.Write(data, 0, length);
                            length = ifs.Read(data, 0, data.Length);
                        }
                    }
                }
            }
        }
Пример #4
0
        /// <summary>
        /// Create a self-signed certificate using the established subject, key, and optional
        /// extensions.
        /// </summary>
        /// <param name="notBefore">
        ///   The oldest date and time where this certificate is considered valid.
        ///   Typically <see cref="DateTimeOffset.UtcNow"/>, plus or minus a few seconds.
        /// </param>
        /// <param name="notAfter">
        ///   The date and time where this certificate is no longer considered valid.
        /// </param>
        /// <returns>
        ///   An <see cref="X509Certificate2"/> with the specified values. The returned object will
        ///   assert <see cref="X509Certificate2.HasPrivateKey" />.
        /// </returns>
        /// <exception cref="ArgumentException">
        ///   <paramref name="notAfter"/> represents a date and time before <paramref name="notAfter"/>.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        ///   A constructor was used which did not accept a signing key.
        /// </exception>>
        /// <exception cref="CryptographicException">
        ///   Other errors during the certificate creation process.
        /// </exception>
        public X509Certificate2 CreateSelfSigned(DateTimeOffset notBefore, DateTimeOffset notAfter)
        {
            if (notAfter < notBefore)
            {
                throw new ArgumentException(SR.Cryptography_CertReq_DatesReversed);
            }
            if (_key == null)
            {
                throw new InvalidOperationException(SR.Cryptography_CertReq_NoKeyProvided);
            }

            Debug.Assert(_generator != null);

            byte[] serialNumber = new byte[8];
            RandomNumberGenerator.Fill(serialNumber);

            using (X509Certificate2 certificate = Create(
                       SubjectName,
                       _generator,
                       notBefore,
                       notAfter,
                       serialNumber))
            {
                RSA rsa = _key as RSA;

                if (rsa != null)
                {
                    return(certificate.CopyWithPrivateKey(rsa));
                }

                ECDsa ecdsa = _key as ECDsa;

                if (ecdsa != null)
                {
                    return(certificate.CopyWithPrivateKey(ecdsa));
                }

                Gost3410 gost3410 = _key as Gost3410;
                if (gost3410 != null)
                {
                    return(certificate.CopyWithPrivateKey(gost3410));
                }
                Gost3410_2012_256 gost3410_2012_256 = _key as Gost3410_2012_256;
                if (gost3410_2012_256 != null)
                {
                    return(certificate.CopyWithPrivateKey(gost3410_2012_256));
                }
                Gost3410_2012_512 gost3410_2012_512 = _key as Gost3410_2012_512;
                if (gost3410_2012_512 != null)
                {
                    return(certificate.CopyWithPrivateKey(gost3410_2012_512));
                }
            }

            Debug.Fail($"Key was of no known type: {_key?.GetType().FullName ?? "null"}");
            throw new CryptographicException();
        }
Пример #5
0
        public static X509SignatureGenerator CreateForGost(Gost3410_2012_256 key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            return(new Gost3410_2012_256SignatureGenerator(key));
        }
Пример #6
0
        private static void EncriptFile(X509Certificate2 sert, string sourceFile, string encFile)
        {
            var publicKey = (Gost3410_2012_256CryptoServiceProvider)sert.PublicKey.Key;

            var asymmetricAlg = publicKey as Gost3410_2012_256;

            if (asymmetricAlg == null)
            {
                throw new CryptographicException("Not a gost certificate");
            }

            var symmetricKey = Gost28147.Create();

            Gost3410_2012_256  senderRndKey           = Gost3410_2012_256.Create();
            Gost3410Parameters senderRndKeyParameters = senderRndKey.ExportParameters(false);

            GostSharedSecretAlgorithm agreeKey = senderRndKey.CreateAgree(asymmetricAlg.ExportParameters(false));

            var encodedSymmetricKey = agreeKey.Wrap(symmetricKey, GostKeyWrapMethod.CryptoProKeyWrap);

            ICryptoTransform transform = symmetricKey.CreateEncryptor();

            using (FileStream writer = new FileStream(encFile, FileMode.Create))
            {
                BinaryWriter binaryWriter = new BinaryWriter(writer);

                binaryWriter.Write(encodedSymmetricKey.Length);
                binaryWriter.Write(encodedSymmetricKey);

                binaryWriter.Write(symmetricKey.IV.Length);
                binaryWriter.Write(symmetricKey.IV);

                BinaryFormatter binaryFormatter = new BinaryFormatter();
                binaryFormatter.Serialize(writer, senderRndKeyParameters);

                using (CryptoStream cryptoStream = new CryptoStream(writer, transform, CryptoStreamMode.Write))
                {
                    var buffer = new byte[100];

                    using (FileStream reader = new FileStream(sourceFile, FileMode.Open, FileAccess.Read))
                    {
                        var length = reader.Read(buffer, 0, buffer.Length);
                        while (length > 0)
                        {
                            cryptoStream.Write(buffer, 0, buffer.Length);
                            length = reader.Read(buffer, 0, buffer.Length);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Устанавливает секретный ключ.
        /// </summary>
        ///
        /// <param name="key">Объект класса AsymmetricAlgorithm,
        /// содержащий секретный ключ.</param>
        ///
        /// <remarks><para>Ключ должен быть установлен до вызова
        /// функций восстановления ключа.</para>
        /// </remarks>
        ///
        /// <argnull name="key" />
        /// <exception cref="CryptographicException">
        /// <paramref name="key"/> не поддерживает алгоритм
        /// <see cref="Gost3410_2012_256"/>.</exception>
        public override void SetKey(AsymmetricAlgorithm key)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }
            Gost3410_2012_256 gost = key as Gost3410_2012_256;

            if (gost == null)
            {
                throw new CryptographicException(
                          Resources.Cryptography_Assymmetric_GOST3410_2012_256);
            }
            gostKey_ = gost;
        }
Пример #8
0
        public void TestKeyExchange2012_256()
        {
            // Ассиметричный ключ получателя.
            Gost3410_2012_256 AssymKey;

            // Синхропосылка.
            byte[] IV;

            // Создаем случайный открытый ключ.
            using (Gost3410_2012_256 gkey = GetGostProvider2012_256())
            {
                AssymKey = gkey;

                // Создаем случайный секретный ключ, который необходимо передать.
                Gost28147 key = new Gost28147CryptoServiceProvider();
                // Синхропосылка не входит в GostKeyTransport и должна
                // передаваться отдельно.
                IV = key.IV;

                // Создаем форматтер, шифрующий на ассиметричном ключе получателя.
                GostKeyExchangeFormatter Formatter = new GostKeyExchangeFormatter(AssymKey);
                // GostKeyTransport - формат зашифрованной для безопасной передачи
                // ключевой информации.
                GostKeyTransport encKey = Formatter.CreateKeyExchange(key);

                // Шифруемая строка
                string message     = "012345678901234567890";
                byte[] sourceBytes = Encoding.ASCII.GetBytes(message);
                Console.WriteLine("** Строка до шифрования: " + message);

                // Шифруем строку на сессионном ключе
                byte[] encBytes = GostEncrypt(key, sourceBytes);
                Console.WriteLine("** Строка после шифрования: " +
                                  Encoding.ASCII.GetString(encBytes));

                // Получатель расшифровывает GostKeyTransport и само сообщение.
                byte[] decBytes = GostDecrypt(encKey, encBytes, IV, AssymKey);
                Console.WriteLine("** Строка после расшифрования: " +
                                  Encoding.ASCII.GetString(decBytes));

                Assert.Equal(sourceBytes, decBytes);
            }
        }
Пример #9
0
        /// <summary>
        /// Create a CertificateRequest for the specified subject name, GOST3410_2012_256 key, and hash algorithm.
        /// </summary>
        /// <param name="subjectName">
        ///   The parsed representation of the subject name for the certificate or certificate request.
        /// </param>
        /// <param name="key">
        ///   n GOST3410 key whose public key material will be included in the certificate or certificate request.
        ///   This key will be used as a private key if <see cref="CreateSelfSigned" /> is called.
        /// </param>
        /// <param name="hashAlgorithm">
        ///   The hash algorithm to use when signing the certificate or certificate request.
        /// </param>
        public CertificateRequest(X500DistinguishedName subjectName, Gost3410_2012_256 key, HashAlgorithmName hashAlgorithm)
        {
            if (subjectName == null)
            {
                throw new ArgumentNullException(nameof(subjectName));
            }
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (string.IsNullOrEmpty(hashAlgorithm.Name))
            {
                throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm));
            }

            SubjectName = subjectName;

            _key          = key;
            _generator    = X509SignatureGenerator.CreateForGost(key);
            PublicKey     = _generator.PublicKey;
            HashAlgorithm = hashAlgorithm;
        }
Пример #10
0
 /// <summary>
 /// Инициализирует новый экземпляр класса <c>GostKeyValue</c> с заданным
 /// открытым ключом ГОСТ 34.10-2012 256.
 /// </summary>
 ///
 /// <param name="key">Экземпляр реализации класса
 /// <see cref="Gost2012_256KeyValue"/>, в котором содержится открытый
 /// ключ.</param>
 public Gost2012_256KeyValue(Gost3410_2012_256 key)
 {
     _key = key;
 }
Пример #11
0
 /// <summary>
 /// Инициализирует новый экземпляр класса <c>GostKeyValue</c> с новым,
 /// сгенерированным случайным образом открытым ключом ГОСТ 34.10-2012 256.
 /// </summary>
 /// <remarks>При создании нового ключа ГОСТ 34.10-2012 256 этот конструктор
 /// использует реализацию <see cref="Gost3410_2012_256"/> по
 /// умолчанию, как определено классом
 /// <see cref="System.Security.Cryptography.CryptoConfig"/>.</remarks>
 public Gost2012_256KeyValue()
 {
     _key = (Gost3410_2012_256)Gost3410_2012_256.Create();
 }
Пример #12
0
        /// <summary>
        /// Create a certificate using the established subject, key, and optional extensions using
        /// the provided certificate as the issuer.
        /// </summary>
        /// <param name="issuerCertificate">
        ///   An X509Certificate2 instance representing the issuing Certificate Authority (CA).
        /// </param>
        /// <param name="notBefore">
        ///   The oldest date and time where this certificate is considered valid.
        ///   Typically <see cref="DateTimeOffset.UtcNow"/>, plus or minus a few seconds.
        /// </param>
        /// <param name="notAfter">
        ///   The date and time where this certificate is no longer considered valid.
        /// </param>
        /// <param name="serialNumber">
        ///   The serial number to use for the new certificate. This value should be unique per issuer.
        ///   The value is interpreted as an unsigned (big) integer in big endian byte ordering.
        /// </param>
        /// <returns>
        ///   An <see cref="X509Certificate2"/> with the specified values. The returned object will
        ///   not assert <see cref="X509Certificate2.HasPrivateKey" />.
        /// </returns>
        /// <exception cref="ArgumentNullException"><paramref name="issuerCertificate"/> is null.</exception>
        /// <exception cref="ArgumentException">
        ///   The <see cref="X509Certificate2.HasPrivateKey"/> value for <paramref name="issuerCertificate"/> is false.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///   The type of signing key represented by <paramref name="issuerCertificate"/> could not be determined.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///   <paramref name="notAfter"/> represents a date and time before <paramref name="notBefore"/>.
        /// </exception>
        /// <exception cref="ArgumentException"><paramref name="serialNumber"/> is null or has length 0.</exception>
        /// <exception cref="ArgumentException">
        ///   <paramref name="issuerCertificate"/> has a different key algorithm than the requested certificate.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        ///   <paramref name="issuerCertificate"/> is an RSA certificate and this object was created via a constructor
        ///   which does not accept a <see cref="RSASignaturePadding"/> value.
        /// </exception>
        public X509Certificate2 Create(
            X509Certificate2 issuerCertificate,
            DateTimeOffset notBefore,
            DateTimeOffset notAfter,
            byte[] serialNumber)
        {
            if (issuerCertificate == null)
            {
                throw new ArgumentNullException(nameof(issuerCertificate));
            }
            if (!issuerCertificate.HasPrivateKey)
            {
                throw new ArgumentException(SR.Cryptography_CertReq_IssuerRequiresPrivateKey, nameof(issuerCertificate));
            }
            if (notAfter < notBefore)
            {
                throw new ArgumentException(SR.Cryptography_CertReq_DatesReversed);
            }
            if (serialNumber == null || serialNumber.Length < 1)
            {
                throw new ArgumentException(SR.Arg_EmptyOrNullArray, nameof(serialNumber));
            }

            if (issuerCertificate.PublicKey.Oid.Value != PublicKey.Oid.Value)
            {
                throw new ArgumentException(
                          SR.Format(
                              SR.Cryptography_CertReq_AlgorithmMustMatch,
                              issuerCertificate.PublicKey.Oid.Value,
                              PublicKey.Oid.Value),
                          nameof(issuerCertificate));
            }

            DateTime notBeforeLocal = notBefore.LocalDateTime;

            if (notBeforeLocal < issuerCertificate.NotBefore)
            {
                throw new ArgumentException(
                          SR.Format(
                              SR.Cryptography_CertReq_NotBeforeNotNested,
                              notBeforeLocal,
                              issuerCertificate.NotBefore),
                          nameof(notBefore));
            }

            DateTime notAfterLocal = notAfter.LocalDateTime;

            // Round down to the second, since that's the cert accuracy.
            // This makes one method which uses the same DateTimeOffset for chained notAfters
            // not need to do the rounding locally.
            long notAfterLocalTicks = notAfterLocal.Ticks;
            long fractionalSeconds  = notAfterLocalTicks % TimeSpan.TicksPerSecond;

            notAfterLocalTicks -= fractionalSeconds;
            notAfterLocal       = new DateTime(notAfterLocalTicks, notAfterLocal.Kind);

            if (notAfterLocal > issuerCertificate.NotAfter)
            {
                throw new ArgumentException(
                          SR.Format(
                              SR.Cryptography_CertReq_NotAfterNotNested,
                              notAfterLocal,
                              issuerCertificate.NotAfter),
                          nameof(notAfter));
            }

            // Check the Basic Constraints and Key Usage extensions to help identify inappropriate certificates.
            // Note that this is not a security check. The system library backing X509Chain will use these same criteria
            // to determine if a chain is valid; and a user can easily call the X509SignatureGenerator overload to
            // bypass this validation.  We're simply helping them at signing time understand that they've
            // chosen the wrong cert.
            var basicConstraints = (X509BasicConstraintsExtension)issuerCertificate.Extensions[Oids.BasicConstraints2];
            var keyUsage         = (X509KeyUsageExtension)issuerCertificate.Extensions[Oids.KeyUsage];

            if (basicConstraints == null)
            {
                throw new ArgumentException(SR.Cryptography_CertReq_BasicConstraintsRequired, nameof(issuerCertificate));
            }
            if (!basicConstraints.CertificateAuthority)
            {
                throw new ArgumentException(SR.Cryptography_CertReq_IssuerBasicConstraintsInvalid, nameof(issuerCertificate));
            }
            if (keyUsage != null && (keyUsage.KeyUsages & X509KeyUsageFlags.KeyCertSign) == 0)
            {
                throw new ArgumentException(SR.Cryptography_CertReq_IssuerKeyUsageInvalid, nameof(issuerCertificate));
            }

            AsymmetricAlgorithm key = null;
            string keyAlgorithm     = issuerCertificate.GetKeyAlgorithm();
            X509SignatureGenerator generator;

            try
            {
                switch (keyAlgorithm)
                {
                case Oids.Rsa:
                    if (_rsaPadding == null)
                    {
                        throw new InvalidOperationException(SR.Cryptography_CertReq_RSAPaddingRequired);
                    }

                    RSA rsa = issuerCertificate.GetRSAPrivateKey();
                    key       = rsa;
                    generator = X509SignatureGenerator.CreateForRSA(rsa, _rsaPadding);
                    break;

                case Oids.EcPublicKey:
                    ECDsa ecdsa = issuerCertificate.GetECDsaPrivateKey();
                    key       = ecdsa;
                    generator = X509SignatureGenerator.CreateForECDsa(ecdsa);
                    break;

                //begin: gost
                case Oids.Gost3410EL:
                    Gost3410 gost3410 = issuerCertificate.GetGost3410PrivateKey();
                    key       = gost3410;
                    generator = X509SignatureGenerator.CreateForGost(gost3410);
                    break;

                case Oids.Gost3410_2012_256:
                    Gost3410_2012_256 gost3410_2012_256 = issuerCertificate.GetGost3410_2012_256PrivateKey();
                    key       = gost3410_2012_256;
                    generator = X509SignatureGenerator.CreateForGost(gost3410_2012_256);
                    break;

                case Oids.Gost3410_2012_512:
                    Gost3410_2012_512 gost3410_2012_512 = issuerCertificate.GetGost3410_2012_512PrivateKey();
                    key       = gost3410_2012_512;
                    generator = X509SignatureGenerator.CreateForGost(gost3410_2012_512);
                    break;

                //end: gost
                default:
                    throw new ArgumentException(
                              SR.Format(SR.Cryptography_UnknownKeyAlgorithm, keyAlgorithm),
                              nameof(issuerCertificate));
                }

                return(Create(issuerCertificate.SubjectName, generator, notBefore, notAfter, serialNumber));
            }
            finally
            {
                key?.Dispose();
            }
        }
Пример #13
0
 public ICertificatePal CopyWithPrivateKey(Gost3410_2012_256 gost)
 {
     return(CopyWithPersistedCapiKey(((Gost3410_2012_256CryptoServiceProvider)gost).CspKeyContainerInfo));
 }
Пример #14
0
        internal Gost3410_2012_256SignatureGenerator(Gost3410_2012_256 key)
        {
            Debug.Assert(key != null);

            _key = key;
        }
        public byte[] DecryptMessage()
        {
            X509Certificate2 cert = GetCertificate();

            Gost3410_2012_256 assym = cert.PrivateKey as Gost3410_2012_256;

            var s_parts = encryptedSessionKey.Split(':');
            var parts   = encryptedSessionKey.Split(':').Select(part => part.Split(' ').Select(e => Convert.ToByte(e, 16)).ToArray()).ToArray();
            //0 - Параметры шифрования ключа обмена. Компонент является результатом выполнения CryptGetKeyParam(KP_CIPHEROID).
            //1 - Эфемерный открытый ключ, который использовался для выработки ключа обмена. Компонент является результатом выполнения CryptExportKey(PUBLICKEYBLOBEX).
            //2 - Симметричный ключ, зашифрованный на ключе обмена. Компонент является результатом выполнения CryptExportKey(SIMPLEBLOB).
            //
            //   -=PUBLICKEYBLOB=-
            // BYTE bPublicKeyBlob[] =
            // {
            //		0x06, // bType = PUBLICKEYBLOB
            //		0x20, // bVersion = 0x20
            //		0x00, 0x00, // reserved
            //		0x23, 0x2E, 0x00, 0x00, // KeyAlg = ALG_SID_GR3410EL
            //		0x4D, 0x41, 0x47, 0x31, // Magic = GR3410_1_MAGIC
            //		0x00, 0x02, 0x00, 0x00, // BitLen = 512
            //		bASN1GostR3410_94_PublicKeyParameters
            //		0x30, 0x12,
            //		0x06, 0x07,
            //		0x2A, 0x85, 0x03, 0x02, 0x02, 0x24, 0x00,
            //		0x06, 0x07,
            //		0x2A, 0x85, 0x03, 0x02, 0x02, 0x1E, 0x01,
            //		bPublicKey
            //		0x2D, 0xC3, 0xFD, 0xF6, 0x9C, 0x91, 0x3D, 0xCC,
            //		0xB6, 0x53, 0x26, 0x8E, 0x51, 0x2F, 0x5E, 0xDD,
            //		0xE4, 0x1A, 0x5D, 0xB3, 0x58, 0x3C, 0xDF, 0x60,
            //		0x68, 0xF2, 0x48, 0xA2, 0xB0, 0xB8, 0xDE, 0x7B,
            //		0xC9, 0xAA, 0x20, 0xE3, 0xCF, 0x63, 0xDF, 0x5F,
            //		0x39, 0x55, 0x21, 0xE0, 0xA0, 0xDD, 0x85, 0x3E,
            //		0x0A, 0xAF, 0x44, 0xFA, 0x49, 0x3C, 0xD5, 0x4C,
            //		0xA8, 0x04, 0x8D, 0x1D, 0x9C, 0x41, 0x85, 0xFB
            //	};
            //
            // BYTE bEncryptionParamSet[] = {
            //		0x30, 0x09, // SEQUENCE (размер 0x09)
            //		0x06, 0x07, // OBJECT IDENTIFIER,  (размер 0x07)
            //		0x2a, 0x85, 0x03, 0x02, 0x02, 0x1f, 0x01 // 1.2.643.2.2.31.1
            //	};
            //  -=SIMPLEBLOB=-
            //	BYTE bSimpleBlob[] =
            //	{
            //		0x01, // bType = SIMPLEBLOB
            //      0x20, // bVersion = 0x20
            //      0x00, 0x00, // reserved
            //      0x23, 0x2e, 0x00, 0x00, // KeyAlg = ALG_SID_GR3410EL
            //      0x4d, 0x41, 0x47, 0x31, // Magic = GR3410_1_MAGIC
            //      0x1e, 0x66, 0x00, 0x00, // EncryptKeyAlgId = CALG_G28147
            //      0x76, 0xee, 0xb4, 0x6b, 0x1b, 0x10, 0x36, 0xeb, // bUKM
            //      // pbEncryptedKey
            //      0x5e, 0x70, 0x73, 0x5f, 0x36, 0x98, 0xb4, 0x35,
            //		0x5b, 0x45, 0x03, 0x7f, 0xa7, 0xce, 0x00, 0x97,
            //		0x11, 0x5e, 0x45, 0xc6, 0x58, 0x59, 0x94, 0x72,
            //		0x66, 0x42, 0x06, 0x3f, 0x72, 0x3a, 0xb4, 0x9e,
            //		0x8c, 0x86, 0x08, 0x84, // pbMacKey
            //      0x30, 0x09, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x1f, 0x01 // bEncryptionParamSet
            //  };

            Gost2012_256KeyExchangeDeformatter Deformatter = new Gost2012_256KeyExchangeDeformatter(assym);
            GostKeyTransport encKey = new GostKeyTransport();

            //0- 31 2E 32 2E 36 34 33 2E 37 2E 31 2E 32 2E 35 2E 31 2E 31 00
            //1- 0A 20 00 00 49 2E 00 00 4D 41 47 31 00 02 00 00 30 13 06 07 2A 85 03 02 02 24 00 06 08 2A 85 03 07 01 01 02 02 8B FF 19 01 0B CF BB C9 03 59 58 D0 6F 24 C1 3C 5D 1F AC 9B F8 F7 24 7B 48 4E 39 2E 9A 42 B6 66 60 CA D8 0E 62 7E 22 15 CC C9 E5 A6 2E 58 FF 9B 1D FB EA 7B 5E 42 B5 FD 51 97 BD D9 6E 24 16 AC
            //
            //0A PUBLICKEYBLOBEX
            //20 Version
            //00 00 Reserved
            //49 2E 00 00 // KeyAlg = ???
            //4D 41 47 31 // Magic = GR3410_1_MAGIC
            //00 02 00 00 // EncryptKeyAlgId
            //30 ???
            //13 Length for Oids
            //06 07 2A 85 03 02 02 24 00 // OId ??? 1.2.643.2.2.36.0 PublicKeyParamSet
            //06 08 2A 85 03 07 01 01 02 02 // OId ??? 1.2.643.7.1.1.2.2 DigestParamSet
            //8B FF 19 01 0B CF BB C9 //PublicKey
            //03 59 58 D0 6F 24 C1 3C
            //5D 1F AC 9B F8 F7 24 7B
            //48 4E 39 2E 9A 42 B6 66
            //60 CA D8 0E 62 7E 22 15
            //CC C9 E5 A6 2E 58 FF 9B
            //1D FB EA 7B 5E 42 B5 FD
            //51 97 BD D9 6E 24 16 AC
            //
            //2- 01 20 00 00 1E 66 00 00 FD 51 4A 37 1E 66 00 00 6A 0F 44 24 B6 CB 8B 7C 91 8B D1 55 2D 7D 07 67 6F 03 42 8E DC BE D0 9B 84 BA 8E 04 E7 FA 3A 2A 9B 2C F6 F1 71 86 3D F6 4E 32 52 65 30 09 06 07 2A 85 03 02 02 1F 01"
            //
            //01 SIMPLEBLOB
            //20 Version
            //00 00 Reserved
            //1E 66 00 00 KeyAlg
            //FD 51 4A 37 Magic
            //1E 66 00 00 EncryptKeyAlgId
            //6A 0F 44 24 B6 CB 8B 7C UKM
            //91 8B D1 55 2D 7D 07 67 EncryptedKey
            //6F 03 42 8E DC BE D0 9B
            //84 BA 8E 04 E7 FA 3A 2A
            //9B 2C F6 F1 71 86 3D F6
            //4E 32 52 65 MacKey
            //30 09 06 07 2A 85 03 02 02 1F 01 EncryptionParamSet
            encKey.SessionEncryptedKey.Ukm                = new byte[] { 0x6A, 0x0F, 0x44, 0x24, 0xB6, 0xCB, 0x8B, 0x7C };
            encKey.SessionEncryptedKey.EncryptedKey       = new byte[] { 0x91, 0x8B, 0xD1, 0x55, 0x2D, 0x7D, 0x07, 0x67, 0x6F, 0x03, 0x42, 0x8E, 0xDC, 0xBE, 0xD0, 0x9B, 0x84, 0xBA, 0x8E, 0x04, 0xE7, 0xFA, 0x3A, 0x2A, 0x9B, 0x2C, 0xF6, 0xF1, 0x71, 0x86, 0x3D, 0xF6 };
            encKey.SessionEncryptedKey.Mac                = new byte[] { 0x4E, 0x32, 0x52, 0x65 };
            encKey.SessionEncryptedKey.EncryptionParamSet = "1.2.643.2.2.31.1";
            encKey.TransportParameters.DigestParamSet     = "1.2.643.7.1.1.2.2";
            encKey.TransportParameters.PublicKey          = new byte[] { 0x8B, 0xFF, 0x19, 0x01, 0x0B, 0xCF, 0xBB, 0xC9, 0x03, 0x59, 0x58, 0xD0, 0x6F, 0x24, 0xC1, 0x3C, 0x5D, 0x1F, 0xAC, 0x9B, 0xF8, 0xF7, 0x24, 0x7B, 0x48, 0x4E, 0x39, 0x2E, 0x9A, 0x42, 0xB6, 0x66, 0x60, 0xCA, 0xD8, 0x0E, 0x62, 0x7E, 0x22, 0x15, 0xCC, 0xC9, 0xE5, 0xA6, 0x2E, 0x58, 0xFF, 0x9B, 0x1D, 0xFB, 0xEA, 0x7B, 0x5E, 0x42, 0xB5, 0xFD, 0x51, 0x97, 0xBD, 0xD9, 0x6E, 0x24, 0x16, 0xAC };
            encKey.TransportParameters.PublicKeyParamSet  = "1.2.643.2.2.36.0";

            Gost28147 key = (Gost28147)Deformatter.DecryptKeyExchange(encKey);

            key.IV = sessionKeyIV.Split(' ').Select(c => Convert.ToByte(c, 16)).ToArray();
            //byte[] encBytes = Enumerable.Range(0, dataEncrypted.Length)
            //					.Where(x => x % 2 == 0)
            //					.Select(x => Convert.ToByte(dataEncrypted.Substring(x, 2), 16))
            //					.ToArray();
            byte[] encBytes = Convert.FromBase64String(dataEncrypted);

            byte[] targetBytes     = new byte[1024];
            int    currentPosition = 0;

            CPCryptoAPITransform cryptoTransform =
                (CPCryptoAPITransform)key.CreateDecryptor();

            int inputBlockSize   = cryptoTransform.InputBlockSize;
            int sourceByteLength = encBytes.Length;

            try
            {
                int numBytesRead = 0;
                while (sourceByteLength - currentPosition >= inputBlockSize)
                {
                    numBytesRead = cryptoTransform.TransformBlock(
                        encBytes,
                        currentPosition,
                        inputBlockSize,
                        targetBytes,
                        currentPosition);

                    currentPosition += numBytesRead;
                }

                byte[] finalBytes = cryptoTransform.TransformFinalBlock(
                    encBytes,
                    currentPosition,
                    sourceByteLength - currentPosition);

                finalBytes.CopyTo(targetBytes, currentPosition);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Caught unexpected exception:" + ex.ToString());
            }
            byte[] retVal = TrimArray(targetBytes);
            return(retVal);
        }