Back in October 2020, I created a tool called jwt-hack to make security testing for JSON Web Tokens (JWTs) a bit more convenient. At the time, this Go-based tool was a project born out of my own necessity, focusing on its core crack
feature to find JWT signing secrets using wordlists or brute force.
Truth be told, for the nearly five years since, the project has been somewhat neglected compared to my other work. While I made small improvements here and there, a part of me always felt it deserved more. That's why I finally decided to take the plunge and give the project a complete reboot, leading to the release of a new major version: jwt-hack v2.
In this post, I'd like to briefly share what the key changes in jwt-hack v2 are and where the project is headed next.
From Go to Rust: The Core Change
The biggest change in v2 is the complete switch from Go to Rust. Rewriting all the existing Go code in Rust took a fair amount of effort, but I believe it was a worthwhile endeavor.
The primary reason was stability. Frankly, v1 would occasionally run into unexpected memory-related issues. Thanks to Rust's Ownership system and its strict compile-time checks, I was able to prevent these kinds of bugs at the source, resulting in a much more stable tool.
Of course, a performance boost came along as a bonus. Even a simple benchmark shows a pretty satisfying speed improvement.
Metric | jwt-hack v1 | jwt-hack v2 |
---|---|---|
Time (mean ± σ) | 1.874 s ± 0.033 s | 678.6 ms ± 165.8 ms |
Range (min … max) | 1.834 s … 1.935 s | 623.5 ms … 1150.4 ms |
User Time | 7.312 s | 3516.7 ms |
System Time | 1.985 s | 491.1 ms |
Runs | 10 | 10 |
Performance comparison of the crack
feature under identical conditions ($ jwt-hack crack eyJ0e... --mode brute --max 4
)
Strengthening the Foundation
This wasn't just about changing the language; I also focused on strengthening the project's foundation.
Test Coverage
One of the areas I paid the most attention to during v2's development was the test code. I wrote far more thorough tests compared to the previous version, creating a solid base to minimize side effects from future code changes and maintain stability as new features are added.
Compatibility
Even though it's a major version release, all the command-line options and usage patterns from v1 are fully inherited. This means you can update and apply it to your existing scripts or pipelines without any migration work.
Expanded Features
Building on the stability and development convenience gained from the switch to Rust, I've added several features that I'd long felt were necessary.
Support for More Algorithms
While it previously focused on HMAC-based algorithms (HS256, HS384, HS512), jwt-hack now supports asymmetric encryption algorithms like RSA (RS*) and ECDSA (ES*).
New Key-Based Functionality
Going beyond simple secret-based testing, it's now possible to generate, verify, and test tokens using private/public keys. For example, you can easily create a JWT signed with a private key like this:
ssh-keygen -t rsa -b 4096 -E SHA256 -m PEM -P "" -f RS256.key
jwt-hack encode '{"a":"z"}' --private-key RS256.key --algorithm=RS256
New Verify Mode
Truth be told, the previous version lacked even the basic functionality to verify if a JWT's signature was valid. This update introduces a verify
mode that allows you to check a token's signature with a secret or a public key, making the tool more complete for token testing.
Broader Attack Vector Support
One of jwt-hack's core features is generating tokens for known attack vectors. In addition to the existing none
algorithm and jku/x5u
attacks, it now supports a wider range of vectors and will continue to expand in the future:
- Algorithm Confusion (tampering with the
alg
header to HS256) - SQL Injection in
kid
(inserting an SQLi payload into thekid
header) - Other known attack techniques
Installation
Cargo
If you're a Rust developer, you can install it directly via cargo
.
cargo install jwt-hack
Homebrew
And for one of the most exciting pieces of news: jwt-hack is now included in the official homebrew-core
! You can install and update it with a simple command, no need to tap a separate repository.
brew install jwt-hack
More
You can also get jwt-hack through various other channels, including the Snapcraft Package, Docker Hub, and GHCR.
Final Thoughts
Breathing new life into a long-neglected project was more enjoyable than I expected. It was great to see the tool improve, but what made it particularly fun was the process of getting to know the Rust language more deeply.
Going forward, I plan to build jwt-hack into a comprehensive tool packed with various features for JWT security testing. If you have any ideas for necessary features or improvements, please don't hesitate to leave a comment on the GitHub Issues. Your interest is the driving force behind this project.