Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20200526153624.GA14779@openwall.com>
Date: Tue, 26 May 2020 17:36:24 +0200
From: Solar Designer <solar@...nwall.com>
To: john-users@...ts.openwall.com
Subject: hashcat vs. JtR

Hi,

A reporter contacted me privately asking:

"In 2020, how would you judge the main differences between hashcat and
JtR, and for which use cases?"

and clarifying:

"For my purposes a high-level understanding of the differences would be
most useful"

I suggested to post my thoughts on this publicly so that others can see
and comment (and maybe correct me).  My list of differences quickly got
way too long, so I adjusted it to start with high-level comparisons and
only then describe some detail and provide some examples.  Here goes:

Overall, JtR is more of a CPU tool which also supports GPUs (for some
(non-)hashes), while hashcat is more of a GPU tool which also supports
CPUs (for all of its supported (non-)hashes, but only through OpenCL).

These days, a professional password cracking rig contains multiple GPUs,
and hashcat is the tool to use those most efficiently.  However, JtR is
likely to also be used there, providing a more complete feature set and
greater flexibility across the two tools combined.

For casual uses, the choice will vary by personal preference,
possibility and ease of installation on whatever system the person
readily has, and need for higher performance and greater flexibility
primarily on GPUs (hashcat) or CPUs (JtR).

Current versions of hashcat require OpenCL (in latest release) or can
also use CUDA without OpenCL (in git, so will be in the next release).
This means they won't work at all (not even on CPU) without a suitable
"driver" like this installed on the system.  In contrast, JtR supports
OpenCL, but that is optional - JtR can also be built and run without
OpenCL on the system, in which case it will only use the CPUs.  Some
systems don't have GPUs, so hashcat's dependency on OpenCL or CUDA can
be a nuisance on those.

JtR is usually faster than hashcat on CPU (especially for slow hashes
like bcrypt), but hashcat is usually faster than JtR on GPU (especially
for fast hashes like NTLM).  There are occasional exceptions to that.
For example, hashcat's NTLM is impressively fast even on CPU (with
Intel's OpenCL), while JtR's optimized md5crypt is twice faster than
hashcat's on NVIDIA Kepler GPUs (which hashcat considers too old and
unsupported, but in practice is able to use anyway).

hashcat's multi-GPU support is much better than JtR's.  hashcat
distributes work between GPUs dynamically, whereas JtR does so before
the attack starts.  As a result, when running with a mix of different
speed GPUs hashcat keeps all of them busy until the attack completes,
whereas JtR may have some GPUs complete their work sooner than others.

hashcat's "brain" remembers previously-tested passwords and thus lets
multiple attacks (sequential and/or concurrent) skip repeated testing of
the same candidate passwords.  This is especially useful when a team is
working on attacking slow (non-)hashes.  JtR has no equivalent feature.

While JtR is purely a password cracker, hashcat supports cracking of
some binary keys as well.

While either tool supports a few hundred of different (non-)hash types,
there's far from a 100% overlap between what's supported by the tools.
In cases where whatever the user needs is only supported by one of the
tools, that dictates the choice of tool to use.  The alternative to that
is writing the missing code for the other tool (and ideally contributing
it to there for all to use), but that requires skill and effort.

For example, JtR supports cracking of passwords for FreeBSD GELI
volumes (albeit only on CPU), which hashcat does not (at all).  On the
other hand, JtR only supports non-cascaded ciphers for Windows
DiskCryptor (that is, when only one cipher is used at a time), whereas
hashcat has more complete DiskCryptor support including for cascaded
ciphers.  There are many other cases of this sort.  They will change
over time, but in general nuance like this can be crucial in practice.

JtR also lets the user combine fast hashes in various ways creating
so-called "dynamic formats", even right on the command-line.  These only
work on CPU, but they do use SIMD.  This is useful for cracking custom
web applications' passwords where developers used to get creative in how
they mix the different hash types provided by PHP or such.  hashcat has
no equivalent feature.  On the other hand, for the specific combinations
of fast hashes that hashcat does support, it supports them on GPU.

There are also auxiliary tools that are developed along with one of
these projects, but are usable with the other.  For example, to attack a
cryptocurrency wallet.dat file on GPUs, a user would first use JtR's
bitcoin2john.py and then use hashcat on its output.  Conversely,
hashcat's 7z2hashcat.pl is the upstream project for JtR's 7z2john.pl,
but that isn't as user-visible with 7z2john.pl being in JtR tree.

Also importantly, there are differences in maximum supported password
lengths.  Recent hashcat supports lengths up to 256 for all (non-)hashes
through inclusion of deliberately less optimal (slower) implementations
along with optimized faster implementations that are more length-limited
(with length limits varying by hash type, most painful perhaps being the
optimized md5crypt's limit of 15).  JtR generally only includes
optimized implementations with length limits inherent to those
optimizations, with only some exceptions (e.g., on CPU it includes both
"md5crypt" with the usual limit of 15 and "md5crypt-long" capable of up
to 125, but on GPU it currently only has the optimized "md5crypt-opencl"
with the limit of 15).  So hashcat fares much better in this respect.
Luckily, most other optimization-related length limits are high enough
not to pose a problem in practice (e.g., 55 for raw MD5).  This issue
doesn't apply for most modern (non-)hash types; it only exists for those
older and not so well designed password hash types where processing time
is significantly affected by password length.

There's also not a 100% overlap in which attacks the tools can run, and
how.  JtR has many candidate password generators on CPU and also uses
those to feed candidate passwords to GPUs, with only "mask mode"
delegated to GPUs when cracking fast hashes like NTLM.  To compensate,
JtR is able to stack on-device mask mode on top of other modes, forming
hybrid modes where part of the processing occurs on host CPU and part on
GPU.  This is efficient, but requires that a part of the attack be
expressed as a mask.  hashcat implements some equivalent (to JtR's) and
some different candidate password generators, but has them implemented
in device-side code.  This makes hashcat more flexible for efficiently
running complex attacks against fast hashes on GPU, but makes little
difference for attacks on slow (non-)hashes.

Also in terms of flexibility, JtR has more candidate password generators
(and lets the user write custom ones in a C-like language).  For
example, its "single crack" mode derives candidate passwords from
usernames and other user-specific information and targets them against
the specific user's password hash (and other hashes with the same salt),
which is efficient when cracking salted hashes.  JtR's "Subsets" mode
generates strings consisting of few different characters (progressively
increasing that number) out of a large set of possible characters.  Its
"Keyboard" mode (one of the pre-defined custom modes) generates keyboard
walk patterns.  There are no equivalent modes built into hashcat.  On
the other hand, hashcat has "Combination" mode, which combines words
from multiple wordlists to form candidate passphrases.  JtR's closest
built-in equivalent is PRINCE mode, kindly contributed by atom of
hashcat.  So usage of both tools can produce best results.  Speaking of
which: unfortunately, hashcat tends to greatly under-utilize GPUs when
it's fed candidate passwords via stdin, even when the (non-)hash type is
slow enough that such under-utilization wouldn't be inherently expected.
A workaround is to have "john --stdout" output written out to a file and
then read back by hashcat, but that triggers even slower startup.

hashcat's startup time feels painfully long for running and adjusting
many quick attacks manually, especially on CPU where JtR starts up
quickly.  This is in part related to hashcat's use of OpenCL even on
CPU, but not only that: when run on a new large wordlist, hashcat spends
a lot of time "caching" it, whereas JtR can start cracking right away.

On CPU, JtR directly (without relying on an OpenCL backend) supports
common SIMD instruction sets up to AVX-512 on x86-64.

JtR also supports AltiVec on POWER and NEON/ASIMD on ARM/Aarch64.  On
the other hand, due to NVIDIA's policy of not supporting OpenCL other
than on x86-64, JtR is unable to use NVIDIA GPUs on non-x86-64.  Recent
git hashcat regained such ability through its reintroduction of CUDA
support, but I doubt there's a decent OpenCL implementation to use such
non-x86 CPUs with hashcat.  So if you're on a platform like this and
want to use CPUs, use JtR.  If you're on an exotic platform like this
and want to use NVIDIA GPUs, use hashcat.  For example, use JtR on a
Raspberry Pi, but use hashcat on a NVIDIA Jetson.  You can also use both
JtR and hashcat on NVIDIA Jetson to use its CPU and GPU, respectively.
Of course, these devices are slow, so this is for casual/hobbyist use.

JtR also runs on plenty of other CPU architectures (without SIMD), for
which there might not exist OpenCL support.

JtR directly supports ZTEX 1.15y FPGA boards (including many at once).
Unfortunately, these are now rare.  Yet for those who have them, JtR
provides very good speeds at bcrypt (higher than hashcat's on high-end
GPUs in a per-board comparison) and at descrypt, while also supporting
several other common hash types.  hashcat could theoretically support
FPGAs through OpenCL (and JtR could too), but this doesn't work well in
practice (if at all).

There are third-party tools that use hashcat and/or JtR.  For example,
for hashcat there's Hashtopolis: https://github.com/s3inlc/hashtopolis
For JtR there's ByePass: https://github.com/webpwnized/byepass
If someone wants the functionality provided by these tools, this also
determines whether to use hashcat or JtR.

There are binary packages of hashcat and/or JtR in various repositories.
The user's operating system distribution of choice might have just one
of those tools.  Besides, it might not provide the most optimal OpenCL
backend for licensing reasons.  For example, Kali Linux appears to
provide pocl instead of Intel's OpenCL, on which hashcat complains:
"Not a native Intel OpenCL runtime. Expect massive speed loss."  There's
no such issue with JtR as packaged in Kali Linux.

The above aspects are very far from a complete comparison of the tools.
The examples given are just that.  There can be many more such examples -
for different (non-)hash types, different attacks, different hardware,
different OS - where one tool or the other would have advantages.

I also started writing a list of what's the same or similar between the
tools.  It quickly got way too long to include in this same message, so
I abandoned it for now.  I might try and "complete" and post it later.

I'd appreciate any comments, any major differences I might have missed,
and especially corrections if I got anything wrong.

Alexander

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.