/// <summary> /// constructs from file /// </summary> /// <param name="path">file name</param> /// <param name="passphrase">passphrase or empty string if passphrase is not required</param> public SSH1UserAuthKey(string path, string passphrase) { #if PODEROSA_KEYFORMAT PrivateKeyLoader loader = new PrivateKeyLoader(path); loader.LoadSSH1PrivateKey( passphrase, out _modulus, out _publicExponent, out _privateExponent, out _primeP, out _primeQ, out _crtCoefficient, out _comment); #else Stream s = File.Open(path, FileMode.Open); byte[] header = new byte[32]; s.Read(header, 0, header.Length); if (Encoding.ASCII.GetString(header) != "SSH PRIVATE KEY FILE FORMAT 1.1\n") throw new SSHException(String.Format(Strings.GetString("BrokenKeyFile"), path)); SSH1DataReader reader = new SSH1DataReader(ReadAll(s)); s.Close(); byte[] cipher = reader.Read(2); //first 2 bytes indicates algorithm and next 8 bytes is space reader.Read(8); _modulus = reader.ReadMPInt(); _publicExponent = reader.ReadMPInt(); _comment = reader.ReadString(); byte[] prvt = reader.GetRemainingDataView().GetBytes(); //必要なら復号 CipherAlgorithm algo = (CipherAlgorithm)cipher[1]; if (algo != 0) { Cipher c = CipherFactory.CreateCipher(SSHProtocol.SSH1, algo, ConvertToKey(passphrase)); byte[] buf = new byte[prvt.Length]; c.Decrypt(prvt, 0, prvt.Length, buf, 0); prvt = buf; } SSH1DataReader prvtreader = new SSH1DataReader(prvt); byte[] mark = prvtreader.Read(4); if (mark[0] != mark[2] || mark[1] != mark[3]) throw new SSHException(Strings.GetString("WrongPassphrase")); _privateExponent = prvtreader.ReadMPInt(); _crtCoefficient = prvtreader.ReadMPInt(); _primeP = prvtreader.ReadMPInt(); _primeQ = prvtreader.ReadMPInt(); #endif }
/// <summary> /// Read SSH1 private key parameters. /// </summary> /// <param name="passphrase">passphrase for decrypt the key file</param> /// <param name="modulus">private key parameter</param> /// <param name="publicExponent">private key parameter</param> /// <param name="privateExponent">private key parameter</param> /// <param name="primeP">private key parameter</param> /// <param name="primeQ">private key parameter</param> /// <param name="crtCoefficient">private key parameter</param> /// <exception cref="SSHException">failed to parse</exception> public void Load( string passphrase, out BigInteger modulus, out BigInteger publicExponent, out BigInteger privateExponent, out BigInteger primeP, out BigInteger primeQ, out BigInteger crtCoefficient) { if (keyFile == null) throw new SSHException("A key file is not loaded yet"); byte[] hdr = Encoding.ASCII.GetBytes(PrivateKeyFileHeader.SSH1_HEADER); if (!ByteArrayUtil.ByteArrayStartsWith(keyFile, hdr)) throw new SSHException(Strings.GetString("NotValidPrivateKeyFile")); SSH1DataReader reader = new SSH1DataReader(keyFile); reader.Read(hdr.Length); byte[] cipher = reader.Read(2); //first 2 bytes indicates algorithm and next 8 bytes is space reader.Read(8); modulus = reader.ReadMPInt(); publicExponent = reader.ReadMPInt(); byte[] comment = reader.ReadString(); byte[] prvt = reader.ReadAll(); //必要なら復号 CipherAlgorithm algo = (CipherAlgorithm)cipher[1]; if (algo != 0) { Cipher c = CipherFactory.CreateCipher(SSHProtocol.SSH1, algo, SSH1PassphraseToKey(passphrase)); byte[] buf = new byte[prvt.Length]; c.Decrypt(prvt, 0, prvt.Length, buf, 0); prvt = buf; } SSH1DataReader prvtreader = new SSH1DataReader(prvt); byte[] mark = prvtreader.Read(4); if (mark[0] != mark[2] || mark[1] != mark[3]) throw new SSHException(Strings.GetString("WrongPassphrase")); privateExponent = prvtreader.ReadMPInt(); crtCoefficient = prvtreader.ReadMPInt(); primeP = prvtreader.ReadMPInt(); primeQ = prvtreader.ReadMPInt(); }
private void ReceiveServerKeys() { DataFragment packet = ReceivePacket(); SSH1DataReader reader = new SSH1DataReader(packet); SSH1PacketType pt = (SSH1PacketType) reader.ReadByte(); if (pt != SSH1PacketType.SSH_SMSG_PUBLIC_KEY) throw new SSHException("unexpected SSH SSH1Packet type " + pt, packet.GetBytes()); _cInfo.AntiSpoofingCookie = reader.Read(8); _cInfo.ServerKeyBits = reader.ReadInt32(); BigInteger serverKeyExponent = reader.ReadMPInt(); BigInteger serverKeyModulus = reader.ReadMPInt(); _cInfo.ServerKey = new RSAPublicKey(serverKeyExponent, serverKeyModulus); _cInfo.HostKeyBits = reader.ReadInt32(); BigInteger hostKeyExponent = reader.ReadMPInt(); BigInteger hostKeyModulus = reader.ReadMPInt(); _cInfo.HostKey = new RSAPublicKey(hostKeyExponent, hostKeyModulus); //read protocol support parameters int protocol_flags = reader.ReadInt32(); int supported_ciphers_mask = reader.ReadInt32(); _cInfo.SupportedEncryptionAlgorithmsMask = supported_ciphers_mask; int supported_authentications_mask = reader.ReadInt32(); //Debug.WriteLine(String.Format("ServerOptions {0} {1} {2}", protocol_flags, supported_ciphers_mask, supported_authentications_mask)); if (reader.RemainingDataLength > 0) throw new SSHException("data length mismatch", packet.GetBytes()); bool found = false; foreach (CipherAlgorithm a in _param.PreferableCipherAlgorithms) { if (a != CipherAlgorithm.Blowfish && a != CipherAlgorithm.TripleDES) continue; else if (a == CipherAlgorithm.Blowfish && (supported_ciphers_mask & (1 << (int)CipherAlgorithm.Blowfish)) == 0) continue; else if (a == CipherAlgorithm.TripleDES && (supported_ciphers_mask & (1 << (int)CipherAlgorithm.TripleDES)) == 0) continue; _cInfo.IncomingPacketCipher = _cInfo.OutgoingPacketCipher = a; found = true; break; } if (!found) throw new SSHException(String.Format(Strings.GetString("ServerNotSupportedX"), "Blowfish/TripleDES")); if (_param.AuthenticationType == AuthenticationType.Password && (supported_authentications_mask & (1 << (int)AuthenticationType.Password)) == 0) throw new SSHException(String.Format(Strings.GetString("ServerNotSupportedPassword")), packet.GetBytes()); if (_param.AuthenticationType == AuthenticationType.PublicKey && (supported_authentications_mask & (1 << (int)AuthenticationType.PublicKey)) == 0) throw new SSHException(String.Format(Strings.GetString("ServerNotSupportedRSA")), packet.GetBytes()); TraceReceptionEvent(pt, "received server key"); }
/// <summary> /// Process forwarded message. /// </summary> /// <param name="message">a forwarded message</param> private void ProcessMessage(DataFragment message) { if (_authKeyProvider == null || !_authKeyProvider.IsAuthKeyProviderEnabled) { SendFailure(); return; } SSH1DataReader reader = new SSH1DataReader(message); OpenSSHAgentForwardingMessageType messageType = (OpenSSHAgentForwardingMessageType)reader.ReadByte(); switch (messageType) { // for SSH1 keys case OpenSSHAgentForwardingMessageType.SSH_AGENTC_REQUEST_RSA_IDENTITIES: SSH1Identities(); break; case OpenSSHAgentForwardingMessageType.SSH_AGENTC_RSA_CHALLENGE: { reader.ReadUInt32(); // ignored BigInteger e = reader.ReadMPInt(); BigInteger n = reader.ReadMPInt(); BigInteger encryptedChallenge = reader.ReadMPInt(); byte[] sessionId = reader.Read(16); uint responseType = reader.ReadUInt32(); SSH1IRSAChallenge(e, n, encryptedChallenge, sessionId, responseType); } break; // for SSH2 keys case OpenSSHAgentForwardingMessageType.SSH2_AGENTC_REQUEST_IDENTITIES: SSH2Identities(); break; case OpenSSHAgentForwardingMessageType.SSH2_AGENTC_SIGN_REQUEST: { byte[] blob = reader.ReadByteString(); byte[] data = reader.ReadByteString(); uint flags = reader.ReadUInt32(); SSH2Sign(blob, data, flags); } break; default: SendFailure(); break; } }