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 HC-128 RNG #74

Merged
merged 3 commits into from
Dec 21, 2017
Merged

Add HC-128 RNG #74

merged 3 commits into from
Dec 21, 2017

Conversation

pitdicker
Copy link

@pitdicker pitdicker commented Dec 14, 2017

This implements the HC-128 cryptographically secure RNG. See #53.

It is similar to ISAAC, but proven to be secure and (in many cases) faster.

I have been sitting on this code for a few weeks hoping that I could reduce the amount of unsafe code and some duplication. But that didn't work out yet, so I am just making a PR as it is.

@pitdicker
Copy link
Author

I should add that the output of this RNG matches the reference implementation. I have tested the first 65536 result with a couple of random seeds.

@dhardy
Copy link
Owner

dhardy commented Dec 15, 2017

This PR could probably be done directly against upstream? (Possibly it would leave some smaller details to fix later, but I think this would be easier than merging here then upstream.)

@pitdicker
Copy link
Author

Now that I see the direction you want to go with upstream, I will do that.
If you have an interest at looking at it already, that would be nice because I probably will not be able to make the PR today.

}

impl Hc128Rng {
pub fn init(seed: &[u32]) -> Hc128Rng {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we were trying to use fixed-length byte arrays instead of slices of u32? Of course it may be easier to convert from byte arrays in from_rng and from_seed but why is this variable length? (It would at least be nice to have documentation of what is expected to be passed to init.)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use u32's here because that is what the algorithm uses, and convert in from_seed and from_rng. It was fixed-length before using le::convert_slice_32.

But you are right, I should add documentation.

One thing I noticed about le::convert_slice_32 is that it assumes seed is aligned as [u32], while it only is an [u8]. Something to fix or give a big warning.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Yes, it's quite possible I messed up the le functions.

let (p, q) = self.t.split_at_mut(512);
// FIXME: it would be great if we the bounds checks here could be
// optimized out, and we would not need unsafe.
// This improves performance by about 7%.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this is because p and q are slices, hence the compiler doesn't know the length? You could try using array_ref instead maybe, though it's not much of a solution. Or use t directly.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have tried something like 20 variants. In some of them p and q where arrays, and t did not exist. If have tried macro's instead of functions, and various manual bounds checks in update. But no luck convincing LLVM they are unnecessary yet 😞 . I can't be much more precise, because I did not save or document all tries. Maybe expecting it to optimize out 7 bounds checks is to much to ask. It already reduces that down to 1 on average (but there is not any specific one, that is the average over the whole update function).

@dhardy
Copy link
Owner

dhardy commented Dec 15, 2017

I just created rust-random#209; hopefully this can land on top of that (maybe add convert_slice_32 to this module for now; I'm still not sure about the le module).

@pitdicker
Copy link
Author

Great! That should make it much simpler (for me).

@dhardy
Copy link
Owner

dhardy commented Dec 21, 2017

Might as well merge this I guess.

@dhardy dhardy merged commit eaeee11 into dhardy:master Dec 21, 2017
@pitdicker
Copy link
Author

I should have said I converted initto use an array as you suggested, but was not ready to add the commit yet. I will make a PR together with a change to the le functions to correct alignment.

@pitdicker pitdicker deleted the hc-128 branch December 21, 2017 13:12
@dhardy
Copy link
Owner

dhardy commented Dec 21, 2017

Ah, ok. Probably the le stuff should be moved into a different file, but whether that should be called le, conversions, utils or something else I don't know. Also not sure whether it should be minimal or include a fair number of functions.

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

Successfully merging this pull request may close these issues.

2 participants