Close

Initialisation: the ugly

A project log for Another Table-Based Stream Scrambler

Non-reversible, non-cryptographic scrambler for PRNG, 16 bits at a time.

yann-guidon-ygdesYann Guidon / YGDES 02/18/2025 at 19:290 Comments

Just to check some assumptions and see how entropy increases in the LUT, I added some popcount instructions in the braille display and run the test again...

  0  64  LUT:
 128  ⣈⣚⣬⣾⠱⠂⠭⠧⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
  80  ⢔⠰⠋⣯⢝⠯⡔⣰⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
Total 2000

On the first insertion, the LUT has already lost 48 bits !

The total must always remain 2048, by definition, so there is something very wrong.

I have an excuse, though: the initial pattern 0xAAAA is one of the "worst cases", which is not expected to happen. But the loss of bits is not acceptable.

...............

Aaaaand it was a simple stupid bug, it's solved.

Or not.

  8  112  LUT:
 113  ⣈⣚⣬⣾⠱⠂⠭⠧⠠⠄⠭⠄⠭⠉⠠⠍⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 120  ⢔⠐⠋⣏⢐⠣⡐⣰⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 121  ⣈⣚⣬⣾⠱⠂⠭⠧⠭⠭⠭⠭⠭⠭⠭⠭⠡⠭⠅⠭⠬⠉⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⢔⠰⠋⣯⢝⠯⡔⣰⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⣈⣚⣬⣾⠱⠂⠭⠧⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⢔⠰⠋⣯⢝⠯⡔⣰⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⣈⣚⣬⣾⠱⠂⠭⠧⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⢔⠰⠋⣯⢝⠯⡔⣰⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⣈⣚⣬⣾⠱⠂⠭⠧⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⢔⠰⠋⣯⢝⠯⡔⣰⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⣈⣚⣬⣾⠱⠂⠭⠧⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⢔⠰⠋⣯⢝⠯⡔⣰⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⣈⣚⣬⣾⠱⠂⠭⠧⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⢔⠰⠋⣯⢝⠯⡔⣰⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⣈⣚⣬⣾⠱⠂⠭⠧⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
 128  ⢔⠰⠋⣯⢝⠯⡔⣰⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭⠭
Total 2018

Now 30 bits are lost when the insertion algo gives up ...

.....

Aaaand I didn't validate an index at the start of the function ! It works so much better now !

----

