/// <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)); }
/// <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")); } }
/* * 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); } }
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); } }