Triplesec combines 3 ciphers (now 2), incase a vulnerability in one is found. Maybe it would be a fun project to build a PRNG that combines multiple PRNGs.

Here, an unnecessarily complicated, difficult to implement, snakeoil solution.

  1. A common block of memory, “the pad”, is overwritten once with yarrow, blum blum shum, and fortuna, on their own, using a seed from the system CSPRNG, and then the block itself for the other two runs.
  2. A repeating yarrow write-head reads sequential blocks and overwrites them.
  3. A blum-blum shum write-head, starting at the first block, overwrites it, then calculates its next jump (if the calculation has not finished, it moves to the next block of memory). The calculation uses a full-cycle linear congruential generator mapped onto blocks of memory, and whatever bytes it read.
  4. A fortuna write-head starts at the first block, overwites it, and calculates its next position using a full cycle linear feedback shift register, and whatever bytes it wrote.
  5. Output bytes from the PRNG are the XOR of all 3 write-heads at the time of the call to the socket. Writes to the pad can be mutexed or not, your choice. If you so choose, the system CSPRNG can insert into a position every time a read is called (the position is the inverse of wherever the yarrow head is at the time)

So, goroutines, or rust?


global pad # sized appropriately for both the LGC & LFSR to be full-cycle given parameters.
global hY, hBBS, hF # can be xored together
global yarrowposition # used for inserting the system CSPRNG into the block.
def init(): # overwrite the pad with each, once.
  pad = yarrow(seed=os.csprng())
  pad = blumblumshum(vars=pad, seed=pad)
  pad = fortuna(vars=pad, seed=pad)
  return pad

def headYarrow():
  while True:
    for yarrowposition, byte in pad:
      hY = yarrow(byte)
      pad[yarrowposition] = hY

def headBlumBlumShum():
  position = 0
  while True:
    defer position = jumpFC_LCG(pad[position])
    hBBS = blumblumshum(pad[position])
    pad[position] = hBBS
    yield position or position += 1

def headFortuna():
  position = 0
  while True:
    hF = fortuna(pad[position])
    pad[position] = hF
    defer position = jumpFC_LFSR(pad[position])
    yield positiion or position += 1

def jumpFC_LCG(position):
  return linearCongruentialGeneratorModulo(position)

def jumpFC_LFSR(position):
  return linearFeedbackShiftRegisterModulo(position)

def readParanoidRNG():
  yield hY ^ hBBS ^ hF

def ReadParanoidRNG(length):
  pad[-yarrowposition] = os.CSPRNG() # mess up the readers
  bytes = readParanoidRNG()
  return bytes