FYI here is how the LUT looks when initialised with the AES LUT:

 LUT:
 141  ⠪⠳⡁⡼⡲⠿⢭⡻⠘⢺⠞⡳⢕⡷⡘⢥⣟⠘⠠⠁⢓⠷⣎⡓⢁⣾⢻⢯⢯⣓⣻⠾
 134  ⡼⣢⢳⢂⡙⣡⢂⡽⣋⣺⡗⡩⣿⠧⢇⢸⠜⣕⣆⢬⠣⢒⠤⣗⢤⣌⣮⢔⣱⠺⣣⢠
 134  ⠬⢟⡻⣽⢌⢋⠚⠖⢖⠞⢢⡟⠓⢿⡝⣤⣶⠜⡤⢕⢍⢵⡃⢹⠢⠹⣺⣨⢣⠙⡦⠍
 111  ⡀⠄⡖⢧⢑⠓⠶⢣⡐⡈⣩⢎⠔⠅⢚⣊⠾⠇⡫⠊⢒⢀⡡⢲⡵⣳⣃⠗⢩⢚⠕⠽
 121  ⠺⡁⣸⢃⢾⡔⠴⡊⢆⡋⡰⡶⣈⡪⠎⢐⢬⠪⢔⡛⡬⢮⣤⢛⡭⡑⠵⢳⢞⡗⢊⢄
 130  ⡴⠫⠸⢩⡠⠀⠨⣵⣽⠐⣵⣼⣙⢙⣪⡫⡮⡲⠍⣣⠦⣞⠯⡙⢗⡢⣅⡤⣍⡨⢄⣧
 123  ⢈⢨⣨⣷⣓⣒⠀⣻⣄⠣⣜⡥⢫⠛⡂⢅⢿⠥⢴⣹⡨⠂⠅⡿⣘⠨⢛⡜⠥⣏⠆⣐
 125  ⢨⠩⡔⢓⡎⠠⣇⣇⣢⢊⡟⣍⡇⡘⠂⢽⢡⣜⣗⢞⣝⣪⠃⠑⠁⠈⠋⣿⣂⢻⡳⢪
 137  ⡚⣥⢉⡄⠉⠋⠡⣴⡧⡯⠷⢏⣬⠤⣲⠏⢏⢤⢺⢗⣧⡾⣦⡝⢸⠴⢜⡭⢶⡉⠻⠻
 129  ⢎⠰⣔⢁⠼⡧⠒⣬⢷⠒⣕⡒⠝⢈⢅⣀⢲⠦⣹⣶⠟⣘⣰⠌⡌⣮⠽⡮⣯⡃⡶⣫
 118  ⠧⢰⢹⠚⡊⡚⠹⡂⡍⡡⡑⠆⢥⠔⣁⡬⡷⢢⢟⢫⠲⣔⡆⠲⣒⢉⡈⢍⣞⢴⡋⡹
 139  ⣼⢷⠮⣠⡞⠟⡣⡵⢦⣅⢪⢭⡹⡦⠐⣑⣊⡴⣫⠮⢠⢼⣾⣲⡸⠵⣥⡺⡪⣖⢼⡀
 125  ⡏⣚⣭⡸⣐⠕⠛⡖⣀⡌⠇⢖⢧⢜⠙⢦⢙⣰⠊⣭⠈⠼⡩⡏⠗⡣⢀⣝⣴⣃⡯⣂
 131  ⠰⠸⠩⡞⡿⢝⣑⠶⡉⡠⢝⠃⡢⢾⡅⡆⡕⠱⢵⠝⡺⠯⣏⣙⢋⢆⣡⢡⣌⡍⣷⣎
 130  ⢐⢱⢰⣸⡛⣈⡥⠉⣖⡱⡒⣩⢽⣆⢘⢌⣠⣋⣳⡎⣛⢇⡜⣱⢃⣦⠫⠭⣉⡐⠱⣯
 120  ⠏⣄⡓⢑⠄⣁⡾⡅⣚⣟⠿⢶⢮⠢⠖⡰⢱⠡⡱⣉⠌⡕⠳⡇⠭⢘⠑⠬⡄⣛⡽⠎
Total 2048

