-
Notifications
You must be signed in to change notification settings - Fork 139
Conversation
beecd66
to
080a57e
Compare
For now I looked only at the ChaCha changes. While for (1) the class in |
@ocheron Hi, mind taking another look? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not super familiar with the random part but think this is ok to add, with a few review comments.
module Crypto.Random.Types | ||
( | ||
MonadRandom(..) | ||
, MonadPseudoRandom | ||
, DRG(..) | ||
, PRG(..) | ||
, prgNewEntropy | ||
, prgNew |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer not to expose prgNewEntropy unless absolutely necessary. This function relies on its argument always returning requested length.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can remove it, but it's really just a convenience wrapper around prgNewSeed
, a typeclass method of the new PRG
class I'm adding in this PR. Anyone can recreate prgNewEntropy
themselves, so I'm not sure hiding it achieves anything in terms of avoiding misuse.
For prgNewSeed
, I basically copied the type signature of the existing ChaCha.initializeSimple
. Its implementation checks the length of the seed, but the type signature does not make this obvious. So I could modify both of these to return a CryptoFailable StateSimple/gen
instead - and then this type would propagate through into prgNewEntropy
. How does that sound? That should make it much more obvious that anyone implementing prgNewSeed
should explicitly check the length.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For example, in 9922075
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think the real convenience wrapper is prgNew
, without a CryptoFailable
result.
MonadRandom
is supposed to always return the requested length.
So if the PRG
and MonadRandom
instances are implemented correctly, a result will be generated.
Misuse comes only with prgNewEntropy
.
People not wanting getRandomBytes
, or wanting length larger than minimum, can call the PRG
methods directly.
They will know best if the length requirement is always met or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the interests of getting this PR merged, I don't want to continue arguing over a minor point, and so I've un-exposed prgNewEntropy
as you wanted, and made prgNew
auto-unwrap the CryptoFailable
.
However, I still believe the old version is OK and more helpful for users. In Haskell, typeclass instances are chosen by the caller, so I don't see a fundamental usage/abuse/security difference between:
- letting the user implicitly select the instance of
MonadRandom
class inprgNew
, vs - letting the user explicitly select the
getEntropy
function inprgNewEntropy
Either of these could return the wrong length, but (a) the programmer can easily check the function they're using behaves correctly and (b) since 9922075 we mandate a length check in prgNewSeed
.
Arguably, the explicit version (2) is easier to check - with MonadRandom
(1) you have to look up the instance definition first, which could be a redirection to another function (e.g. MonadRandom IO
), so it takes two steps. This is why in my own code, I prefer to use getEntropy
explicitly and avoid the implicit MonadRandom IO
instance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want to merge initializeSimpleErr
like this.
Bytes after the 40th are ignored and don't contribute to the DRG.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ocheron It is the same as the current behaviour of initializeSimple
- as you can see in the diff I did not change the behaviour. How do you want to fix it, and shouldn't it be done in a separate PR?
ping @ocheron |
ping @ocheron I am still interested in getting this PR merged, can you elaborate on the next steps? |
Sorry I don't do Haskell anymore and have left the project. |
@ocheron OK, thanks for the response and best of luck with whatever you're doing now! @vincenthz can you take over and have a look please? |
Ping @vincenthz again - I've also added a generic |
archiving repository |
This PR adds a
PRG
typeclass that supports initialising from a seed (which the system DRG cannot implement), and exposes raw functionality in ChaCha so other people can implement their own PRGs.Motivation: I'm writing a network simulator that can run simulations deterministically with arbitrary suspend-resume capabilities. To do this, I need to be able to suspend the state of the PRG and write it to disk, then read it later. I appreciate this might be a controversial feature so didn't include it in this PR, but have merely exposed the functionality needed to easily write my own PRG.
If you like, I can also add a commit that includes a
ChaChaPureInsecure
instance ofPRG
that usesByteString
and derives(Show, Read, Generic)
, etc for serialisation purposes. (UsingScrubbedBytes
is also possible for more security, but is more work as you have to write some of the instances by hand, I didn't get around to it yet.)