I’ve recently written an SSH library called Thrussh, and I’ve also started to use it for actual tasks like replacing the SCP client in Pijul.
This is an important rule of cryptography: do not do your own crypto. Cryptography is full of subtleties, and it is frighteningly easy to introduce more problems than you solve.
For example supporting outdated cryptography, even if you don’t really plan to use it, can be harmful to your legitimate crypto, as shown by the Drown attack on HTTPS.
Or side-channel attacks, by which an attacker can get bits of a secret key by monitoring differences in the heat, electromagnetic, or time patterns of a processor.
This is why I’m using libsodium. Also, this is why I’m using the raw version of it, with as little fuss as possible in the bindings themselves.
Thrussh was designed to have the lowest possible code size and dependency set, so as to make it easily readable. It has a server and a client side, sharing a datastructure called CommonSession
(see src/session.rs
in our darcs repository). Sessions maintain a state, essentially when exchanging keys in the beginning, or when re-exchanging keys during an SSH connection.
Thrussh does not depend on any network library: users of this library are instead expected to provide it with instances of std::io::BufRead
and std::io::Write
. This design allows it to be used with synchronous or asynchronous sockets. In both cases (synchronous or asynchronous), the interface is exactly the same: users need to implement either the Server
trait (if they’re writing a server) or the Client
trait (if writing a client). Then, they just have to create an instance of thrussh::server::Connection
(respectively thrussh::client::Connection
), and then successively calling the .read
and .write
methods of the connections, in a loop (starting with .write
for synchronous sockets).
A number of methods (for instance .is_authenticated
) are supplied for the client to be able to stop the loop at some stages of the protocol, for instance when user input is needed.
Thrussh has been mostly tested with the mio
crate, which allows efficient and portable asynchronous I/O. Writing an SCP client was actually fairly easy, see the result on its darcs:
darcs get https://pijul.org/darcs/scp
It’s not a full scp program: in particular, it does not have the -f
and -t
options required to implement SCP on the server side.
This is probably a relatively easy task anyway, as it does not use SSH: it’s just a parser of stdin that can write to files. See this description of the SCP protocol for more details.
We’ve received a number of comments suggesting that we should move to github as soon as possible. This is simply not going to happen. We might switch to Pijul when it’s ready, of course.
The main benefit we see in darcs is that we already know it, and it can be learnt completely in almost no time by anyone.
This is not the case of any 3-way-merge-based systems, although people who’ve been using such systems for years usually reply that “once you know it it’s easy”. This is probably true, but unrelated to the above claim.
Also, in darcs, patches are associative, which is a really useful property to have in a VCS. This is not a bug/implementation mistake in 3-way merge/git, as suggested by some. It’s a problem in the algorithm itself.