Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20150507095033.GA22844@openwall.com>
Date: Thu, 7 May 2015 12:50:33 +0300
From: Aleksey Cherepanov <lyosha@...nwall.com>
To: john-dev@...ts.openwall.com
Subject: Re: get_binary_*() and get_hash_*() methods

On Tue, May 05, 2015 at 10:53:10PM +0300, Aleksey Cherepanov wrote:
> On Tue, May 05, 2015 at 09:07:49PM +0200, Frank Dittrich wrote:
> > On 05/05/2015 08:53 PM, Aleksey Cherepanov wrote:
> > > Formats provide get_binary_[0-6]() and get_hash_[0-6]() methods to
> > > john. If the algo in them is the same then it is possible to construct
> > > default cmp_all function. Are they used this way? Are they required to
> > > have the same algo? If so, why is not there default cmp_all() based on
> > > them?
> > 
> > I think many formats could just use fmt_default_binary_hash_0 -
> > fmt_default_binary_hash_6. Only formats which know that their hashes
> > have a non-random distribution in (certain parts of) their hashes should
> > need to implement their own binary_hash_[0-6].
> > But I think fmt_default_binary_hash_0 - fmt_default_binary_hash_6 are
> > jumbo specific, they don't exist in core.
> > 
> > But fmt_default_salt_hash just returns 0 (which is OK for saltless hashes).
> > So, we would need other "default" implementations for salt_hash_[0-6].
> 
> I don't touch salt_hash() yet.
> 
> I mean, we can implement cmp_all using other methods, something like
> the following:
> 
> static int cmp_all(void *binary, int count)
> {
>     int i;
>     int b = fmt_default_binary_hash_6(binary);
>     for (i = 0; i < count; i++) {
>         if (get_hash_6(i) == b)
>             return 1;
>     }
>     return 0;
> }
> 
> Though some formats define get_hash_6 as "return 0;".
> 
> Hm, get_hash_6 is in format's file. self is needed to access it in
> default implementation. But then it will not be inlined.
> 
> A macro may be used to insert the code of cmp_all into format's file.
> Though get_hash_6 gives only 31 bits, while raw-sha512 checks all 64
> bits in 1 check.
> 
> So I think my question about default implementation of cmp_all is
> solved.

I think I've got a wrong (or just suboptimal) solution. While it is
possible to use such function it should be better to use other algo.
Because john itself implements similar check.

In DES_bs.c in DES_bs_cmp_one :

/* Start by comparing bits that are not part of get_hash*() return value */
	CMP_BIT(30);
	CMP_BIT(31);


Does john always use binary_hash[]() methods before cmp_all()?

It looks like crypt_all() gets struct db_salt *salt? Is it the whole
db? The salt was set up by set_salt() so it should be the db, right?

Is the db intended to be checked by crypt_all()?

>From formats.h for crypt_all():

 * Returns the last output index for which there might be a match (against the
 * supplied salt's hashes) plus 1.  A return value of zero indicates no match.


BTW from formats.h for crypt_all():
 * For implementation reasons, this may happen to always compute at least
 * min_keys_per_crypt ciphertexts even if the requested count is lower,
 * although it is preferable for implementations to obey the count whenever
 * practical and also for callers not to call crypt_all() with fewer than
 * min_keys_per_crypt keys whenever practical.

Is it worth to put several implementations into crypt_all() to handle
different counts efficiently? I guess, it won't be noticeable in huge
attacks but implementing scenario with small chunks of work for
distribution it may affect performance, no? Though bigger crypt_all()
may reduce performance due to code cache, will not it?


Thanks!

-- 
Regards,
Aleksey Cherepanov

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.