The variability is pretty great, from 111 to 141 bits per line. This gotta be smoothed by 500 insertions of 64-bit words...

 500  11  LUT:
 132  ⡖⢂⢔⣈⡆⢵⢛⣎⠱⠿⡈⠝⢻⡧⢍⢠⠻⠟⡤⠛⢹⣮⣈⢂⠩⠗⡦⠽⣻⠾⣞⠲
 126  ⣔⣢⢏⣧⢆⣑⣒⡼⡈⣳⢤⢼⠫⠦⠗⣤⢭⠌⡉⡧⠷⡉⠋⡋⠛⢝⢌⣙⠍⠊⢍⡩
 127  ⣙⢑⠆⣤⢧⣯⢷⢜⢓⠘⠤⣄⡴⠏⡛⣡⡴⣯⣑⠓⠻⠠⠥⡷⡦⡦⣛⠛⢘⠰⠵⡒
 124  ⢜⡗⠖⣒⡄⢗⠳⡷⠱⢨⣅⠥⡘⡨⣊⠜⢫⣧⢟⢜⢝⢃⠑⡸⡍⠐⡾⡇⠃⡬⠇⣺
 125  ⢴⢎⡱⠐⡛⡀⣿⢂⢆⠶⣫⠸⢹⡞⢀⡷⡻⣁⠂⣫⠅⢡⢴⡙⡀⣏⣩⢠⣓⣾⡛⢑
 131  ⠚⢪⡌⠀⣳⡣⡈⡧⠔⠇⡠⢬⠊⢯⣵⠻⢋⣹⢛⣿⣗⣖⡛⢅⢲⡭⠲⢠⠗⡁⠿⣼
 136  ⡅⢒⣣⡋⢨⣾⠃⢆⢪⣬⢌⢴⠗⢜⣲⡻⡭⡱⣢⡁⡸⢽⠽⢼⡽⠳⣊⡏⢪⡹⠱⢝
 140  ⠏⣞⠷⠶⣍⡥⣹⠳⣍⢗⣽⠍⣈⣱⡖⡏⣿⢗⡃⠅⢨⠱⣳⢞⠀⡨⢾⣒⣶⡞⢈⡩
 118  ⡦⢊⢝⢾⠉⢧⠬⠪⢉⡽⡜⡠⡷⠘⢦⣁⢮⠬⠸⠇⡉⡟⡠⢃⠤⡈⠆⠻⠊⣟⣔⡧
 121  ⢋⢳⣑⣐⣔⡠⡉⡈⡟⣙⠺⢇⠺⢏⣢⠨⠉⠫⣥⣴⡵⣲⠀⠚⣦⣜⠈⠃⢫⡝⡏⡤
 126  ⠃⠘⡥⣙⢰⡿⢄⡰⠑⢘⡃⣝⡑⠯⢹⢅⣾⡧⢒⠪⣨⣐⠅⣿⣸⣉⡦⣖⢰⢥⡡⢶
 126  ⣭⢗⡳⡣⣪⠅⣩⣋⠐⡠⢎⢼⠔⡺⠖⣀⡰⢲⠯⠣⣯⡖⢖⢖⢍⡍⣔⣴⡲⠹⠘⢙
 129  ⡢⢾⠋⢏⠌⢆⣻⡧⠫⣈⠴⡔⡠⣻⠟⡞⠝⢍⡍⡇⢜⠊⠊⢓⣫⡺⢪⢈⡣⣅⡳⡮
 124  ⡱⡧⢣⡾⡐⢱⣚⠫⢦⢘⠼⢅⢊⠌⡇⢏⠐⠱⣱⡘⣹⡭⣯⡱⣥⠆⠖⠍⣟⡒⢔⢈
 129  ⣔⣬⡘⡣⡌⢜⢝⡮⠹⠕⢙⢲⣱⣡⠉⠌⠩⠧⢝⠤⡠⢷⣟⠚⣞⣐⡠⣟⠿⣘⡱⢱
 134  ⢸⡴⣩⡹⢒⣆⡆⠒⢢⡭⢏⡭⡐⣐⢛⢃⡝⢏⡰⢺⡍⡽⡢⣭⠵⠞⡒⣯⣝⢾⠑⢜
Total 2048

Well the distribution didn't budge significantly, so AES is a good start, requiring only a nominal number of insertions.

I also changed the way entropy is added, in case it's low quality.

int AddEntropy(uint64_t* p, uint64_t E, int index, int max_mask) {
  int i=Loop_AddEntropy(p, E, index, max_mask);
  if (i<0)
    return i;
  return Loop_AddEntropy(p, ~E, i, max_mask);
}

This doubles the effect of any call while also compensating for bad entropy (like very small numbers or a counter). And Loop_AddEntropy() now refuses to run if E=0.

Here is the LUT initialised with a counter (0 to 255 and complement):

