Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Grostl #8

Closed
newpavlov opened this issue Jan 11, 2017 · 5 comments
Closed

Add Grostl #8

newpavlov opened this issue Jan 11, 2017 · 5 comments

Comments

@newpavlov
Copy link
Member

Claimed by @gsgsingh93

Moved from #1:

I'm having some trouble with the types for Grostl. The issue is that the BlockSize depends on the OutputSize, and so I can't figure out to define the impl for Digest. If the Output size is 256 bits or less, then 512 is used as the block size. If the output size is greater than 256 bytes, then 1024 is used as the block size. Here's what I have right now, with the incorrectly hardcoded BlockSize as U512

extern crate digest;
extern crate generic_array;

use std::marker::PhantomData;

use digest::Digest;
use generic_array::{ArrayLength, GenericArray};
use generic_array::typenum::U512;

// TODO: This could also be U1024
type BlockSize = U512;

pub struct Grostl<OutputSize: ArrayLength<u8>> {
    phantom: PhantomData<OutputSize>,
}

impl<OutputSize: ArrayLength<u8>> Grostl<OutputSize> {
    fn new() -> Grostl<OutputSize> {
        Grostl { phantom: PhantomData }
    }
}

impl<OutputSize: ArrayLength<u8>> Default for Grostl<OutputSize> {
    fn default() -> Self { Self::new() }
}

impl<OutputSize: ArrayLength<u8>> Digest for Grostl<OutputSize> {
    type OutputSize = OutputSize;
    type BlockSize = BlockSize;

    fn input(&mut self, input: &[u8]) {
    }

    fn result(mut self) -> GenericArray<u8, Self::OutputSize> {
        GenericArray::default()
    }
}

Note that OutputSize is parameterized here because Grostl can output hashes between 1 and 64 bytes.

EDIT: I guess if there's no fancy solution with the generics that could get this to work, I could always just override block_bytes and block_bits in the trait, and just set a dummy BlockSize and not use it.

@newpavlov newpavlov mentioned this issue Jan 11, 2017
18 tasks
@newpavlov
Copy link
Member Author

newpavlov commented Jan 11, 2017

Overriding block_bytes and block bits will not work, as BlockSize used in the HMAC implementation to create key arrays.

Probably the easiest way to implement this will be to define two separate types with appropriate bounds on OutputSize. It will look approximately like this:

struct Grostl<OutputSize, BlockSize> {
   ...
    os: PhantomData<OutputSize>,
    bs: PhantomData<BlockSize>,
}

pub type GrostlSmall<OutputSize>
    where OutputSize: ArrayLength<u8> + Cmp<U512>,
          Compare<T1, U257>: Same<Less>
    = Grostl<OutputSize, U512>;

pub type GrostlBig<OutputSize>
    where OutputSize: ArrayLength<u8> + Cmp<U512>,
          Compare<T1, U256>: Same<Greater>
    = Grostl<OutputSize, U1024>;

Grostl will be private and user will only have access to GrostlBig and GrostlSmall (and other aliases based on them, e.g. Grostl256, Grostl384, Grostl512, etc.). After that you can implement Digest generically over OutputSize and BlockSize without worrying about incorrect combinations.

This approach is a bit hacky, but I couldn't get with a better one. Probably with specialization it will be possible to write it in a more general manner, but unfortunately I am not that familiar with it.

@gsingh93
Copy link
Contributor

Thanks, I'll do that. I have some questions though.

  • I'm assuming by T1 you mean OutputSize?
  • What's the point of the Cmp<U512> bound?
  • Shouldn't GrostlBig have be bounded by something like Compare<OutputSize, U513>: Same<Less> as well?

@gsingh93
Copy link
Contributor

Another point:

pub type GrostlSmall<OutputSize>
    where OutputSize: ArrayLength<u8> + Cmp<U512>,
          Compare<OutputSize, U257>: Same<Less>
    = Grostl<OutputSize, U512>;

With that code, I'd like to not make the Grostl struct public. Then the user is forced to use a type alias with the correct BlockSize; they can't mess that up. But I'm hinting the warning E0446 (rust-lang/rust#34537) about exporting a private type in a public API, which will soon be an error. I'll go ahead an make it public for now, but I'm wondering if you have any ideas on the issue.

@newpavlov
Copy link
Member Author

newpavlov commented Jan 12, 2017

I'm assuming by T1 you mean OutputSize?

Yes, it was leftover from testing code.

What's the point of the Cmp bound?

It allows us to write condition which uses Compare type operator. You can think about it as of typenum's implementation detail.

Shouldn't GrostlBig have be bounded by something like Compare<OutputSize, U513>: Same<Less> as well?

Yes, forgot to add upper bound.

With that code, I'd like to not make the Grostl struct public. Then the user is forced to use a type alias with the correct BlockSize; they can't mess that up. But I'm hinting the warning E0446 (rust-lang/rust#34537) about exporting a private type in a public API, which will soon be an error. I'll go ahead an make it public for now, but I'm wondering if you have any ideas on the issue.

I believe warning also gives a note with a way around it. You just need to place Grostl in the different module. I've used the same aproach for Streebog hash function.

@newpavlov
Copy link
Member Author

Closed in the #10.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants