Beispiel #1
0
        public void OnData(byte[] data, int offset, int length)
        {
            _buffer.Write(data, offset, length);
            int expectedLength = SSHUtil.ReadInt32(_buffer.UnderlyingBuffer, 0);

            if (expectedLength + 4 <= _buffer.Length)
            {
                SSH2DataReader        r  = new SSH2DataReader(new DataFragment(_buffer.UnderlyingBuffer, 4, _buffer.Length - 4));
                AgentForwadPacketType pt = (AgentForwadPacketType)r.ReadByte();
                //remaining len-1
                _buffer.SetOffset(0);

                switch (pt)
                {
                case AgentForwadPacketType.SSH2_AGENTC_REQUEST_IDENTITIES:
                    SendKeyList();
                    break;

                case AgentForwadPacketType.SSH2_AGENTC_SIGN_REQUEST:
                    SendSign(r);
                    break;

                default:
                    //Debug.WriteLine("Unknown agent packet " + pt.ToString());
                    TransmitWriter(OpenWriter(AgentForwadPacketType.SSH_AGENT_FAILURE));
                    break;
                }
            }
        }
Beispiel #2
0
        internal static RSAPublicKey ReadFrom(SSH2DataReader reader)
        {
            BigInteger exp = reader.ReadMPInt();
            BigInteger mod = reader.ReadMPInt();

            return(new RSAPublicKey(exp, mod));
        }
