Never wanting to get stale professionally, I regularly experiment with different libraries, frameworks programming languages, and tools. It helps me stay on top of what’s going on in the industry. The Rust programming language seems to be getting used and talked about much more these days. I even saw it referenced in a TV/stream commercial for a staffing company recently; although, I can’t remember that company’s name.
But “acquiring” new programming languages requires more justification for me to want to my precious personal time. It’s not something you can usually experiment with for just a few hours and walk away from having a sound opinion. You must spend significant amount time using a language to really understand it.
Now, going through tutorials isn’t a very good way to learn a language. Sure, it makes getting tooling setup and a simple working program running easy. But the moment you step off the narrative trail of the tutorial, you find yourself unsupported, having to put in signficant energy to self-learn what went wrong and get back on track. If the tutorial is typical, it doesn’t seem all that interesting. You face the question, “how much work do I want to put in to make a dumb tutorial app that I don’t care about work better?”
So, I tend to reframe the learning experience as one where I build something I want to build with the new technology. This gives me a goal to shoot for and helps me stay motivated. The trick is to not be overly ambitious.
I opted, this time, to make a little tool I could use to simplfy verification of digests on files I’ve downloaded. You know, hashes, checksums, fingerprints…those strings filled with random-looking alpha-numeric values that most people have seen on download sites, but which few people know how to use, and fewer acutally use. You’ll typically only see them for:
- executables that aren’t signed by a publisher
- archives used to prepare executables that don’t include signatures that operating systems automatically verify
- for files you download from vendors who are particularly security-minded
Most operating systems have some sort of tool available to check the digests (certutil, md5sum, shasum, sha256sum, openssl But they:
- are usually command line tools
- require you enter the algorithm name
- require you visually/manually compare your computed digest against the public one
I don’t mind using command-line tools, but I though it’d be nice to use the same tool in each environment I’m in.
The other two issue make the tedious task of performing the verification all on the user’s shoulders. It should be lower effort to performt he vericication.
The computer can guess the possible algorithm from the length of the digest. Most digests are published in hex-encoded form. If you look at the most commonly used algoritms, they all have use distinct bit-lengths. You have to get into pretty weird territory before you start to see algorithms with digest sizes equal in length to more popular algorithms.
Why should I waste effort visually comparing two digests? I can hope to take advantage of the characteric of cryptographic hashes that makes small changes in input result in obvious changes in output. Or I can just let my computer do that comparison
So I created digestify to take the little bit of extra effort out of digest verification.
You give it a file and a digest. It guesses the candidate digest algorithms from the provided digest length. For each candidate, it computes the digest and compares it, telling you when they do or don’t match.
It currently supports SHA-512, SHA-256, SHA-1, MD5, and CRC-32.
At the moment, I haven’t set up packaging of distributable binaries. So it’s not the easied to install. If you’ve installed the rust toolchain with rustup, you can run:
cargo install digestify
Sources are available on github.
Examples in us:
$ digestify Cargo.lock ac4a0ad1af6773ce6980cc9958cfd18820275f28b8055b93e4d69688e2fd72c8 Verifying 'Cargo.lock' against provided digest of size 64 hex chars / 256 bits. Candidate digest(s): SHA-256. SHA-256: MATCHES Expected=ac4a0ad1af6773ce6980cc9958cfd18820275f28b8055b93e4d69688e2fd72c8 Actual=ac4a0ad1af6773ce6980cc9958cfd18820275f28b8055b93e4d69688e2fd72c8 $ echo $? 0
$ digestify Cargo.toml f26c2e4e001349b737a3a5cc5fc4afc87b423773 Verifying 'Cargo.toml' against provided digest of size 40 hex chars / 160 bits. Candidate digest(s): SHA-1. SHA-1: FAIL Expected=f26c2e4e001349b737a3a5cc5fc4afc87b423773 Actual=a30d387b67f1e4d26fd59b3ddb94cfde58d23287 $ echo $? 254
Maybe someday I’ll:
- set up CI to build signed prebuilt binaries for common platforms
- add colored terminal output to highlight differences
- learn how to write docs for rust code
- perhaps even experiment with some UI libraries to build a simple front end to help those that despise command line tools