LUT:
 128  ⣿⠀⣾⠁⣽⠂⣼⠃⣻⠄⣺⠅⣹⠆⣸⠇⢿⡀⢾⡁⢽⡂⢼⡃⢻⡄⢺⡅⢹⡆⢸⡇
 128  ⣷⠈⣶⠉⣵⠊⣴⠋⣳⠌⣲⠍⣱⠎⣰⠏⢷⡈⢶⡉⢵⡊⢴⡋⢳⡌⢲⡍⢱⡎⢰⡏
 128  ⣯⠐⣮⠑⣭⠒⣬⠓⣫⠔⣪⠕⣩⠖⣨⠗⢯⡐⢮⡑⢭⡒⢬⡓⢫⡔⢪⡕⢩⡖⢨⡗
 128  ⣧⠘⣦⠙⣥⠚⣤⠛⣣⠜⣢⠝⣡⠞⣠⠟⢧⡘⢦⡙⢥⡚⢤⡛⢣⡜⢢⡝⢡⡞⢠⡟
 128  ⣟⠠⣞⠡⣝⠢⣜⠣⣛⠤⣚⠥⣙⠦⣘⠧⢟⡠⢞⡡⢝⡢⢜⡣⢛⡤⢚⡥⢙⡦⢘⡧
 128  ⣗⠨⣖⠩⣕⠪⣔⠫⣓⠬⣒⠭⣑⠮⣐⠯⢗⡨⢖⡩⢕⡪⢔⡫⢓⡬⢒⡭⢑⡮⢐⡯
 128  ⣏⠰⣎⠱⣍⠲⣌⠳⣋⠴⣊⠵⣉⠶⣈⠷⢏⡰⢎⡱⢍⡲⢌⡳⢋⡴⢊⡵⢉⡶⢈⡷
 128  ⣇⠸⣆⠹⣅⠺⣄⠻⣃⠼⣂⠽⣁⠾⣀⠿⢇⡸⢆⡹⢅⡺⢄⡻⢃⡼⢂⡽⢁⡾⢀⡿
 128  ⡿⢀⡾⢁⡽⢂⡼⢃⡻⢄⡺⢅⡹⢆⡸⢇⠿⣀⠾⣁⠽⣂⠼⣃⠻⣄⠺⣅⠹⣆⠸⣇
 128  ⡷⢈⡶⢉⡵⢊⡴⢋⡳⢌⡲⢍⡱⢎⡰⢏⠷⣈⠶⣉⠵⣊⠴⣋⠳⣌⠲⣍⠱⣎⠰⣏
 128  ⡯⢐⡮⢑⡭⢒⡬⢓⡫⢔⡪⢕⡩⢖⡨⢗⠯⣐⠮⣑⠭⣒⠬⣓⠫⣔⠪⣕⠩⣖⠨⣗
 128  ⡧⢘⡦⢙⡥⢚⡤⢛⡣⢜⡢⢝⡡⢞⡠⢟⠧⣘⠦⣙⠥⣚⠤⣛⠣⣜⠢⣝⠡⣞⠠⣟
 128  ⡟⢠⡞⢡⡝⢢⡜⢣⡛⢤⡚⢥⡙⢦⡘⢧⠟⣠⠞⣡⠝⣢⠜⣣⠛⣤⠚⣥⠙⣦⠘⣧
 128  ⡗⢨⡖⢩⡕⢪⡔⢫⡓⢬⡒⢭⡑⢮⡐⢯⠗⣨⠖⣩⠕⣪⠔⣫⠓⣬⠒⣭⠑⣮⠐⣯
 128  ⡏⢰⡎⢱⡍⢲⡌⢳⡋⢴⡊⢵⡉⢶⡈⢷⠏⣰⠎⣱⠍⣲⠌⣳⠋⣴⠊⣵⠉⣶⠈⣷
 128  ⡇⢸⡆⢹⡅⢺⡄⢻⡃⢼⡂⢽⡁⢾⡀⢿⠇⣸⠆⣹⠅⣺⠄⣻⠃⣼⠂⣽⠁⣾⠀⣿
Total 2048 

and the result after adding "entropy" (counter from 1 to 256):

