Early std.crypto

Piotr Szturmaj bncrbme at jadamspam.pl
Tue Oct 25 14:12:45 PDT 2011


Martin Nowak wrote:
> On Tue, 25 Oct 2011 09:43:48 +0200, Piotr Szturmaj
> <bncrbme at jadamspam.pl> wrote:
>
>> Martin Nowak wrote:
>>> I have to say though that I like the current struct based interface
>>> much better.
>>>
>>> struct Hash
>>> {
>>> // enhanced by some compile time traits
>>> enum hashLength = 16;
>>> enum blockLength = 0;
>>
>> The reason why hash and block length are runtime variables is that
>> some hash functions are parametrized with variables of great
>> amplitude, for example CubeHash may have any number of rounds, and any
>> size of block and hash output.
>>
>>> // three interface functions
>>> void start();
>>> void update(const(ubyte)[] data);
>>> void finish(ref ubyte[hashLength] digest);
>>> }
>>
>> There, it is:
>>
>> reset();
>> put();
>> finish();
>>
> Reset does two different things depending on the internal state. Not so
> good.

I think that's negligible, but it may be "unbranched" easily.

>> The put() function makes hash implementation an OutputRange.
>>
>>> You wouldn't need the save, restore functions.
>>
>> They're not needed. They only serve as speed optimization when hashing
>> many messages which have the same beginning block. This is used in
>> HMAC, which is:
>>
>> HMAC(func, key, message) = func(key ^ opad, func(key ^ ipad, message));
>>
>> when func supports saving the IV, the first parts are precomputed,
>> when not HMAC resorts to full hashing. This optimization is also
>> mentioned in HMAC spec.
>>
> If hash contexts were value type you could simply do.
> auto saved = hash_ctx;
> Or alternatively one could add a 'save()' function to an isSaveableHash(H)
> concept.

Yes, I thought about that, but current way is faster because only 
initialization vector is saved, and api name emphasises it. General 
save() on SHA512 would need to copy IV and 80 ulongs (internal state).

>>> Some unnecessary allocations could go away.
>>> Most important instances would have less mutable state.
>>
>> Could you specify which ones, please?
>>
> Basically every 'new' in std.hash.crypto.base but especially the ones in
> hash(T) and hashToHex(T).

Yes, this will be fixed.

>>> You could probably parameterize a Merkle Damgård base with free
>>> functions for the transformation.
>>
>> What would be the difference from current class parametrization?
>>
> Just wanted to point out a specific alternative if code reuse is of a
> concern.
> If not using classes you need a way to inject the transformation which
> could
> be done like.
> alias MerkleDamgard!(uint, 5, 80, 16, 20, sha1Transform) SHA1;

Either way this function must be written. Either as free function or as 
class method. I don't think someone would use transformation function 
directly.

>>> A dynamic interface can be obtaines by templated instances similar to
>>> what std.range does.
>>
>> Could you elaborate? I don't know exactly what do you mean. Function
>> templates?
>>
> http://www.digitalmars.com/d/2.0/phobos/std_range.html#InputRange
> DynamicAllocatorTemplate at
> https://github.com/dsimcha/TempAlloc/blob/master/std/allocators/allocator.d
>
> These are to support cases where you either want a stable ABI or
> have a template firewall for scalability issues (e.g. could be sensible
> for the HMAC implementation although not really necessary).
>

I will look into it. Thanks!


More information about the Digitalmars-d mailing list