Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20121213001539.GA10795@openwall.com>
Date: Thu, 13 Dec 2012 04:15:39 +0400
From: Solar Designer <solar@...nwall.com>
To: john-dev@...ts.openwall.com
Subject: Re: Run-time change of a format's max length

On Wed, Dec 12, 2012 at 01:33:11AM +0100, magnum wrote:
> I'm in the process of tweaking ntlmv2-opencl. I now use partial binary transfers, and Unicode conversion on GPU. After that I could make the plaintext buffer variable-size. Like other fast formats it gets a significant boost from really short plaintext lengths, like 8.

I think that this format would be badly impacted by the bottleneck even
at lengths up to 8.  The real fix is for us to implement on-GPU
set_mask() as discussed this summer.  Until we do, we only have these
very limited workarounds.  In this context, I am not sure how much
effort we want to put into the workarounds.  On the other hand, they
would be helpful for some cracking modes even after we have set_mask().

> That is a severe limit though, and you wouldn't want to recompile for different lengths. So a better option is to default to 27 characters, but honor the --length option of Jumbo (which merely decreases format->params.plaintext_length).

Shouldn't this option be called --max-length instead, and we'd have
--min-length too?

As to plaintext_length, I intend to add a flag that would indicate
whether truncation at this length occurs in actual use of the target
systems (that use hashes of this type) or whether it's a limitation of
the format as implemented in JtR.  There's a third possibility - the
target systems do not permit longer passwords - but for our needs this
is the same as JtR limitation, I think (except for documentation /
reporting, maybe).  To summarize, there are three possibilities:

1. Target systems truncate at plaintext_length.

2. JtR does not support longer than plaintext_length even though target
systems do.

3. Target systems do not permit longer than plaintext_length.

When processing an overly long candidate password (one that would exceed
plaintext_length), JtR should truncate it if #1 is true or skip it if #2
or #3 are true.  This logic is not currently implemented (JtR always
truncates), but I think we should implement it.

In this context, if --max-length is specified and results in the value
of plaintext_length being lowered, this should be treated the same as
#2/#3 (longer passwords skipped).  It should not result in truncation.

> This I can (and will) do right now, in init(). But here comes the punch line, and the question:
> 
> If we let eg. incremental mode alter format->params.plaintext_length (that is, tell the format about incremental's MaxLen), we will automatically use the best possible speed. So how do we accomplish this? Just change it? Well, the problem is that the format inits long before incremental does.

This is a catch-22.  Incremental mode itself uses the format's
plaintext_length to see if its MaxLen was possibly higher than that, and
it lowers MaxLen if so.  Thus, if the format's init() may alter
plaintext_length, this needs to happen before incremental mode uses
plaintext_length for this check.

Yes, maybe we need to introduce a new interface - or rather, just a new
convention - that plaintext_length may be reduced by a cracking mode, in
which case the format _may_ (but is not required) to make use of this
info and actually stop supporting longer passwords (that it previously
could support).  I guess it'd check for the possibly-lowered
plaintext_length at the start of crypt_all() and call a re-init function
if so.  With GPU formats, there's a lot of work being done per
crypt_all() call, so this extra if/call will probably not cost much.

Alternatively, we could introduce a reinit() method or stipulate that
init() may be called a second time.  In fact, the latter is happening
now for formats that share an init() implementation - the dynamic
formats, some DES-based hash formats.

> Perhaps I could implement a check in clear_keys() that detects the change, and re-inits whatever is needed. That's the best I can think of right now (except for more core changes). This would theoretically even support adapting to the shorter length *within* an incremental run but that will be too slow to be useful I guess... hmmm but it might be useful for batch mode, between modes.

Yes, you're right about these aspects.  And yes, clear_keys() may be a
better place than crypt_all().

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.