Repository navigation
CHANGE: Re-enable ReseedingRng #1748
Description
Activity
Thanks for the report; it's been hard to find real uses of
ReseedingRngoutside ofrand. I might reconsider if there are more requests, but find it unlikely given that most users will not needReseedingRngand its removal significantly simplifiedrand.For now, I'd recommend either copying
ReseedingRngfrom before #1722 or merging its functionality into your RNGs as we did withThreadRng.Could it be an option to expose
BlockRng<ReseedingCore>>as sayReseedingStdRng? I knowStdRngis sufficient usually, but sinceThreadRngexists, I am strongly tempted to reproduce the "best practice" when a Send + Sync alternative is desired.Or something like
struct ThreadRngCore(BlockRng<ReseedingCore>);.ReseedingRngwas a clunky solution to mimicThreadRngbehavior so will not be necessary if theThreadRnglogic is accessible.So, something like this?
pub struct ReseedingStdRng { ... } impl ReseedingStdRng { pub fn new() > Result<Self, SysError>; pub fn reseed(&mut self) > Result<(), SysError>; } impl TryRng for ReseedingStdRng { type Error = Infallible; // ... } impl TryCryptoRng for ReseedingStdRng {}
This should be a reasonable addition: it can replace most of the internals of
ThreadRngwithout unnecessary parametrisation.Would someone like to make a PR? (Not a promise, but I don't currently see a reason to block this.)
Reacted by LiosKThreadRngdoes not useReseedingRnginrandv0.10. It no longer needs it since the new implementation gets number of generated blocks from the ChaCha cipher core.We could re-introduce
ReseedingRng<R: SeedableRng>, but I think it should be done in a separate RNG crate.Since every change has a cost (even if just API churn or extra code size), every change must have sufficient motivation.
Every part of public API also has cost. Both for users and maintainers.
Will try to make a PR later.
ReseedingRng<R: SeedableRng>
No. To making it generic over
Rwe'd needR: block::Generator + SeedableRngand then we'd want theblock::CryptoGeneratortrait again. Much simpler to just haveReseedingStdRng.But you are right that even this simpler version probably doesn't need to be in
rand. Why not put your own copy ins2n-quic? I doubt many crates would useReseedingStdRng(but let us know if yours does).I meant the less efficient but much simpler variant of
ReseedingRngwhich checks the reseeding condition on eachnext_u32/u64/fill_bytescall instead of doing it on each block generation. IIRC I even seen it implemented internally in some crate while researching howReseedingRngused in the wild.- added a commit that references this issue
on Feb 25, 2026 - added 2 commits that reference this issue
on Mar 8, 2026 FYI, I published the
reseeding_rngcrate - a simplified reimplementation ofReseedingRngfor use withrandv0.10. I went with aTryRng-based approach that checks the reseeding condition on every call totry_next_u32/try_next_u64/try_fill_bytes, since it makes for a nicer API.Performance is the obvious concern, but benchmarking shows the overhead is pretty negligible - under a nanosecond per call, probably just a couple of extra machine instructions. The catch is that a nanosecond can still eat up ~20% of total call time, so it's not nothing.
Also, working on this made me appreciate how ergonomic the super/sub trait relationships in v0.10 are for this kind of thing - really nice design!
EDIT (addition): I just noticed that the
Generator-based implementation can sometimes be noticeably slower than theTryRng-based one when callingtry_fill_bytes()with large buffers like[u8; 1024 * 4]. This is presumably because theTryRng-based one checks the reseeding condition once pertry_fill_bytes()call usually, while theGenerator-based one checks it multiple times.- added a commit that references this issue
on Mar 29, 2026 - added a commit that references this issue
on Apr 17, 2026 - added a commit that references this issue
on May 4, 2026 @WesleyAC I hadn't expected to see a frequently-reseeding
ChaChagenerator overJitterRng. I guess it's good enough as an additional source of entropy, though we don't recommend it as a primary source of entropy (I'm sure you've already seen #699). But isReseedingRngthe right tool for this anyway? In-lining its code wouldn't add much complexity and would allow mixing the old output with a fresh seed.If we do make some form of reseeding-rng public in
rand, I don't believe we'd make it as configurable as the oldReseedingRng.Btw, inlining
ReseedingRngis easy, but writing tests to make sure it's properly working is not straightforward because it's indeterministic. That is one reason why users want to rely on a credible external crate.- added a commit that references this issue
on Jun 28, 2026 See #1828.
Summary
How does this affect the API / end-user? (Include API-breaking changes, value-breaking changes and API additions.)
rand's user can access theReseedingRngstruct that was previously avaible untilrandv0.10. This struct has been removed in v0.10. A related issue: #1721.Details
What changes does this require internally?
It might be as simple as reverting this PR: #1722.
Essentially, we would like this struct to be made available, instead of be deprecated completely.
Motivation
What is the motivation for this change?
Since every change has a cost (even if just API churn or extra code size), every change must have sufficient motivation. This is arguably the most important part of the RFC.
We use
randfor generating random bytes in s2n-quic: a rust implementation of the QUIC protocol. We userandfor both public and private generator. We will add more details about how we useReseedingRngin our own issue: aws/s2n-quic#2986.Alternatives
Which alternatives might be considered, and why or why not?
One alternative is to implement a
ReseedingRngwrapper in s2n-quic for our own usage. I think having it fromrandis more preferable.