Beispiel #3
0
        private void SendSign(SSH2DataReader r)
        {
            byte[] blob = r.ReadString();
            byte[] data = r.ReadString();
            //Debug.WriteLine(String.Format("SignRequest blobsize={0} datasize={1}", blob.Length, data.Length));

            SSH2UserAuthKey[] keys = _client.GetAvailableSSH2UserAuthKeys();
            SSH2UserAuthKey   key  = FindKey(keys, blob);

            if (key == null)
            {
                TransmitWriter(OpenWriter(AgentForwadPacketType.SSH_AGENT_FAILURE));
                _client.NotifyPublicKeyDidNotMatch();
            }
            else
            {
                SSH2DataWriter signpack = new SSH2DataWriter();
                signpack.WriteString(SSH2Util.PublicKeyAlgorithmName(key.Algorithm));
                signpack.WriteAsString(key.Sign(data));

                SSH2DataWriter wr = OpenWriter(AgentForwadPacketType.SSH2_AGENT_SIGN_RESPONSE);
                wr.WriteAsString(signpack.ToByteArray());
                TransmitWriter(wr);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Reads a multiple precision integer.
        /// </summary>
        /// <returns>a multiple precision integer</returns>
        private BigInteger ReadBigIntWithBits(SSH2DataReader reader)
        {
            int bits  = reader.ReadInt32();
            int bytes = (bits + 7) / 8;

            byte[] biData = reader.Read(bytes);
            return(new BigInteger(biData));
        }
Beispiel #5
0
        internal static DSAPublicKey ReadFrom(SSH2DataReader reader)
        {
            BigInteger p = reader.ReadMPInt();
            BigInteger q = reader.ReadMPInt();
            BigInteger g = reader.ReadMPInt();
            BigInteger y = reader.ReadMPInt();

            return(new DSAPublicKey(p, g, q, y));
        }
Beispiel #6
0
        internal static EDDSAPublicKey ReadFrom(PublicKeyAlgorithm algorithm, SSH2DataReader reader)
        {
            EdwardsCurve curve = EdwardsCurve.FindByAlgorithm(algorithm);

            if (curve == null)
            {
                throw new SSHException(Strings.GetString("UnsupportedEllipticCurve"));
            }

            byte[] q = reader.ReadByteString();
            return(new EDDSAPublicKey(curve, q));
        }
        /// <summary>
        /// Read PuTTY SSH2 private key parameters.
        /// </summary>
        /// <param name="passphrase">passphrase for decrypt the key file</param>
        /// <param name="keyPair">key pair</param>
        /// <param name="comment">comment or empty if it didn't exist</param>
        public void Load(string passphrase, out KeyPair keyPair, out string comment)
        {
            if (keyFile == null)
            {
                throw new SSHException("A key file is not loaded yet");
            }

            int             version;
            string          keyTypeName;
            KeyType         keyType;
            string          encryptionName;
            CipherAlgorithm?encryption;

            byte[] publicBlob;
            byte[] privateBlob;
            string privateMac;
            string privateHash;

            using (StreamReader sreader = GetStreamReader()) {
                //*** Read header and key type
                ReadHeaderLine(sreader, out version, out keyTypeName);

                if (keyTypeName == "ssh-rsa")
                {
                    keyType = KeyType.RSA;
                }
                else if (keyTypeName == "ssh-dss")
                {
                    keyType = KeyType.DSA;
                }
                else
                {
                    throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (unexpected key type)");
                }

                //*** Read encryption
                ReadItemLine(sreader, "Encryption", out encryptionName);

                if (encryptionName == "aes256-cbc")
                {
                    encryption = CipherAlgorithm.AES256;
                }
                else if (encryptionName == "none")
                {
                    encryption = null;
                }
                else
                {
                    throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (unexpected encryption)");
                }

                //*** Read comment
                ReadItemLine(sreader, "Comment", out comment);

                //*** Read public lines
                string publicLinesStr;
                ReadItemLine(sreader, "Public-Lines", out publicLinesStr);
                int publicLines;
                if (!Int32.TryParse(publicLinesStr, out publicLines) || publicLines < 0)
                {
                    throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (invalid public lines)");
                }

                ReadBlob(sreader, publicLines, out publicBlob);

                //*** Read private lines
                string privateLinesStr;
                ReadItemLine(sreader, "Private-Lines", out privateLinesStr);
                int privateLines;
                if (!Int32.TryParse(privateLinesStr, out privateLines) || privateLines < 0)
                {
                    throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (invalid private lines)");
                }

                ReadBlob(sreader, privateLines, out privateBlob);

                //*** Read private MAC
                ReadPrivateMACLine(sreader, version, out privateMac, out privateHash);
            }

            if (encryption.HasValue)
            {
                byte[] key    = PuTTYPassphraseToKey(passphrase);
                byte[] iv     = new byte[16];
                Cipher cipher = CipherFactory.CreateCipher(SSHProtocol.SSH2, encryption.Value, key, iv);
                if (privateBlob.Length % cipher.BlockSize != 0)
                {
                    throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (invalid key data size)");
                }
                cipher.Decrypt(privateBlob, 0, privateBlob.Length, privateBlob, 0);
            }

            bool verified = Verify(version, privateMac, privateHash,
                                   passphrase, keyTypeName, encryptionName, comment, publicBlob, privateBlob);

            if (!verified)
            {
                if (encryption.HasValue)
                {
                    throw new SSHException(Strings.GetString("WrongPassphrase"));
                }
                else
                {
                    throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (HMAC verification failed)");
                }
            }

            if (keyType == KeyType.RSA)
            {
                SSH2DataReader reader = new SSH2DataReader(publicBlob);
                byte[]         magic  = reader.ReadString();
                if (!ByteArrayUtil.AreEqual(magic, Encoding.ASCII.GetBytes("ssh-rsa")))
                {
                    throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (missing magic)");
                }

                BigInteger e = reader.ReadMPInt();
                BigInteger n = reader.ReadMPInt();

                reader = new SSH2DataReader(privateBlob);
                BigInteger d    = reader.ReadMPInt();
                BigInteger p    = reader.ReadMPInt();
                BigInteger q    = reader.ReadMPInt();
                BigInteger iqmp = reader.ReadMPInt();

                BigInteger u = p.modInverse(q);

                keyPair = new RSAKeyPair(e, d, n, u, p, q);
            }
            else if (keyType == KeyType.DSA)
            {
                SSH2DataReader reader = new SSH2DataReader(publicBlob);
                byte[]         magic  = reader.ReadString();
                if (!ByteArrayUtil.AreEqual(magic, Encoding.ASCII.GetBytes("ssh-dss")))
                {
                    throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (missing magic)");
                }

                BigInteger p = reader.ReadMPInt();
                BigInteger q = reader.ReadMPInt();
                BigInteger g = reader.ReadMPInt();
                BigInteger y = reader.ReadMPInt();

                reader = new SSH2DataReader(privateBlob);
                BigInteger x = reader.ReadMPInt();

                keyPair = new DSAKeyPair(p, g, q, y, x);
            }
            else
            {
                throw new SSHException("Unknown file type. This should not happen.");
            }
        }
        /// <summary>
        /// Read SSH.com SSH2 private key parameters.
        /// </summary>
        /// <param name="passphrase">passphrase for decrypt the key file</param>
        /// <param name="keyPair">key pair</param>
        /// <param name="comment">comment or empty if it didn't exist</param>
        /// <exception cref="SSHException">failed to parse</exception>
        public void Load(string passphrase, out KeyPair keyPair, out string comment)
        {
            if (keyFile == null)
            {
                throw new SSHException("A key file is not loaded yet");
            }

            String base64Text;

            using (StreamReader sreader = GetStreamReader()) {
                string line = sreader.ReadLine();
                if (line == null || line != PrivateKeyFileHeader.SSH2_SSHCOM_HEADER)
                {
                    throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (missing header)");
                }

                StringBuilder buf = new StringBuilder();
                comment = String.Empty;
                while (true)
                {
                    line = sreader.ReadLine();
                    if (line == null)
                    {
                        throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (unexpected eof)");
                    }
                    if (line == PrivateKeyFileHeader.SSH2_SSHCOM_FOOTER)
                    {
                        break;
                    }
                    if (line.IndexOf(':') >= 0)
                    {
                        if (line.StartsWith("Comment: "))
                        {
                            comment = line.Substring("Comment: ".Length);
                        }
                    }
                    else if (line[line.Length - 1] == '\\')
                    {
                        buf.Append(line, 0, line.Length - 1);
                    }
                    else
                    {
                        buf.Append(line);
                    }
                }
                base64Text = buf.ToString();
            }

            byte[] keydata = Base64.Decode(Encoding.ASCII.GetBytes(base64Text));
            //Debug.WriteLine(DebugUtil.DumpByteArray(keydata));

            SSH2DataReader reader = new SSH2DataReader(keydata);
            int            magic  = reader.ReadInt32();

            if (magic != MAGIC)
            {
                throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (magic code unmatched)");
            }
            int    privateKeyLen = reader.ReadInt32();
            string type          = Encoding.ASCII.GetString(reader.ReadString());

            string ciphername = Encoding.ASCII.GetString(reader.ReadString());
            int    bufLen     = reader.ReadInt32();

            if (ciphername != "none")
            {
                CipherAlgorithm algo = CipherFactory.SSH2NameToAlgorithm(ciphername);
                byte[]          key  = SSH2UserAuthKey.PassphraseToKey(passphrase, CipherFactory.GetKeySize(algo));
                Cipher          c    = CipherFactory.CreateCipher(SSHProtocol.SSH2, algo, key);
                byte[]          tmp  = new Byte[reader.Image.Length - reader.Offset];
                c.Decrypt(reader.Image, reader.Offset, reader.Image.Length - reader.Offset, tmp, 0);
                reader = new SSH2DataReader(tmp);
            }

            int parmLen = reader.ReadInt32();

            if (parmLen < 0 || parmLen > reader.Rest)
            {
                throw new SSHException(Strings.GetString("WrongPassphrase"));
            }

            if (type.IndexOf("if-modn") != -1)
            {
                //mindterm mistaken this order of BigIntegers
                BigInteger e = reader.ReadBigIntWithBits();
                BigInteger d = reader.ReadBigIntWithBits();
                BigInteger n = reader.ReadBigIntWithBits();
                BigInteger u = reader.ReadBigIntWithBits();
                BigInteger p = reader.ReadBigIntWithBits();
                BigInteger q = reader.ReadBigIntWithBits();
                keyPair = new RSAKeyPair(e, d, n, u, p, q);
            }
            else if (type.IndexOf("dl-modp") != -1)
            {
                if (reader.ReadInt32() != 0)
                {
                    throw new SSHException(Strings.GetString("UnsupportedPrivateKeyFormat")
                                           + " (" + Strings.GetString("Reason_UnsupportedDSAKeyFormat") + ")");
                }
                BigInteger p = reader.ReadBigIntWithBits();
                BigInteger g = reader.ReadBigIntWithBits();
                BigInteger q = reader.ReadBigIntWithBits();
                BigInteger y = reader.ReadBigIntWithBits();
                BigInteger x = reader.ReadBigIntWithBits();
                keyPair = new DSAKeyPair(p, g, q, y, x);
            }
            else
            {
                throw new SSHException(Strings.GetString("UnsupportedAuthenticationMethod"));
            }
        }
Beispiel #9
0
        /*
         * Format style note
         *  ---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----
         *  Comment: *******
         *  <base64-encoded body>
         *  ---- END SSH2 ENCRYPTED PRIVATE KEY ----
         *
         *  body = MAGIC_VAL || body-length || type(string) || encryption-algorithm-name(string) || encrypted-body(string)
         *  encrypted-body = array of BigInteger(algorithm-specific)
         */
#if !PODEROSA_KEYFORMAT
        public static SSH2UserAuthKey FromSECSHStyleStream(Stream strm, string passphrase)
        {
            StreamReader r = new StreamReader(strm, Encoding.ASCII);
            string       l = r.ReadLine();

            if (l == null || l != "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----")
            {
                throw new SSHException("Wrong key format");
            }

            string comment = "";

            l = r.ReadLine();
            StringBuilder buf = new StringBuilder();

            while (l != "---- END SSH2 ENCRYPTED PRIVATE KEY ----")
            {
                if (l.IndexOf(':') == -1)
                {
                    buf.Append(l);
                }
                else if (l[l.Length - 1] == '\\')
                {
                    buf.Append(l, 0, l.Length - 1);
                }
                else if (l.StartsWith("Comment: "))
                {
                    comment = l.Substring("Comment: ".Length);
                }

                l = r.ReadLine();
                if (l == null)
                {
                    throw new SSHException("Key is broken");
                }
            }
            r.Close();

            byte[] keydata = Base64.Decode(Encoding.ASCII.GetBytes(buf.ToString()));
            //Debug.WriteLine(DebugUtil.DumpByteArray(keydata));


            SSH2DataReader re    = new SSH2DataReader(keydata);
            int            magic = re.ReadInt32();

            if (magic != MAGIC_VAL)
            {
                throw new SSHException("key file is broken");
            }
            int    privateKeyLen = re.ReadInt32();
            string type          = Encoding.ASCII.GetString(re.ReadString());

            string ciphername = Encoding.ASCII.GetString(re.ReadString());
            int    bufLen     = re.ReadInt32();

            if (ciphername != "none")
            {
                CipherAlgorithm algo = CipherFactory.SSH2NameToAlgorithm(ciphername);
                byte[]          key  = PassphraseToKey(passphrase, CipherFactory.GetKeySize(algo));
                Cipher          c    = CipherFactory.CreateCipher(SSHProtocol.SSH2, algo, key);
                byte[]          tmp  = new Byte[re.Image.Length - re.Offset];
                c.Decrypt(re.Image, re.Offset, re.Image.Length - re.Offset, tmp, 0);
                re = new SSH2DataReader(tmp);
            }

            int parmLen = re.ReadInt32();

            if (parmLen < 0 || parmLen > re.Rest)
            {
                throw new SSHException(Strings.GetString("WrongPassphrase"));
            }

            if (type.IndexOf("if-modn") != -1)
            {
                //mindterm mistaken this order of BigIntegers
                BigInteger e = re.ReadBigIntWithBits();
                BigInteger d = re.ReadBigIntWithBits();
                BigInteger n = re.ReadBigIntWithBits();
                BigInteger u = re.ReadBigIntWithBits();
                BigInteger p = re.ReadBigIntWithBits();
                BigInteger q = re.ReadBigIntWithBits();
                return(new SSH2UserAuthKey(new RSAKeyPair(e, d, n, u, p, q), comment));
            }
            else if (type.IndexOf("dl-modp") != -1)
            {
                if (re.ReadInt32() != 0)
                {
                    throw new SSHException("DSS Private Key File is broken");
                }
                BigInteger p = re.ReadBigIntWithBits();
                BigInteger g = re.ReadBigIntWithBits();
                BigInteger q = re.ReadBigIntWithBits();
                BigInteger y = re.ReadBigIntWithBits();
                BigInteger x = re.ReadBigIntWithBits();
                return(new SSH2UserAuthKey(new DSAKeyPair(p, g, q, y, x), comment));
            }
            else
            {
                throw new SSHException("unknown authentication method " + type);
            }
        }
Beispiel #10
0
        public static SSH2UserAuthKey FromByteArray(byte[] keydata, string passphrase)
        {
            SSH2DataReader re    = new SSH2DataReader(keydata);
            int            magic = re.ReadInt32();

            if (magic != MAGIC_VAL)
            {
                throw new SSHException("key file is broken");
            }
            int    privateKeyLen = re.ReadInt32();
            string type          = Encoding.ASCII.GetString(re.ReadString());

            string ciphername = Encoding.ASCII.GetString(re.ReadString());
            int    bufLen     = re.ReadInt32();

            if (ciphername != "none")
            {
                CipherAlgorithm algo = CipherFactory.SSH2NameToAlgorithm(ciphername);
                byte[]          key  = PassphraseToKey(passphrase, CipherFactory.GetKeySize(algo));
                Cipher          c    = CipherFactory.CreateCipher(SSHProtocol.SSH2, algo, key);
                byte[]          tmp  = new Byte[re.Image.Length - re.Offset];
                c.Decrypt(re.Image, re.Offset, re.Image.Length - re.Offset, tmp, 0);
                re = new SSH2DataReader(tmp);
            }

            int parmLen = re.ReadInt32();

            if (parmLen < 0 || parmLen > re.Rest)
            {
                throw new SSHException(Strings.GetString("WrongPassphrase"));
            }

            if (type.IndexOf("if-modn") != -1)
            {
                //mindterm mistaken this order of BigIntegers
                BigInteger e = re.ReadBigIntWithBits();
                BigInteger d = re.ReadBigIntWithBits();
                BigInteger n = re.ReadBigIntWithBits();
                BigInteger u = re.ReadBigIntWithBits();
                BigInteger p = re.ReadBigIntWithBits();
                BigInteger q = re.ReadBigIntWithBits();
                return(new SSH2UserAuthKey(new RSAKeyPair(e, d, n, u, p, q)));
            }
            else if (type.IndexOf("dl-modp") != -1)
            {
                if (re.ReadInt32() != 0)
                {
                    throw new SSHException("DSS Private Key File is broken");
                }
                BigInteger p = re.ReadBigIntWithBits();
                BigInteger g = re.ReadBigIntWithBits();
                BigInteger q = re.ReadBigIntWithBits();
                BigInteger y = re.ReadBigIntWithBits();
                BigInteger x = re.ReadBigIntWithBits();
                return(new SSH2UserAuthKey(new DSAKeyPair(p, g, q, y, x)));
            }
            else
            {
                throw new SSHException("unknown authentication method " + type);
            }
        }
Beispiel #11
0
        /// <summary>
        /// Read PuTTY SSH2 private key parameters.
        /// </summary>
        /// <param name="passphrase">passphrase for decrypt the key file</param>
        /// <param name="keyPair">key pair</param>
        /// <param name="comment">comment or empty if it didn't exist</param>
        public void Load(string passphrase, out KeyPair keyPair, out string comment)
        {
            if (keyFile == null)
            {
                throw new SSHException("A key file is not loaded yet");
            }

            int             version;
            string          keyTypeName;
            KeyType         keyType;
            string          encryptionName;
            CipherAlgorithm?encryption;

            byte[] publicBlob;
            byte[] privateBlob;
            string privateMac;
            string privateHash;

            using (StreamReader sreader = GetStreamReader())
            {
                //*** Read header and key type
                ReadHeaderLine(sreader, out version, out keyTypeName);

                if (keyTypeName == "ssh-rsa")
                {
                    keyType = KeyType.RSA;
                }
                else if (keyTypeName == "ssh-dss")
                {
                    keyType = KeyType.DSA;
                }
                else if (keyTypeName.StartsWith("ecdsa-sha2-"))
                {
                    keyType = KeyType.ECDSA;
                }
                else if (keyTypeName == "ssh-ed25519")
                {
                    keyType = KeyType.ED25519;
                }
                else
                {
                    throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (unexpected key type)");
                }

                //*** Read encryption
                ReadItemLine(sreader, "Encryption", out encryptionName);

                if (encryptionName == "aes256-cbc")
                {
                    encryption = CipherAlgorithm.AES256;
                }
                else if (encryptionName == "none")
                {
                    encryption = null;
                    passphrase = "";    // prevent HMAC error
                }
                else
                {
                    throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (unexpected encryption)");
                }

                //*** Read comment
                ReadItemLine(sreader, "Comment", out comment);

                //*** Read public lines
                string publicLinesStr;
                ReadItemLine(sreader, "Public-Lines", out publicLinesStr);
                int publicLines;
                if (!Int32.TryParse(publicLinesStr, out publicLines) || publicLines < 0)
                {
                    throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (invalid public lines)");
                }

                ReadBlob(sreader, publicLines, out publicBlob);

                //*** Read private lines
                string privateLinesStr;
                ReadItemLine(sreader, "Private-Lines", out privateLinesStr);
                int privateLines;
                if (!Int32.TryParse(privateLinesStr, out privateLines) || privateLines < 0)
                {
                    throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (invalid private lines)");
                }

                ReadBlob(sreader, privateLines, out privateBlob);

                //*** Read private MAC
                ReadPrivateMACLine(sreader, version, out privateMac, out privateHash);
            }

            if (encryption.HasValue)
            {
                byte[] key    = PuTTYPassphraseToKey(passphrase);
                byte[] iv     = new byte[16];
                Cipher cipher = CipherFactory.CreateCipher(SSHProtocol.SSH2, encryption.Value, key, iv);
                if (privateBlob.Length % cipher.BlockSize != 0)
                {
                    throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (invalid key data size)");
                }
                cipher.Decrypt(privateBlob, 0, privateBlob.Length, privateBlob, 0);
            }

            bool verified = Verify(version, privateMac, privateHash,
                                   passphrase, keyTypeName, encryptionName, comment, publicBlob, privateBlob);

            if (!verified)
            {
                if (encryption.HasValue)
                {
                    throw new SSHException(Strings.GetString("WrongPassphrase"));
                }
                else
                {
                    throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (HMAC verification failed)");
                }
            }

            if (keyType == KeyType.RSA)
            {
                SSH2DataReader reader = new SSH2DataReader(publicBlob);
                string         magic  = reader.ReadString();
                if (magic != "ssh-rsa")
                {
                    throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (missing magic)");
                }

                BigInteger e = reader.ReadMPInt();
                BigInteger n = reader.ReadMPInt();

                reader = new SSH2DataReader(privateBlob);
                BigInteger d    = reader.ReadMPInt();
                BigInteger p    = reader.ReadMPInt();
                BigInteger q    = reader.ReadMPInt();
                BigInteger iqmp = reader.ReadMPInt();

                BigInteger u = p.ModInverse(q);

                keyPair = new RSAKeyPair(e, d, n, u, p, q);
            }
            else if (keyType == KeyType.DSA)
            {
                SSH2DataReader reader = new SSH2DataReader(publicBlob);
                string         magic  = reader.ReadString();
                if (magic != "ssh-dss")
                {
                    throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (missing magic)");
                }

                BigInteger p = reader.ReadMPInt();
                BigInteger q = reader.ReadMPInt();
                BigInteger g = reader.ReadMPInt();
                BigInteger y = reader.ReadMPInt();

                reader = new SSH2DataReader(privateBlob);
                BigInteger x = reader.ReadMPInt();

                keyPair = new DSAKeyPair(p, g, q, y, x);
            }
            else if (keyType == KeyType.ECDSA)
            {
                SSH2DataReader reader        = new SSH2DataReader(publicBlob);
                string         algorithmName = reader.ReadString();
                string         curveName     = reader.ReadString();
                byte[]         publicKeyPt   = reader.ReadByteString();

                reader = new SSH2DataReader(privateBlob);
                BigInteger privateKey = reader.ReadMPInt();

                EllipticCurve curve = EllipticCurve.FindByName(curveName);
                if (curve == null)
                {
                    throw new SSHException(Strings.GetString("UnsupportedEllipticCurve") + " : " + curveName);
                }
                ECPoint publicKey;
                if (!ECPoint.Parse(publicKeyPt, curve, out publicKey))
                {
                    throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (parsing public key failed)");
                }

                keyPair = new ECDSAKeyPair(curve, new ECDSAPublicKey(curve, publicKey), privateKey);

                if (!((ECDSAKeyPair)keyPair).CheckKeyConsistency())
                {
                    throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (invalid key pair)");
                }
            }
            else if (keyType == KeyType.ED25519)
            {
                SSH2DataReader reader        = new SSH2DataReader(publicBlob);
                string         algorithmName = reader.ReadString();
                byte[]         publicKey     = reader.ReadByteString();

                reader = new SSH2DataReader(privateBlob);
                byte[] privateKey = reader.ReadByteString();

                EdwardsCurve curve = EdwardsCurve.FindByAlgorithm(PublicKeyAlgorithm.ED25519);
                if (curve == null)
                {
                    throw new SSHException(Strings.GetString("UnsupportedEllipticCurve"));
                }

                keyPair = new EDDSAKeyPair(curve, new EDDSAPublicKey(curve, publicKey), privateKey);

                if (!((EDDSAKeyPair)keyPair).CheckKeyConsistency())
                {
                    throw new SSHException(Strings.GetString("NotValidPrivateKeyFile") + " (invalid key pair)");
                }
            }
            else
            {
                throw new SSHException("Unknown file type. This should not happen.");
            }
        }