256  46  LUT:
 136  ⡥⠟⡲⡌⣉⢟⢉⣳⢚⠕⢍⣱⠖⡱⡶⠬⠞⢁⢞⣢⡖⡩⣻⡹⠈⣙⢜⡻⡕⢢⡟⡽
 124  ⢔⢌⠱⠿⣟⡟⠁⣬⠪⡓⣎⣁⠠⢠⣾⠓⠖⣫⠠⣫⡮⠳⠄⣨⠨⣁⠅⣘⣖⣪⢶⡯
 125  ⡰⡅⣋⢦⠠⣛⠽⢔⢏⢸⠴⡙⣟⠤⣂⠩⣉⠽⢮⢅⡠⢚⢵⣴⠢⠣⣝⣸⢟⡡⡂⠫
 118  ⢼⣀⡲⠿⡑⢁⠁⠞⢟⠝⣣⢽⢓⢄⠠⠷⡀⣝⠜⡒⡬⡪⣏⣈⢈⠲⡸⠰⣤⠇⣞⢴
 144  ⡵⢀⢧⣏⠓⢰⡡⢛⡮⣅⣡⡝⣸⢻⡇⢝⢏⢣⣰⡥⣜⢽⢯⠥⢏⣥⣰⡥⣜⢽⢯⠥
 127  ⢎⣥⣰⡥⣜⢽⢯⠥⡰⠚⠏⢚⠣⡂⡐⣚⠫⣼⡔⠔⣍⡋⡥⡎⠲⣿⡖⠠⢵⠏⠥⡎
 120  ⢩⠦⡠⢙⠕⠋⡥⠐⣱⢓⡦⠒⣱⢹⣘⡯⡱⢴⣴⢳⡡⢕⡑⡷⣲⠎⠂⢕⣡⢠⡺⡨
 127  ⡇⢳⡽⡏⠯⡇⡭⢕⢸⣌⢊⠔⣐⢺⣐⠨⢀⠬⢩⡟⣟⡤⢐⠦⡵⣢⢱⣖⣥⠌⡥⡗
 124  ⣿⠗⡂⠹⣒⢟⠑⢺⣈⠕⢯⣱⢌⡀⣺⡂⢻⠝⠚⡍⢕⡱⠙⠤⢓⣹⠰⡼⠢⡊⡜⢬
 118  ⡦⠄⠠⣑⢼⠆⠞⠄⢪⣽⡞⠡⣏⢱⢃⠣⡤⢿⣅⠕⣏⣂⣮⡾⡀⡂⢍⠑⠓⡂⣞⢖
 131  ⢲⣩⡪⣪⢤⢵⠁⡡⠮⣲⣿⢠⠕⡺⢗⢡⢙⠖⠀⡟⣪⢅⡈⡞⢬⠮⣣⡻⣮⢬⠟⣘
 137  ⢬⣍⣣⡻⣯⢬⠟⣘⡒⡣⠈⢤⠑⡃⣰⠧⠾⡸⠜⣱⢙⡋⡚⠣⡞⢧⣼⣑⢵⣧⣝⢩
 123  ⣃⠄⡫⢢⢟⢴⡜⢃⠶⣩⢔⠝⡨⡋⢡⡸⠶⢇⠯⢑⣖⢑⡖⣪⠵⢚⡧⠬⢅⣱⣔⢐
 127  ⣂⣄⢼⣴⠵⢡⠡⠵⠽⢃⡃⠋⣊⡞⣞⣊⠨⣼⢁⢵⠇⢼⠌⢞⣔⢶⠮⡟⢜⣀⣱⡫
 137  ⣱⠻⠫⠇⢌⢻⡶⢙⠨⠠⢍⡼⢣⣮⠀⡮⡳⣟⠧⢙⣭⢕⢽⣲⠳⣁⡼⢏⡆⢘⣷⡣
 130  ⢤⠝⣨⢏⡼⣺⡐⡰⡓⢜⢕⡾⢋⠅⢢⢯⢣⡪⠳⢭⠕⠙⡥⠈⡳⢭⡌⢒⣾⣷⢘⣅
Total 2048

Thus in the worst case of pathologically low entropy, the algorithm needs more iterations, probably 400 or 500, to achieve a semblance of uniform scrambling. A proper "entropy source" would be a whole sentence or "passkey", cycling through chunks of 8 bytes at a time.

Discussions