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); } }
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); } }
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()); }
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); } }
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))) )); }
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)); }