Skip to content

BlaiseSegal/ft_ssl

Repository files navigation

ft_ssl

ft_ssl is a cross-platform .NET 9 command line tool that reimplements RFC-compliant MD5 and SHA-256 hashing with a focus on stream processing, low allocations, and parity with the original Unix-style interface.

Features

  • Pure C# implementations of MD5 (RFC 1321) and SHA-256 (FIPS 180-4)
  • CLI-compatible options: stdin echo (-p), quiet (-q), reverse output (-r), and literal strings (-s)
  • Stream-based hashing that handles arbitrarily large inputs without loading them fully into memory
  • Zero-allocation fast path for MD5 to enable meaningful micro-benchmarks
  • Extensive regression tests built from official test vectors and padding edge cases

Repository Layout

Path Notes
src/ft_ssl Console entry point, option parsing, and hash implementations
tests/ft_ssl.Tests xUnit test suite covering RFC and edge-case vectors
benchmarks/ft_ssl.Benchmarks BenchmarkDotNet harness for throughput measurements
docs/performance Stored benchmark reports (latest SHA-256 run)
ft_ssl.sln Convenience solution file for working in IDEs

Getting Started

Prerequisites

Build the solution

dotnet restore
dotnet build ft_ssl.sln

Run the CLI

The executable expects the OpenSSL-inspired syntax:

ft_ssl command [command_opts] [command_args]

Invoke it directly from the project root via the SDK:

dotnet run --project src/ft_ssl -- md5 -s "hello"
dotnet run --project src/ft_ssl -- sha256 path/to/file.txt

You can also publish a standalone executable if you prefer to ship a self-contained binary:

dotnet publish src/ft_ssl -c Release -r osx-arm64 --self-contained false
./src/ft_ssl/bin/Release/net9.0/osx-arm64/publish/ft_ssl sha256 file.bin

Command Reference

Option Description
md5, sha256 Selects the hashing algorithm to run
-p Read from stdin, echo the exact input to stdout, then print the digest
-q Quiet mode: only the lowercase hex digest is emitted
-r Reverse mode: print digest followed by the subject ("string" or file path)
-s <string> Hash the literal string immediately following the flag
<file> Any non-flag argument is treated as a file path and hashed in order

Behavioral notes:

  • With no -s, -p, or file arguments, the program reads a single message from stdin and prints (stdin)= <digest>.
  • Multiple -s occurrences are allowed; they are processed in the order they appear on the command line before file inputs.
  • Missing files and permission errors are reported with the same wording as the original OpenSSL tool.

Worked Examples

# Echo stdin and hash it twice in one go
printf 'BlaiseSegal\n' | dotnet run --project src/ft_ssl -- md5 -p -p

# Hash two literal strings and a file in a single invocation
dotnet run --project src/ft_ssl -- sha256 -s "abc" -s "" ./tests/testdata.bin

# Quiet checksum for scripting
ft_ssl md5 -q -s "so we beat on boats against the current borne back ceaselessly into the past"

Implementation Notes

High-level architecture

  1. Program dispatches to the requested algorithm and orchestrates option parsing.
  2. CommandOptions.Parse(ReadOnlySpan<string>) interprets flags without allocations and records pending strings/files.
  3. Both algorithms implement IHashAlgorithm, exposing ComputeHash(Stream) and ComputeHash(byte[]) so the CLI can operate over spans or streams.
  4. Output formatting copies the conventions of the reference ft_ssl/openssl commands (quiet, reverse, stdin labels).

MD5 pipeline (Md5Algorithm)

  • Maintains a four-word state and a 512-bit working buffer, mirroring RFC 1321 step-by-step.
  • Accepts streaming updates, accumulating bytes until it can process a full 64-byte block.
  • Provides a TryComputeHash(ReadOnlySpan<byte>, Span<byte>) helper to compute digests without heap allocations, used by the benchmarks.

SHA-256 pipeline (Sha256Algorithm)

  • Implements the FIPS 180-4 schedule with a 16-word ring buffer to avoid repeatedly allocating the 64-word message schedule.
  • Uses MemoryMarshal.Cast and BinaryPrimitives.ReverseEndianness to convert input to big-endian words efficiently.
  • Applies Unsafe.Add to minimize bounds checks during the round loop while staying in safe managed code.

CLI ergonomics

  • Option parsing keeps track of whether stdin should be read after processing -s and file inputs, matching the original project rubric.
  • Error conditions (unknown flag, missing -s value) surface as console warnings, which mirrors how the historical ft_ssl behaves.

Testing

Execute the test suite with:

dotnet test

Covered scenarios include:

  • RFC 1321 Appendix A.5 MD5 vectors ("", "a", "abc", ...) and carefully chosen padding edge cases (55- and 64-byte messages).
  • FIPS 180-4 SHA-256 examples for empty input, "abc", the multi-block "abcdbc...nopq", and long 448-bit-aligned inputs.
  • Boundary conditions around the padding logic for both algorithms.

Representative vectors verified by the tests:

Input MD5 digest
"" d41d8cd98f00b204e9800998ecf8427e
"abc" 900150983cd24fb0d6963f7d28e17f72
"1234567890" * 8 57edf4a22be3c955ac49da2e2107b67a
Input SHA-256 digest
"" e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
"abc" ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1

Refer to tests/ft_ssl.Tests/Md5Tests.cs and tests/ft_ssl.Tests/Sha256Tests.cs for the complete catalogue.

Benchmarks

BenchmarkDotNet is used to monitor throughput and allocation behavior. Run a subset of the suite with:

dotnet run --project benchmarks/ft_ssl.Benchmarks -c Release -- --filter "*Sha256*"

Latest recorded numbers (see docs/performance/Sha256Benchmarks-report-github.md):

Benchmark Mean StdDev Allocated Notes
SHA-256 on a 1 MiB block 3.679 ms 0.0043 ms 56 B Arm64, .NET 9.0.9, Apple M2 Pro

The MD5 harness provides both an allocating and a zero-allocation variant to highlight the benefit of TryComputeHash. If BenchmarkDotNet times out while building, rerun with a longer build timeout, e.g. --buildTimeout 300.

Next Steps & Extensibility

  • Add more digest algorithms (e.g., SHA-512) by implementing IHashAlgorithm.
  • Expand benchmarks with varying input sizes and cross-platform baselines.
  • Wrap the CLI with scripting-friendly formats (JSON output, exit codes) if needed.

For further details, browse the source files in src/ft_ssl or open the solution in an IDE using ft_ssl.sln.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages