<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hacker News: strenholme</title><link>https://news.ycombinator.com/user?id=strenholme</link><description>Hacker News RSS</description><docs>https://hnrss.org/</docs><generator>hnrss v2.1.1</generator><lastBuildDate>Mon, 28 Sep 2026 13:08:04 +0000</lastBuildDate><atom:link href="https://hnrss.org/user?id=strenholme" rel="self" type="application/rss+xml"></atom:link><item><title><![CDATA[New comment by strenholme in "AMD's random number generator can't generate a 0?"]]></title><description><![CDATA[
<p>>>>when I tried it in the latest version of clang on godbolt, that it is eliminating the seeding of the entropy pool<<<<p>This is an unverified claim.  My own testing does not show TCC, GCC, nor clang “optimizing out” the code using uninitialized memory as an entropy pool.<p>The full test is here: <a href="https://github.com/samboy/MaraDNS/tree/master/deadwood-github/sqa/test_uninit" rel="nofollow">https://github.com/samboy/MaraDNS/tree/master/deadwood-githu...</a><p>In summary: On Ubuntu, and in clang at higher levels of optimization, the uninitialized memory is made 0s, but the cryptographic pseudo random number generator still runs.<p>Tests have been done against TCC, GCC, clang, as well as GCC and clang in Cygwin.  As an aside, uninitialized memory does seem to give a little bit of entropy with GCC in cygwin, which indicates it probably did back in 2007 when I originally wrote that code (it doesn’t these days with clang with optimization, nor in Ubuntu, which is why I use clock_gettime() as a second possible source of entropy instead of uninitialized memory)<p>I take claims of security holes in my software seriously, and this isn’t the first time someone made a claim of a real-world security problem, I tested the claim, and was unable to reproduce the alleged security hole in my code.</p>
]]></description><pubDate>Fri, 25 Sep 2026 18:51:40 +0000</pubDate><link>https://news.ycombinator.com/item?id=49848441</link><dc:creator>strenholme</dc:creator><comments>https://news.ycombinator.com/item?id=49848441</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49848441</guid></item><item><title><![CDATA[New comment by strenholme in "AMD's random number generator can't generate a 0?"]]></title><description><![CDATA[
<p>>Entropy is merely an estimate of the effective size of the input space, ie how hard an attacker would have to work to exhaustively search it.<p>Exactly!  Let me give you a real-world case where I estimated entropy:<p>I ran a bunch of clock_gettime() calls and then looked at the delta time between calls.  Just eyeballing the deltas, I decided that just running clock_gettime() by itself wasn’t giving me enough entropy (the time differences would jitter between two delta values in a most predictable manner).  So I updated the code to initialize then destroy an instance of the CSPRNG I use in the code between clock_gettime() calls.  Looking at the deltas after doing that, I saw the deltas in an unpredictable fashion, alternated between over a dozen different values.  That in mind, I decided a single call to clock_gettime() gives one 1 bit or more of entropy.<p>I did the calculations using Cygwin, Ubuntu 26, and an Alpine 24 Docker container, using an x86_64 chip.  In all three cases, looking at the deltas showed at least one bit of entropy per call.  So I have the code do 112 calls and add the nanosecond timestamps to my entropy pool.<p>Now, it’s possible that on a Raspberry Pi the calls will be much more predictable, so I can only say things look nice and random on an x86_64 system.  Since my code is open source, I can’t control what systems people will compile my code on (I’m pretty sure someone in China has probably already made a RISC-V compile of my code, but they aren’t telling me about it).<p>That leads us to: >>>A hash is as secure as its _strongest_ entropy source <i>provided that none of the inputs can snoop on the others</i><<<<p>My code <i>also</i> uses /dev/urandom to seed some of the entropy pool.  So, if there’s a system out there where clock_gettime() is really coarse and not a good source of entropy, we’re still OK if /dev/urandom is good [1]<p>In terms of entropy, I would say that the best attacks out there are maybe 80 bits.  We know 40 bits is hideously insecure these days (e.g. the ColdCard incident), that large companies have solved problems with about 64 bits of entropy, so I would guesstimate that 100 bits of entropy is beyond even big money governments right now.  So, I don’t need to know the exact amount of entropy my entropy pool has; if it has 100 bits of entropy or more, it’s safe for the time being (I would go for 256 bits of entropy for things where we don’t want people to be able to decrypt things later on, but I only use my CSPRNG for numbers which only have to be secure for a couple of minutes at most). [2]<p>[1] This was not always a guarantee on Raspberry Pi.  There were issues before the 5.6 Linux kernel where the entropy pool was drying up and people were using things like haveged to try and keep the entropy pool replenished.<p>[2] Because of limitations in the DNS protocol, an attacker can brute force things with about 28 bits of effort.  Which <i>is</i> a big problem but there are spoof mitigations I use.</p>
]]></description><pubDate>Wed, 23 Sep 2026 17:32:57 +0000</pubDate><link>https://news.ycombinator.com/item?id=49819642</link><dc:creator>strenholme</dc:creator><comments>https://news.ycombinator.com/item?id=49819642</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49819642</guid></item><item><title><![CDATA[New comment by strenholme in "AMD's random number generator can't generate a 0?"]]></title><description><![CDATA[
<p>>>>we (and I do not exclude myself from this category) are extraordinarily bad at sufficiently imagining the failure paths that our code might take and making code work handle failure cases correctly<<<<p>The way I somewhat work around this with the newer coLunacyDNS code (from 2020) is by using `-DGCOV` and `gcov` to check the code coverage when running the automated SQA tests for the code.  I can’t cover every single failure that could be caused by sanity tests in the C code, but I can cover pretty much all (99.53%) other code.<p>>>>But it's not 2005; it's 2026, and this change in compilers has been heavily advertised, discussed, complained about for well over a decade.<<<<p>My code compiles to the C99 standard (-std=c99 and only two syscalls not defined in POSIX) [1].  This in mind, compiler makers have a responsibility to make sure that their compilers, no matter what changes they introduce to them, conform to the C99 spec when compiling with the -std=c99 flag. [2]<p>This means that when I interact with people working on compilers, I bring out the C99 spec and then use that to determine whether it’s a bug in my code or a bug with the compiler.  In this particular case, the C99 spec said it results in undefined behavior when “The value of the object allocated by the malloc function is used”, so that’s a bug with my code.<p>The thing about standards is this: A given piece of C code, if standards compliant, should, when compiled, act a given way with any compiler conformant with that standard.  C developers writing C99 code shouldn’t have to look at any development or document which exists after 1999 to determine whether their code will act a given way.  C compiler writers shouldn’t be telling C99 developers “well, you should know about this 2021 change to the C compiler”.  They should instead say, “well, if you look at this page of the C99 spec, that behavior is undefined so we have no obligation to implement it the same way GCC does”.<p>Standards correct C99 code written in 2005 should behave the same way when compiled in 2026 as it did in 2005.<p>This discussion is like the fights guys get into when playing wargames where they argue whether a given move in the game is legal or not.  When this happens, the correct thing to do is to look at the reference manual and see what that says.<p>>>>it's okay to seed an entropy pool with uninitialized memory in 2005 is maybe defensible<<<<p>Back when I made that decision, clock_gettime() was not universally implemented (it wasn’t implemented on MacOS), so my options for having some kind of entropy for the XOF should /dev/urandom have issues were very limited.  I’ve since updated the code to use clock_gettime(); the Windows port will instead use the non-portable GetSystemTimeAsFileTime() (ghosts of embrace/extend/extinguish). [3]<p>>>>cryptographers keep complaining that we broke their code by turning their obfuscated dataflow-based if statement into an actual if statement<<<<p>The cryptography I use, as is typical for post-AES cryptography, makes sure that the cryptographic core doesn’t use any control flow statements, as seen in this compact representation of that code: [4]<p><pre><code>  #define b(z) for(c=0;c<z;c++)
  uint32_t c,e[42],f[42],g=19,h
  =13,n[45],i,j,k;void m(){j=0;
  b(12)f[c+c%3*h]^=e[c+1];b(g){
  i=c*7%g;k=e[i++];k^=e[i%g]|~e
  [(i+1)%g];j=j+c;n[c]=n[c+g]=k
  >>j%32|k<<-j%32;}for(i=39;i--
  ;f[i+1]=f[i])e[i]=n[i]^n[i+1]
  ^n[i+4];b(3)e[c+h]^=f[c*h]=f[
  c*h+h];*e^=1;}
</code></pre>
[1] The code also assumes that /dev/urandom returns a random stream of bytes, a behavior which POSIX doesn’t specify (newer POSIX <i>finally</i> gives us randomness with getentropy() but that spec is too new for me to assume it’s widely implemented)<p>[2] Until about two years ago, -std=c99 wasn’t needed; C99 code happily compiled as recently as 2022.<p>[3] Let me make this crystal clear: I use both /dev/urandom and looking at jitter with clock_gettime() in the entropy pool my XOF PRNG uses.  Should one of those not have enough entropy, the PRNG is still as secure as the other source of entropy.<p>[4] I very rigorously made sure that k>>j%32|k<<-j%32 trick works to do a bit rotate while being C99 standards compliant because clang broke an earlier version of this bit rotate at some optimization values; note that j and k are uint32_t variables.  Looking at the relevant parts of the standards show this trick only works when the modulo is a power of 2.
The production code either uses x>>r|x<<(32-r)%32 or this:<p><pre><code>  r = ((i * (i + 1)) / 2) % DWR_WORDSIZE;
  // Other code not shown
  if(r > 0 && r < DWR_WORDSIZE) {
                        A[i] = (x >> r) | (x << (DWR_WORDSIZE - r));
                } else {
                        A[i] = x;
                } 
</code></pre>
The “if” isn’t a security issue because r has a predictable value which we assume the attacker already knows.</p>
]]></description><pubDate>Wed, 23 Sep 2026 11:00:31 +0000</pubDate><link>https://news.ycombinator.com/item?id=49814199</link><dc:creator>strenholme</dc:creator><comments>https://news.ycombinator.com/item?id=49814199</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49814199</guid></item><item><title><![CDATA[New comment by strenholme in "AMD's random number generator can't generate a 0?"]]></title><description><![CDATA[
<p>I’m getting similar findings:<p><pre><code>  #include <time.h>
  #include <stdio.h>
  #include <stdint.h>

  int main() {
        struct timespec foo;
        int z;
        uint8_t buffer[512];

        for(z=0;z<128;z++) {
                clock_gettime(CLOCK_REALTIME,&foo);
                buffer[z * 4] = (foo.tv_nsec >> 24) & 0xff;
                buffer[z * 4 + 1] = (foo.tv_nsec >> 16) & 0xff;
                buffer[z * 4 + 2] = (foo.tv_nsec >> 8) & 0xff;
                buffer[z * 4 + 3] = (foo.tv_nsec) & 0xff;
        }
        for(z=0;z<512;z++) {
                printf("%02x ",buffer[z]);
                if(z % 16 == 15) {puts("");}
        }
        return 0;
  }
