Encrypted File Copy

C · OpenSSL · AES-256 · HMAC-SHA256

A small scp-style program in C that copies a file from one machine to another over an encrypted channel. The point was to build the encrypted tunnel by hand with OpenSSL's libcrypto, instead of leaning on SSH, and to see what an authenticated-encryption pipeline actually involves end to end.

The pipeline

On each side the work is split across two threads that hand data to one another through a shared buffer. On the client, one thread reads the file and runs the crypto, the other handles the network. On the server the same split runs in reverse:

Keys, IVs, and the HMAC

The two ends share a pre-shared key. The IV is fresh per transfer and read from /dev/urandom, and it travels alongside the ciphertext because the receiver needs it to decrypt. The HMAC is keyed from the same shared secret and covers the encrypted bytes, so the server can detect any tampering on the wire before it ever touches the plaintext. The check is the important part: if a single bit of the ciphertext is flipped in flight, HMAC validation fails and the file is rejected rather than written.

netcat as the transport

The transport itself is deliberately dumb: the actual bytes move over netcat. The client pipes its base64 payload into an ncat process, and the server reads it back off ncat's output and parses it. That is why everything is base64-encoded first, it keeps the encrypted blob safe to pass through a plain text pipe. Pushing the raw socket work onto netcat let me keep the program focused on the encryption and authentication rather than connection management.

What I took from it

The useful lesson was the discipline of verify-then-decrypt: the HMAC has to be checked before the ciphertext is trusted, and the file must not be written if the check fails. It is a hobby reimplementation of ideas that scp and TLS give you for free, but building the IV handling, the keyed MAC, and the failure path yourself makes it obvious why those pieces exist.