コード例 #1
0
        static void Main(string[] args)
        {
            string file = null, pin = null, defenceFile = null;
            Mode   mode     = Mode.Private;
            bool   showHelp = false;

            options = new OptionSet {
                { "f|file=", "Путь к контейнеру", f => file = f },
                { "d|defence=", "Путь к вспомогательному контейнеру секретного ключа", f => defenceFile = f },
                { "private", "Извлечь закрытый ключ (по умолчанию)", p => { if (p != null)
                                                                            {
                                                                                mode = Mode.Private;
                                                                            }
                  } },
                { "cert", "Извлечь сертификат", c => { if (c != null)
                                                       {
                                                           mode = Mode.Certificate;
                                                       }
                  } },
                { "p|pin=", "ПИН-код", p => pin = p },
                { "h|help", "Помощь", h => showHelp = h != null }
            };

            try {
                options.Parse(args);
            } catch (OptionException e) {
                Console.Error.WriteLine(e.Message);
                return;
            }

            if (showHelp || String.IsNullOrEmpty(file))
            {
                PrintHelp();
                return;
            }

            IExport export;

            if (mode == Mode.Certificate)
            {
                export = new CertificateExport();
            }
            else
            {
                export = new PrivateKeyExport();
            }

            try {
                var container = VipNetContainer.LoadFromFile(file);
                var defence   = defenceFile != null?VipNetContainer.LoadFromFile(defenceFile) : null;

                export.Export(container, defence, pin, Console.OpenStandardOutput());
            } catch (Exception e) {
                Console.Error.WriteLine(e.Message);
            }
        }
コード例 #2
0
ファイル: Export.cs プロジェクト: vitalif/vipnet-extract-data
        public void Export(VipNetContainer container, VipNetContainer defence, string pin, Stream output)
        {
            var privateKey = EncodePrivateKey(container, defence, pin);
            var pemObject  = new PemObject("PRIVATE KEY", privateKey.GetDerEncoded());

            using (var sw = new StreamWriter(output)) {
                var writer = new PemWriter(sw);
                writer.WriteObject(pemObject);
            }
        }
コード例 #3
0
        private byte[] GetDecryptionKey(string pin, VipNetContainer defence)
        {
            var passwordData = Encoding.ASCII.GetBytes(pin ?? "");

            if (DefenceKeyInfo.KeyClass.Value.IntValue == 64 && DefenceKeyInfo.KeyType.Value.IntValue == 24622)
            {
                // Контейнер зашифрован ключом, лежащим в ещё одном контейнере
                if (defence == null)
                {
                    throw new CryptographicException("Закрытый ключ зашифрован секретным ключом, расположенным в отдельном вспомогательном контейнере. Используйте опцию --defence");
                }
                return(defence.Entries[0].GetProtectionKey(pin));
            }
            if (DefenceKeyInfo.Algorithm != null &&
                DefenceKeyInfo.Algorithm.Algorithm.Equals(PkcsObjectIdentifiers.IdPbkdf2))
            {
                // PBKDF2 используется в контейнерах ViPNet Jcrypto SDK
                // Самое смешное, что сам десктопный ViPNet CSP не понимает такие контейнеры
                // А мы понимаем!
                var p = Pbkdf2Params.GetInstance(DefenceKeyInfo.Algorithm.Parameters);
                return(PBKDF2(
                           MacUtilities.GetMac(p.Prf.Algorithm),
                           passwordData,
                           p.GetSalt(),
                           p.IterationCount.IntValue,
                           p.KeyLength.IntValue
                           ));
            }
            var digest        = new Gost3411Digest();
            var keyData       = new byte[digest.GetDigestSize()];
            var unwrappingKey = new byte[digest.GetDigestSize()];

            digest.BlockUpdate(passwordData, 0, passwordData.Length);
            digest.DoFinal(keyData, 0);
            digest.Reset();

            var secodeData = passwordData.Concat(keyData).ToArray();

            digest.BlockUpdate(secodeData, 0, secodeData.Length);
            digest.DoFinal(unwrappingKey, 0);

            var tmp = new int[keyData.Length / 4];

            for (int i = 0; i < keyData.Length; i += 4)
            {
                tmp[i / 4] = BitConverter.ToInt32(keyData, i) - BitConverter.ToInt32(unwrappingKey, i);
            }

            return(tmp.SelectMany(x => BitConverter.GetBytes(x)).ToArray());
        }
コード例 #4
0
ファイル: Export.cs プロジェクト: vitalif/vipnet-extract-data
        public void Export(VipNetContainer container, VipNetContainer defence, string pin, Stream output)
        {
            var cert = container.Entries[0].Certificate;

            if (cert == null)
            {
                throw new InvalidOperationException("Контейнер не содержит сертификата");
            }

            var pemObject = new PemObject("CERTIFICATE", cert.GetEncoded());

            using (var sw = new StreamWriter(output)) {
                var writer = new PemWriter(sw);
                writer.WriteObject(pemObject);
            }
        }
コード例 #5
0
ファイル: Export.cs プロジェクト: vitalif/vipnet-extract-data
        private static Asn1Object EncodePrivateKey(VipNetContainer container, VipNetContainer defence, string pin)
        {
            var entry      = container.Entries[0];
            var gostParams = Gost3410PublicKeyAlgParameters.GetInstance(entry.KeyInfo.Algorithm.Parameters);

            return(new DerSequence(
                       new DerInteger(0),
                       new DerSequence(
                           entry.KeyInfo.Algorithm.Algorithm,
                           new DerSequence(
                               gostParams.PublicKeyParamSet,
                               gostParams.DigestParamSet
                               )
                           ),
                       new DerOctetString(new DerInteger(entry.GetPrivateKey(pin, defence)))
                       ));
        }
コード例 #6
0
        public BigInteger GetPrivateKey(string pin, VipNetContainer defence)
        {
            var cek    = KeyBlock.Take(KeyBlock.Length - 12).ToArray();
            var mac    = KeyBlock.Skip(cek.Length).Take(4).ToArray();
            var data   = cek.Concat(KeyInfo.RawData).ToArray();
            var pinKey = GetDecryptionKey(pin, defence);

            CheckMac(pinKey, cek, data, mac);

            var iv         = KeyBlock.Skip(KeyBlock.Length - 8).ToArray();
            var pkeyMasked = DecryptKey(pinKey, cek, iv);

            byte[] privateKey;
            if (KeyInfo.KeyClass.Value.And(BigInteger.Three).Equals(BigInteger.Zero))
            {
                data = pkeyMasked.Take(pkeyMasked.Length / 2).ToArray();
                var unwrappingKey = pkeyMasked.Skip(pkeyMasked.Length / 2).ToArray();
                privateKey = DecryptKey(unwrappingKey, data);
            }
            else
            {
                var wrapped = pkeyMasked.Take(pkeyMasked.Length / 2).Reverse().ToArray();
                var mask    = pkeyMasked.Skip(pkeyMasked.Length / 2).Reverse().ToArray();

                var algParams = Gost3410PublicKeyAlgParameters.GetInstance(KeyInfo.Algorithm.Parameters);
                var param     = new ECKeyGenerationParameters(algParams.PublicKeyParamSet, new SecureRandom());

                var x = new BigInteger(1, wrapped);
                var y = new BigInteger(1, mask);
                var z = x.Multiply(y).Mod(param.DomainParameters.Curve.Order);

                CheckPrivateKey(param, z);

                privateKey = z.ToByteArrayUnsigned();
            }

            return(new BigInteger(1, privateKey));
        }