</code></pre>
(code is public domain)<p>Here, we see, running it on Windows, at least 1 but of entropy per clock_gettime() call.  For people who argue kernel entropy is somehow more secure, perhaps they should become familiar with how kernels before Linux 5.6 or so on some devices had issues where (u)random wouldn’t provide enough entropy to be really secure (people would use haveged to make sure they had enough entropy).</p>
]]></description><pubDate>Wed, 23 Sep 2026 01:33:06 +0000</pubDate><link>https://news.ycombinator.com/item?id=49810566</link><dc:creator>strenholme</dc:creator><comments>https://news.ycombinator.com/item?id=49810566</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49810566</guid></item><item><title><![CDATA[New comment by strenholme in "AMD's random number generator can't generate a 0?"]]></title><description><![CDATA[
<p>Not POSIX/C99 worship as much as the very practical issue that a lot of C code which used to compile just fine stopped compiling once compilers defaulted to using C23.  To use POSIX calls while compiling with -std=c99 (so I don’t have to update my code should C29 or what not come out) one needs to declare, for each .c file which uses a POSIX call, the version of POSIX the C file is compatible with.</p>
]]></description><pubDate>Wed, 23 Sep 2026 01:29:32 +0000</pubDate><link>https://news.ycombinator.com/item?id=49810551</link><dc:creator>strenholme</dc:creator><comments>https://news.ycombinator.com/item?id=49810551</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49810551</guid></item><item><title><![CDATA[New comment by strenholme in "AMD's random number generator can't generate a 0?"]]></title><description><![CDATA[
<p>>>>no security issues have ever been found in my code, and I test a lot. Therefore no bugs will ever exist in my code and we're all safe<<<<p>That’s not what I have said.  35 issues (mostly minor, but a couple of remote denial of service attacks) have been found with my code in the last 25 years; of those, none have come from the PRNG code I used.  Here in the age of AI, I get multiple security reports a year, so the code is being looked at.<p>With crypto, you can never know for sure the code doesn’t have weaknesses, but one can have confidence in code and algorithms which have been around for years without any weaknesses discovered in them.<p>My question is: If code being around for years doesn’t build confidence in it being secure, what would it take to build confidence in the code.<p>What you’re seeing here is two schools of thought: One is the issue with using uninitialized memory, which yes does result in undefined behavior as per the C99 spec—but, back two decades ago when I made that decision, GCC was the only compiler of significance (clang was just released but was not widely used until years later) and its behavior was to put randomish data in undefined allocated memory.<p>The other is the notion that only Linux Kernel developers can develop a secure PRNG, and obviously I find that attitude very condescending and arrogant.</p>
]]></description><pubDate>Wed, 23 Sep 2026 01:06:10 +0000</pubDate><link>https://news.ycombinator.com/item?id=49810382</link><dc:creator>strenholme</dc:creator><comments>https://news.ycombinator.com/item?id=49810382</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49810382</guid></item><item><title><![CDATA[New comment by strenholme in "AMD's random number generator can't generate a 0?"]]></title><description><![CDATA[
<p>I concede the C99 specification (which I now have a copy of), on page 490 (502 of the PDF) states “The behavior is undefined in the following circumstances:” this is followed by a long list, and on page 501 (page 513 of the PDF) it says, one case where behavior is undefined is when “The value of the object allocated by the malloc function is used”<p>It’s not clear whether that is the memory location malloc() returns or the memory pointed to by malloc(), but based on the next item in the list of cases where behavior is undefined, we have “The value of any bytes in a new object allocated by the realloc function beyond the size of the old object are used [results in undefined behavior]”.<p>The good news is that, as Taek and sltkr have pointed out elsewhere in the thread, clock_gettime() gets us a tiny bit of entropy, not perfect, but better than nothing.  clock_gettime() is also POSIX compliant, although I remember about 15 years ago macOS didn’t support clock_gettime() (I checked, and it does these days).<p>getentropy() will become better than /dev/urandom for kernel level random numbers, but the problem is that getentropy() was only standardized and added to POSIX in 2024—too recent for me to feel 100% sure it’s widely implemented.  And, yes, /dev/urandom (like chroot(), like sergroups()) isn’t defined in POSIX but it’s widely used.</p>
]]></description><pubDate>Tue, 22 Sep 2026 22:25:51 +0000</pubDate><link>https://news.ycombinator.com/item?id=49809111</link><dc:creator>strenholme</dc:creator><comments>https://news.ycombinator.com/item?id=49809111</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49809111</guid></item><item><title><![CDATA[New comment by strenholme in "AMD's random number generator can't generate a 0?"]]></title><description><![CDATA[
<p>Neither one is last time I looked.  I’m a lot more uptight about POSIX compliance with code that needs to compile than I am with code that just needs a special /dev file to run, for the simple reason, when using POSIX during the compile stage, I can place the blame on GCC and/or clang if the program doesn’t compile when my program is POSIX and C99 compliant (I was, like many, burned by the C23 changes which made a lot of code which previously used to compile no longer compile).<p>I actually at one time had a Windows binary which would use Windows proprietary calls to make a “urandom” file (secret.txt was its name) so people could have good entropy on systems using the exact same interface as fopen("/dev/urandom","rb") (i.e fopen("secret.txt","rb")) without needing an actual /dev/urandom.</p>
]]></description><pubDate>Tue, 22 Sep 2026 18:45:30 +0000</pubDate><link>https://news.ycombinator.com/item?id=49806177</link><dc:creator>strenholme</dc:creator><comments>https://news.ycombinator.com/item?id=49806177</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49806177</guid></item><item><title><![CDATA[New comment by strenholme in "AMD's random number generator can't generate a 0?"]]></title><description><![CDATA[
<p>“Software like GPG that doesn't trust what the OS gives you already do that”<p>Exactly.  The people who are so adamant that one shouldn’t roll their own crypto are people who think we should just blindly trust the kernel to always return secure random numbers which haven’t been backdoored.<p>Now, in the real world, if they control the kernel’s RNG, they control a lot more than the RNG so any protection is an illusion.  But blindly trusting a kernel’s RNG is something that makes some people understandably uncomfortable.<p>The decision I made to include a secure random number generator as part of my code in 2007 was the exact same decision DJB made to include a secure random number generator with his code in 1999, and it’s a decision I stand by: It never has had a known security problem, the FUD claiming otherwise isn’t backed up by evidence, and it makes a lot of sense in cross-platform code which targets embedded systems.</p>
]]></description><pubDate>Tue, 22 Sep 2026 18:20:45 +0000</pubDate><link>https://news.ycombinator.com/item?id=49805833</link><dc:creator>strenholme</dc:creator><comments>https://news.ycombinator.com/item?id=49805833</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49805833</guid></item><item><title><![CDATA[New comment by strenholme in "AMD's random number generator can't generate a 0?"]]></title><description><![CDATA[
<p><i>If the optimizer sees that you're loading uninitialized memory, it can reason that since the result of uninitialized memory is garbage, doing any computation on that result is also garbage, and happily delete said computation as a result</i><p>This is an interesting assertion, and one that is easy enough to prove true.<p>Let’s take the following C code, which uses the same XOF algorithm (but not implementation) as my application (Deadwood):<p><pre><code>  #include<stdio.h>
  #include<stdint.h>
  #include<stdlib.h>
  #define b(z) for(c=0;c<z;c++)
  uint32_t c,e[42],f[42],g=19,h
  =13,n[45],i,j,k;void m(){j=0;
  b(12)f[c+c%3*h]^=e[c+1];b(g){
  i=c*7%g;k=e[i++];k^=e[i%g]|~e
  [(i+1)%g];j=j+c;n[c]=n[c+g]=k
  >>j%32|k<<-j%32;}for(i=39;i--
  ;f[i+1]=f[i])e[i]=n[i]^n[i+1]
  ^n[i+4];b(3)e[c+h]^=f[c*h]=f[
  c*h+h];*e^=1;}int main(int c,
  char**v){char*q=malloc(2);if(
  q==0)return 0;q[0]&=31;q[0]|=
  1;q[1]=0;for(;;m()){b(3){for(
  j=0;j<4;){f[c*h]^=k=(*q?255&
  *q:1)<<8*j++;e[c+16]^=k;if(!
  *q++){b(18)m();b(8){j=c;b(1)
  printf("%02x",(e[1+j%2]>>8*c)
  &255);c=j;if(c%2)m();}puts(
  "");return 0;}}}}}
</code></pre>
This code, as I’m sure the parent poster can clearly see, uses four bits of uninitialized allocated memory as its source of entropy.  As per the parent’s assertion, there should therefore exist a compiler whose optimizer will cause this XOF to not correctly run.<p>The above code can have one of the following possible 16 outputs:<p><pre><code>  0a5d51f3745c7266
  f84b051f67115f1a
  f87105c4ecfefe67
  92074ac8e1e7a42e
  1441ac245f288e18
  87023372e57ae001
  047a3ddd14209546
  340b2ff47c61172e
  bfb9289ed096f977
  dfd56a7a8d7d723e
  2151460954a80242
  6822335c6e0160dc
  3783ce3cae3d0774
  4e0156df46c00bac
  69795d939d211e7a
</code></pre>
If the above code has any but one of the above 16 outputs, this is a real world case where a C compiler, seeing uninitialized memory being used, optimizes out the code which uses said uninitialized memory as an input, and therefore will not output one of the above 16 possible words.<p>I’ve tested the above code in GCC -O3 and clang -O3; both generate one of the above 16 possible outputs (each one generating a different output).<p>If there really is a compiler out there which does “happily delete said computation”, which would give a different output than one of the 16 outputs above, please name that compiler, the version of said compiler used, and all compile-time flags used with said compiler.<p>While I’ve never heard of a real world case where a compiler would refuse to run code using uninitialized memory as yet another source of entropy for a secure PRNG, I do know of a real world case where a very nasty security hole was caused because someone incorrectly <i>removed</i> code using uninitialized memory as part of an entropy pool: CVE-2008-0166</p>
]]></description><pubDate>Tue, 22 Sep 2026 16:38:35 +0000</pubDate><link>https://news.ycombinator.com/item?id=49804054</link><dc:creator>strenholme</dc:creator><comments>https://news.ycombinator.com/item?id=49804054</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49804054</guid></item><item><title><![CDATA[New comment by strenholme in "AMD's random number generator can't generate a 0?"]]></title><description><![CDATA[
<p>Yeah, this comes off as a “they already are on the wrong side of the secure hatch” kind of attack.  A malicious hardware device with physical access to a victim’s computer can do a lot more than generate malicious entropy.<p>It’s like the attacks I occasionally see which are like “once we have administrator, we can attack the process because of this insecurity”.  Well, yeah, but once we have administrator, we can read the entire memory of the “vulnerable” process and completely control its output too.<p>I’ve seen in the real world attacks where things were insecure because the PRNG wasn’t given enough entropy (CVE 2008-0166, Coldcard, etc.).  I’ve never seen real world attacks where a PRNG was insecure from getting too much entropy.</p>
]]></description><pubDate>Tue, 22 Sep 2026 14:40:18 +0000</pubDate><link>https://news.ycombinator.com/item?id=49802109</link><dc:creator>strenholme</dc:creator><comments>https://news.ycombinator.com/item?id=49802109</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49802109</guid></item><item><title><![CDATA[New comment by strenholme in "AMD's random number generator can't generate a 0?"]]></title><description><![CDATA[
<p>The advantage of a secure XOF is that a malicious source of entropy needs to do a good deal more work than a simple XOR to generate controlled PRNG output (the attacker needs to do 2^n XOF operations to generate n bits of PRNG output, and that’s only if the attacker knows the output of all other sources of entropy—someone with that level of access can do far more effective attacks).<p>The sources of entropy can be correlated and won’t cancel out with a well designed secure XOF.  SHAKE-256 is an example of a secure XOF.</p>
]]></description><pubDate>Tue, 22 Sep 2026 14:19:08 +0000</pubDate><link>https://news.ycombinator.com/item?id=49801723</link><dc:creator>strenholme</dc:creator><comments>https://news.ycombinator.com/item?id=49801723</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49801723</guid></item><item><title><![CDATA[New comment by strenholme in "AMD's random number generator can't generate a 0?"]]></title><description><![CDATA[
<p>There are theoretical issues where a malicious source of entropy could control the PRNG output, but it’s not a very practical attack.<p><a href="https://blog.cr.yp.to/20140205-entropy.html" rel="nofollow">https://blog.cr.yp.to/20140205-entropy.html</a><p>Intel could much more easily compromise and attack systems than make an implementation of RdRand which is malicious in this manner.</p>
]]></description><pubDate>Tue, 22 Sep 2026 14:15:56 +0000</pubDate><link>https://news.ycombinator.com/item?id=49801664</link><dc:creator>strenholme</dc:creator><comments>https://news.ycombinator.com/item?id=49801664</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49801664</guid></item><item><title><![CDATA[New comment by strenholme in "AMD's random number generator can't generate a 0?"]]></title><description><![CDATA[
<p>Indeed, that’s a real attack.<p>From that page:<p>>>>what I'm advocating here, for security reasons, is a sharp transition between<p>* before crypto: the whole system collecting enough entropy;<p>* after: the system using purely deterministic cryptography, never adding any more entropy.<<<<p>Which is <i>exactly</i> how a XOF should be used, and how I used the XOF in my code.  A malicious source of entropy will need to perform 2^n operations to control n bits of the XOF’s output, and that’s assuming the malicious entropy source somehow perfectly knows the other entropy the XOF is using.</p>
]]></description><pubDate>Tue, 22 Sep 2026 14:03:40 +0000</pubDate><link>https://news.ycombinator.com/item?id=49801492</link><dc:creator>strenholme</dc:creator><comments>https://news.ycombinator.com/item?id=49801492</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49801492</guid></item><item><title><![CDATA[New comment by strenholme in "AMD's random number generator can't generate a 0?"]]></title><description><![CDATA[
<p>I know it’s a joke, but that code wouldn’t pass the DieHard tests.  That’s actually one of the tests I did with the XOF I used, a test I ran over 16 years ago.<p><a href="https://maradns.blogspot.com/2010/07/radiogatun32-passes-all-dieharder-tests.html" rel="nofollow">https://maradns.blogspot.com/2010/07/radiogatun32-passes-all...</a></p>
]]></description><pubDate>Tue, 22 Sep 2026 13:46:58 +0000</pubDate><link>https://news.ycombinator.com/item?id=49801241</link><dc:creator>strenholme</dc:creator><comments>https://news.ycombinator.com/item?id=49801241</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49801241</guid></item><item><title><![CDATA[New comment by strenholme in "AMD's random number generator can't generate a 0?"]]></title><description><![CDATA[
<p>Thanks for writing that code!<p>The point is this: Getting micro-timing won’t give us as much entropy as we want, but it will still give us entropy.  So it’s a perfectly good yet-another-source of entropy to feed in to an entropy pool (such as the input to a XOF).<p>If those Coldcard devices had used this code as one source of entropy, and this source of entropy was the only entropy still working, they never would had been compromised.<p>(I won’t update my 18-year-old PRNG to use this code, of course, since that code is now 18 years old and there are no known weaknesses in said code)</p>
]]></description><pubDate>Tue, 22 Sep 2026 13:40:04 +0000</pubDate><link>https://news.ycombinator.com/item?id=49801147</link><dc:creator>strenholme</dc:creator><comments>https://news.ycombinator.com/item?id=49801147</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49801147</guid></item><item><title><![CDATA[New comment by strenholme in "AMD's random number generator can't generate a 0?"]]></title><description><![CDATA[
<p>The nice thing about a secure XOF is that it doesn’t matter if the entropy given to the XOF is less than perfect.  If an XOF is given 10 different sources of entropy, and only one of them is secure, the XOF will remain secure. [1]<p>One reason why I don’t change the RNGs used in my code is because I <i>know</i> how dangerous playing with RNG code is.  For example, one implemention I wrote of the XOF—not one I used in production code, mind you—generated incorrect vectors, but only in clang and only at some levels of optimization.  Needless to say, I now have a test to make sure my XOF code generates correct vectors with both GCC and clang at multiple different optimization levels.<p>People have brought up CVE-2008-0166 in this thread, but the Coldcard incident from this year (where people literally lost millions of dollars) also comes to mind, so I’m aware how dangerous playing with RNG code is.<p>That’s why the code is basically the same code I had 18 years ago, and why I (as well as multiple people running AI-assisted security audits) have extensively tested that code.<p>The proof is in the pudding: No security issues have ever been found with the XOF PRNG, and it’s been nearly two decades.<p>(I also think “straw men” is being used incorrectly here; most likely the parent poster thinks I was implying that Linux’s /dev/urandom is insecure but the actual argument is that my code runs on a lot more than just Linux, and some of those systems could have an insecure /dev/urandom)<p>[1] As per <a href="https://blog.cr.yp.to/20140205-entropy.html" rel="nofollow">https://blog.cr.yp.to/20140205-entropy.html</a> as long as we’re not using a malicious source of entropy, but said malicious source will need to perform 2^n operations of the XOF to generate n bits of controlled output, and only in the case if said malicious entropy source can somehow know the output of the other entropy sources, especially since the XOF is seeded once then run indefinitely in my code.</p>
]]></description><pubDate>Tue, 22 Sep 2026 13:12:29 +0000</pubDate><link>https://news.ycombinator.com/item?id=49800740</link><dc:creator>strenholme</dc:creator><comments>https://news.ycombinator.com/item?id=49800740</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49800740</guid></item><item><title><![CDATA[New comment by strenholme in "AMD's random number generator can't generate a 0?"]]></title><description><![CDATA[
<p>I wouldn’t trust it as a sole source of entropy, but it can be one of multiple entropy sources to feed in to an XOF to get secure numbers.<p>The nice thing about using multiple entropy sources with a secure XOF is that the resulting entropy is at least as strong as the most secure entropy source given to the XOF.</p>
]]></description><pubDate>Tue, 22 Sep 2026 13:06:07 +0000</pubDate><link>https://news.ycombinator.com/item?id=49800665</link><dc:creator>strenholme</dc:creator><comments>https://news.ycombinator.com/item?id=49800665</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49800665</guid></item><item><title><![CDATA[New comment by strenholme in "AMD's random number generator can't generate a 0?"]]></title><description><![CDATA[
<p>The code I wrote has been used by embedded developers in embedded spaces; I remember getting a bug report from someone in China because they used my code in an embedded system before the timestamp was correctly set on said system.</p>
]]></description><pubDate>Tue, 22 Sep 2026 12:46:13 +0000</pubDate><link>https://news.ycombinator.com/item?id=49800354</link><dc:creator>strenholme</dc:creator><comments>https://news.ycombinator.com/item?id=49800354</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49800354</guid></item><item><title><![CDATA[New comment by strenholme in "AMD's random number generator can't generate a 0?"]]></title><description><![CDATA[
<p>From <a href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/getentropy.html" rel="nofollow">https://pubs.opengroup.org/onlinepubs/9799919799/functions/g...</a><p>“The intended use of this function is to create a seed for other pseudo-random number generators”<p>So, if I were to use genentropy() in a POSIX-compliant way, I would need to do what I already do: Use my own pseudo-random number generator.<p>The Debian openssl disaster (CVE 2008-0166, I remember it well) was caused because someone incorrectly patched secure code: Since the code used uninitialized memory as one of many entropy sources, which causes Valgrind to complain, they patched the code to not use uninitialized memory for entropy, but then accidentally disabled all other sources of entropy (except the 16-bit PID).  It was caused because the person making the patch didn’t fully understand why it was a <i>good</i> idea to, in that context, use code which Valgrind complained about. [1]<p>As an aside, here’s how I deal with those Valgrind errors:<p><pre><code>  #ifdef VALGRIND_NOERRORS
        /* Valgrind reports our intentional use of values of uncleared
         * allocated memory as one source of entropy as an error, so we
         * allow it to be disabled for Valgrind testing */
        memset(noise,0,512);
  #endif /* VALGRIND_NOERRORS */
</code></pre>
I do believe the Linux Kernel does have secure RNG code, but I also write code which has run on a lot of different systems and environments, including embedded ones, and some of them might not have a secure /dev/urandom.<p>[1] Debian has a lot of inflexible policies like this which can cause problems.  Another issue Debian has is they have a policy a given piece of code must always compile to the same binary on a given architecture.  That isn’t true with the unpatched version of my code, because the hash compression routine uses a 32-bit random number generated at compile time to avoid hash collision attacks (it also uses another 32-bit random number at runtime, and I make sure the hash compression values are never visible).  So the Debian version of my code was forced to be patched to be less secure.</p>
]]></description><pubDate>Tue, 22 Sep 2026 12:44:39 +0000</pubDate><link>https://news.ycombinator.com/item?id=49800339</link><dc:creator>strenholme</dc:creator><comments>https://news.ycombinator.com/item?id=49800339</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49800339</guid></item></channel></rss>