private void updateKeys(KeyExchange kex) { byte[] K = kex.getK(); byte[] H = kex.getH(); HASH hash = kex.getHash(); string[] guess = kex.m_guess; if (m_session_id == null) { m_session_id = new byte[H.Length]; Array.Copy(H, 0, m_session_id, 0, H.Length); } /* Initial IV client to server: HASH (K || H || "A" || session_id) Initial IV server to client: HASH (K || H || "B" || session_id) Encryption key client to server: HASH (K || H || "C" || session_id) Encryption key server to client: HASH (K || H || "D" || session_id) Integrity key client to server: HASH (K || H || "E" || session_id) Integrity key server to client: HASH (K || H || "F" || session_id) */ m_buf.reset(); m_buf.putMPInt(K); m_buf.putByte(H); m_buf.putByte((byte)0x41); m_buf.putByte(m_session_id); hash.update(m_buf.m_buffer, 0, m_buf.m_index); m_IVc2s = hash.digest(); int j = m_buf.m_index - m_session_id.Length - 1; m_buf.m_buffer[j]++; hash.update(m_buf.m_buffer, 0, m_buf.m_index); m_IVs2c = hash.digest(); m_buf.m_buffer[j]++; hash.update(m_buf.m_buffer, 0, m_buf.m_index); m_Ec2s = hash.digest(); m_buf.m_buffer[j]++; hash.update(m_buf.m_buffer, 0, m_buf.m_index); m_Es2c = hash.digest(); m_buf.m_buffer[j]++; hash.update(m_buf.m_buffer, 0, m_buf.m_index); m_MACc2s = hash.digest(); m_buf.m_buffer[j]++; hash.update(m_buf.m_buffer, 0, m_buf.m_index); m_MACs2c = hash.digest(); try { Class c; c = Class.ForName(getConfig(guess[KeyExchange.PROPOSAL_ENC_ALGS_STOC])); m_s2ccipher = (Cipher)(c.Instance()); while (m_s2ccipher.BlockSize > m_Es2c.Length) { m_buf.reset(); m_buf.putMPInt(K); m_buf.putByte(H); m_buf.putByte(m_Es2c); hash.update(m_buf.m_buffer, 0, m_buf.m_index); byte[] foo = hash.digest(); byte[] bar = new byte[m_Es2c.Length + foo.Length]; Array.Copy(m_Es2c, 0, bar, 0, m_Es2c.Length); Array.Copy(foo, 0, bar, m_Es2c.Length, foo.Length); m_Es2c = bar; } m_s2ccipher.init(jsch.Cipher.DECRYPT_MODE, m_Es2c, m_IVs2c); m_cipher_size = m_s2ccipher.IVSize; c = Class.ForName(getConfig(guess[KeyExchange.PROPOSAL_MAC_ALGS_STOC])); m_s2cmac = (MAC)(c.Instance()); m_s2cmac.init(m_MACs2c); m_mac_buf = new byte[m_s2cmac.BlockSize]; c = Class.ForName(getConfig(guess[KeyExchange.PROPOSAL_ENC_ALGS_CTOS])); m_c2scipher = (Cipher)(c.Instance()); while (m_c2scipher.BlockSize > m_Ec2s.Length) { m_buf.reset(); m_buf.putMPInt(K); m_buf.putByte(H); m_buf.putByte(m_Ec2s); hash.update(m_buf.m_buffer, 0, m_buf.m_index); byte[] foo = hash.digest(); byte[] bar = new byte[m_Ec2s.Length + foo.Length]; Array.Copy(m_Ec2s, 0, bar, 0, m_Ec2s.Length); Array.Copy(foo, 0, bar, m_Ec2s.Length, foo.Length); m_Ec2s = bar; } m_c2scipher.init(jsch.Cipher.ENCRYPT_MODE, m_Ec2s, m_IVc2s); c = Class.ForName(getConfig(guess[KeyExchange.PROPOSAL_MAC_ALGS_CTOS])); m_c2smac = (MAC)(c.Instance()); m_c2smac.init(m_MACc2s); if (!guess[KeyExchange.PROPOSAL_COMP_ALGS_CTOS].Equals("none")) { string foo = getConfig(guess[KeyExchange.PROPOSAL_COMP_ALGS_CTOS]); if (foo != null) { try { c = Class.ForName(foo); m_deflater = (Compression)(c.Instance()); int level = 6; try { level = int.Parse(getConfig("compression_level")); } catch (Exception) { } m_deflater.init(Compression.DEFLATER, level); } catch (Exception) { Console.Error.WriteLine(foo + " isn't accessible."); } } } else { if (m_deflater != null) m_deflater = null; } if (!guess[KeyExchange.PROPOSAL_COMP_ALGS_STOC].Equals("none")) { string foo = getConfig(guess[KeyExchange.PROPOSAL_COMP_ALGS_STOC]); if (foo != null) { try { c = Class.ForName(foo); m_inflater = (Compression)(c.Instance()); m_inflater.init(Compression.INFLATER, 0); } catch (Exception) { Console.Error.WriteLine(foo + " isn't accessible."); } } } else { if (m_inflater != null) m_inflater = null; } } catch (Exception e) { Console.Error.WriteLine("updatekeys: " + e); } }
private Cipher genCipher() { try { Type t; t = Type.GetType(m_jsch.getConfig("3des-cbc")); m_cipher = (Cipher)(Activator.CreateInstance(t)); } catch//(Exception e) { } return m_cipher; }
internal byte[] genKey(byte[] passphrase, byte[] iv) { if (m_cipher == null) m_cipher = genCipher(); if (m_hash == null) m_hash = genHash(); byte[] key = new byte[m_cipher.BlockSize]; int hsize = m_hash.BlockSize; byte[] hn = new byte[key.Length / hsize * hsize + (key.Length % hsize == 0 ? 0 : hsize)]; try { byte[] tmp = null; if (vendor == VENDOR_OPENSSH) { for (int index = 0; index + hsize <= hn.Length;) { if (tmp != null) { m_hash.update(tmp, 0, tmp.Length); } m_hash.update(passphrase, 0, passphrase.Length); m_hash.update(iv, 0, iv.Length); tmp = m_hash.digest(); Array.Copy(tmp, 0, hn, index, tmp.Length); index += tmp.Length; } Array.Copy(hn, 0, key, 0, key.Length); } else if (vendor == VENDOR_FSECURE) { for (int index = 0; index + hsize <= hn.Length;) { if (tmp != null) { m_hash.update(tmp, 0, tmp.Length); } m_hash.update(passphrase, 0, passphrase.Length); tmp = m_hash.digest(); Array.Copy(tmp, 0, hn, index, tmp.Length); index += tmp.Length; } Array.Copy(hn, 0, key, 0, key.Length); } } catch (Exception) { } return key; }
private byte[] encrypt(byte[] plain, byte[][] _iv) { if (passphrase == null) return plain; if (m_cipher == null) m_cipher = genCipher(); byte[] iv = _iv[0] = new byte[m_cipher.IVSize]; if (m_random == null) m_random = genRandom(); m_random.fill(iv, 0, iv.Length); byte[] key = genKey(passphrase, iv); byte[] encoded = plain; int bsize = m_cipher.BlockSize; if (encoded.Length % bsize != 0) { byte[] foo = new byte[(encoded.Length / bsize + 1) * bsize]; Array.Copy(encoded, 0, foo, 0, encoded.Length); encoded = foo; } try { m_cipher.init(Cipher.ENCRYPT_MODE, key, iv); m_cipher.update(encoded, 0, encoded.Length, encoded, 0); } catch (Exception) { } return encoded; }
internal IdentityFile(string identity, JSch jsch) { m_identity = identity; m_jsch = jsch; try { Type c = Type.GetType(jsch.getConfig("3des-cbc")); m_cipher = (Cipher)Activator.CreateInstance(c); m_key = new byte[m_cipher.BlockSize]; // 24 m_iv = new byte[m_cipher.IVSize]; // 8 c = Type.GetType(jsch.getConfig("md5")); m_hash = (HASH)(Activator.CreateInstance(c)); m_hash.init(); FileInfo file = new FileInfo(identity); FileStream fis = File.OpenRead(identity); byte[] buf = new byte[(int)(file.Length)]; int len = fis.Read(buf, 0, buf.Length); fis.Close(); int i = 0; while (i < len) { if (buf[i] == 'B' && buf[i + 1] == 'E' && buf[i + 2] == 'G' && buf[i + 3] == 'I') { i += 6; if (buf[i] == 'D' && buf[i + 1] == 'S' && buf[i + 2] == 'A') m_type = DSS; else if (buf[i] == 'R' && buf[i + 1] == 'S' && buf[i + 2] == 'A') m_type = RSA; else if (buf[i] == 'S' && buf[i + 1] == 'S' && buf[i + 2] == 'H') { // FSecure m_type = UNKNOWN; m_keytype = FSECURE; } else throw new JSchException("invaid privatekey: " + identity); i += 3; continue; } if (buf[i] == 'C' && buf[i + 1] == 'B' && buf[i + 2] == 'C' && buf[i + 3] == ',') { i += 4; for (int ii = 0; ii < m_iv.Length; ii++) m_iv[ii] = (byte)(((a2b(buf[i++]) << 4) & 0xf0) + (a2b(buf[i++]) & 0xf)); continue; } if (buf[i] == '\r' && i + 1 < buf.Length && buf[i + 1] == '\n' ) { i++; continue; } if (buf[i] == 0x0a && i + 1 < buf.Length) { if (buf[i + 1] == '\n') { i += 2; break; } if (buf[i + 1] == '\r' && i + 2 < buf.Length && buf[i + 2] == '\n' ) { i += 3; break; } bool inheader = false; for (int j = i + 1; j < buf.Length; j++) { if (buf[j] == 0x0a) break; //if(buf[j]==0x0d) break; if (buf[j] == ':') { inheader = true; break; } } if (!inheader) { i++; m_encrypted = false; // no passphrase break; } } i++; } if (m_type == ERROR) throw new JSchException("invaid privatekey: " + identity); int start = i; while (i < len) { if (buf[i] == 0x0a) { bool xd = (buf[i - 1] == 0x0d); Array.Copy(buf, i + 1, buf, i - (xd ? 1 : 0), len - i - 1 - (xd ? 1 : 0) ); if (xd) len--; len--; continue; } if (buf[i] == '-') break; i++; } m_encoded_data = Util.fromBase64(buf, start, i - start); if (m_encoded_data.Length > 4 && // FSecure m_encoded_data[0] == (byte)0x3f && m_encoded_data[1] == (byte)0x6f && m_encoded_data[2] == (byte)0xf9 && m_encoded_data[3] == (byte)0xeb) { Buffer _buf = new Buffer(m_encoded_data); _buf.getInt(); // 0x3f6ff9be _buf.getInt(); byte[] _type = _buf.getString(); byte[] _cipher = _buf.getString(); string s_cipher = System.Text.Encoding.Default.GetString(_cipher); if (s_cipher.Equals("3des-cbc")) { _buf.getInt(); byte[] foo = new byte[m_encoded_data.Length - _buf.OffSet]; _buf.getByte(foo); m_encoded_data = foo; m_encrypted = true; throw new JSchException("unknown privatekey format: " + identity); } else if (s_cipher.Equals("none")) { _buf.getInt(); m_encrypted = false; byte[] foo = new byte[m_encoded_data.Length - _buf.OffSet]; _buf.getByte(foo); m_encoded_data = foo; } } try { file = new FileInfo(identity + ".pub"); fis = File.OpenRead(identity + ".pub"); buf = new byte[(int)(file.Length)]; len = fis.Read(buf, 0, buf.Length); fis.Close(); } catch { return; } if (buf.Length > 4 && // FSecure's public key buf[0] == '-' && buf[1] == '-' && buf[2] == '-' && buf[3] == '-' ) { i = 0; do { i++; } while (buf.Length > i && buf[i] != 0x0a); if (buf.Length <= i) return; while (true) { if (buf[i] == 0x0a) { bool inheader = false; for (int j = i + 1; j < buf.Length; j++) { if (buf[j] == 0x0a) break; if (buf[j] == ':') { inheader = true; break; } } if (!inheader) { i++; break; } } i++; } if (buf.Length <= i) return; start = i; while (i < len) { if (buf[i] == 0x0a) { Array.Copy(buf, i + 1, buf, i, len - i - 1); len--; continue; } if (buf[i] == '-') { break; } i++; } m_publickeyblob = Util.fromBase64(buf, start, i - start); if (m_type == UNKNOWN) { if (m_publickeyblob[8] == 'd') m_type = DSS; else if (m_publickeyblob[8] == 'r') m_type = RSA; } } else { if (buf[0] != 's' || buf[1] != 's' || buf[2] != 'h' || buf[3] != '-') return; i = 0; while (i < len) { if (buf[i] == ' ') break; i++; } i++; if (i >= len) return; start = i; while (i < len) { if (buf[i] == ' ') break; i++; } m_publickeyblob = Util.fromBase64(buf, start, i - start); } } catch (Exception e) { if (e is JSchException) throw (JSchException)e; throw new JSchException(e.ToString()); } }