01
 ███████    ██████     ███████     ████     ████     ██      ▀▀██████
  ░░░██       ██░░░░██░░░░██     ███ ███    ██░░░░██   ██      ██░░░░██
    ██       ██   ██   ██     ██ ████    ██   ██   ▓█      ██   ██
    ██       ██████     █████████ 01    ██   ██         ██████
    █·       ██   ▀█     ▓█   ██      ▓█   ██    ▓█   ██   █▓     ▓█   ██
    ██       ██   █▓   █▓     █▓    ░░▒▓   █▓     █▓    █▓
    ▓▓       ▓▓   ▓▌    ▓▓   ▓▒     ▓▒   ▓▒    ▒░   ▓░   ▒▒     ▓▓    ▓▒
    ▒▓       ▓▌    ▓▒   ▓▓     ░▒   ░░▒████░    ▓░     ▓▒    ░░       ▒░   ░▌    ▒░                 ▓▒                ░▒     ▒░    ▓█
    ▒▓       ░░▒▓                ▒░     ▒·    ▓▒
    ▒·       ▒░     ▒▓     ░▓
    ░▒▒░                  ░            ▒·
    ░░░░▒
    ·░░                                                                          ░░░
    ░░  As complexidades da aleatoriedade na computação                         ·
    ░░  (Ou como falhei em tentar aumentar a aleatoriedade)                     ░░                                                                          ░░
    ·  <! -- [índice]                                                          ·
    ·                                                                          ░░
    ░░  0 - Introdução- Questões a aleatoriedade                                ░
    ·  1 - Entendendo um pequeno gerador de números pseudoaleatórios           ░░
    ░░  2 - Ideia inicial                                                       ·
    ░░  3 - A pseudo-aleatoriedade pode ser exploitada?                         ·
    ░░  4 - A próxima ideia: tentando gerar números mais aleatórios             ░░
    ░░      4.1 - Ideia de melhoria                                             ░
    ·      4.2 - Tentativa fracassada :(                                       ░░  5 - Finalização                                                         ░
    ·      5.1 - Conclusão                                                     ░
    ·      5.2 - Como você pode terminar ou melhorar esse projeto              ░░  -->                                                                     ·
    ░░                                                                          ░░                                                                          ░░  <! -- 0 [Introdução- Questões sobre a aleatoriedade]                    ░                                                                          ░░  Algo que quase todos sabem é que os computadores não geram números      ░
    ░░  verdadeiramente aleatórios. A aleatoriedade é algo complexo, pois os    ·
    ░░  computadores são lógicos demais para gerar números aleatórios, e os     ░░
    ░░  humanos são emocionais demais para tentar gerar números verdadeiramente ░
    ░░  aleatórios. Uma pesquisa mostrou que os humanos tendem padrões para     ░░
    ░░  escolher números aleatórios[1][2][3],                                   ░░
    ░░  https://forms.gle/wsXnfNH4TCT7FRZ38                                     ░░
    ░░  nessa pesquisa, foi pedido que                                          ·
    ░░  escolhessem um número aleatório entre 1 e 10, e de longe o número mais  ░
    ░░  escolhido foi 7. Outro exemplo simples, porém interessante, é quando    ·  pedimos 'Pense em 8 números aleatórios entre 1 e 10'. É bem provável    ░░
    ·  que a pessoa tente ser o mais aleatória possível, evitando repetições   ░░
    ░░  de números ou sequências. No entanto, algo realmente aleatório poderia  ░░  resultar em todos os números sendo iguais ou em uma ordem específica,   ·
    ░░  como de 1 a 8 ou de 8 a 1, pois os eventos são totalmente independentes.░░  Quando falamos sobre máquinas gerando números aleatórios, surge outra   ░
    ░░  questão: como um computador (pense em um script) seria capaz de gerar   ░░
    ·  um número verdadeiramente aleatório?                                    ░░
    ░░                                                                          ░░
    ░░  A resposta é simples: Ele não vai ser capaz =D. Um computador é uma     ·
    ░░  máquina exata que utiliza cálculos para tudo, tornando-o previsível.    ░░
    ·
    ░░  Eu "fiz" um programa para "gerar um número aleatório"                   ░
    ░░                                                                          ░░
    ░░  root@tramoia:~/tramoia# cat gen.py                                      ░░
    ░░                                                                          ░░
    ·    import random                                                         ░░
    ·    print(f"Número aleatório: {random.randint(1, 100)}")                  ░
    ·                                                                          ░░
    ░░
    ░░    root@tramoia:~/tramoia# python3 gen.py                                ░░
    ░░    Numéro aleatório: 86                                                  ░
    ░░    root@tramoia:~/tramoia# python3 gen.py                                ░░
    ░░    Numéro aleatório: 65                                                  ░░
    ░░    root@tramoia:~/tramoia# python3 gen.py                                ░░
    ░░    Numéro aleatório: 75                                                  ░░
    ░░    root@tramoia:~/tramoia# python3 gen.py                                ░░
    ░░    Numéro aleatório: 24                                                  ·
    ░░                                                                          ·  Esses resultados não são aleatórios. Antes de qualquer explicação,      ░░
    ░░  precisamos entender o que são números pseudoaleatórios.                 ░
    ░░  -->                                                                     ░
    ░░                                                                          ░░
    ·  <! -- 1 [Entendendo um pequeno gerador de números pseudoaleatórios]     ░░                                                                          ░░
    ░░  Os números pseudoaleatórios são números que parecem ser aleatórios,     ·  mas que na verdade não são. Como não sou muito bom em matemática, vou   ░░
    ░░  dar um exemplo sobre um gerador de fácil entendimento chamado           ░░  'Geradores Congruentes Lineares'[4] . Eu vou fazer uma versão em        ░░
    ░░  python do gerador de congruentes linerares para usar como exemplo,      ░░
    ·  em seguida vou mostrar a melhor maneira de piorar ele! Mas que é bem    ░░
    ░░  legal :) .                                                              ░░
    ░░                                                                          ·
    ░░  1 -> Escolhemos uma seed (Semente) inicial, esse valor pode ser obtido  ░░
    ░░  de vários maneiras, mas vamos definir ela manualmente. A semente será   ·
    ·  o X_0.                                                                  ░░
    ·  2 -> Aplicamos essa equação para calcular o x1: X_{1}=(AX_0+B) mod M    ░░  3 -> Agora vamos calcular o X2: X_{2}=(AX_1+B) mod M                    ░░  4 -> Bom... Vamos calcular o X3: X_{3}=(AX_2+B) mod M                   ░░  5 -> Acho que deu para entender o que vai acontecer aqui                ░
    ░░                                                                          ·
    ░░  De maneira tosca, definimos uma seed X_0 ​ e aplicamos uma operação de   ░░  multiplicação de A (um multiplicador) com X_0 ​ (a seed), somamos B      ░░
    ░░  (um incremento), e, em seguida, aplicamos a operação mod M (Encontrar   ·
    ░░  o resto da divisão) para obter o próximo número aleatório X1, em        ░░
    ░░  seguida, esse número X1 será utilizado para gerar o próximo número,     ░
    ·  podemos dizer que ele é a nova seed. Isso pode parecer confuso, certo?  ░░
    ░░  Valores reais podem ajudar a entender melhor                            ░░
    ░░                                                                          ░░
    ·    A = 5                                                                 ░░    B = 3                                                                 ░░
    ░░    M = 16                                                                ░░
    ░░    X0 = 7 (seed)                                                         ░░
    ·                                                                          ░░
    ░░    X1​ = (5×7+3) módulo 16  = 38 mod 16 = *6*                             ░░
    ░░    //38 ÷ 16 = 2 e o resto é 6, 2 × 16 + 6 = 38                          ·
    ░░    X1 = 6                                                                ░░
    ·                                                                          ·
    ░░    X2 = (5×6+3) módulo 16 = 33 mod 16 = *1*                              ░░    X2 = 1                                                                ░░
    ░░                                                                          ░░
    ░░    X3 = (5×1+3) módulo 16 = 8 mod 16 = *8*                               ░
    ·  X3 = 8                                                                  ░░
    ░░                                                                          ░░
    ░░  -->                                                                     ░
    ·                                                                          ░░
    ░░                                                                          ░░
    ░░  <! -- 2 [Ideia inicial]                                                 ·
    ·                                                                          ·
    ░░  Minha ideia inicial era quebrar a lib random do python. Não havia       ·  nenhum motivo específico para isso, apenas queria executar o mesmo      ░░
    ░░  programa várias vezes e sempre ser retornado os mesmos valores, claro   ░░  que sem setar a seed no próprio script, e sim manipulando os fatores    ░░
    ·  externos utilizado pela lib para gerar uma seed aleatória.              ░░
    ░░                                                                          ░░  A biblioteca random utiliza o algoritmo Mersenne-Twister[5], que é      ░░
    ░░  muito mais complexo que um gerador congruente linear e possui um        ░
    ·  período bem maior (2^19937-1) o que significa que somente após          ░  (2^19937-1) números gerados, a sequencia vai se repetir, muito          ░░
    ░░  provavelmente você não vai conseguir gerar todos eles mesmo se deixar   ░░
    ░░  um while true com multi threads executando. Um detalhe óbvio, mas que   ░░
    ░░  vale ser dito: Não importa se serão gerados números entre 1 e 5 ou 1 e  ░
    ·  12389429823, a questão é a quantidade de números gerados até esgotar o  ░  período e os número começarem a ser os mesmos (na mesma ordem, como se  ·
    ░░  fosse a primeira vez executando). De maneira superficial, será definida ░░
    ░░  uma seed e em seguida aplicada as operações matemáticas.                ·
    ░░                                                                          ░░
    ░░                                                                          ░░
    ·  Você deve estar se perguntando "Bom, se eu não setei a seed, por que    ░░
    ░░  quando eu rodo o script outra vez ele não retorna os mesmo valores? Se  ░░
    ░░  eu não setei uma seed, qual seed ele usa?" Essa é uma ótima pergunta.   ░░
    ░░  Essa questão foi a minha motivação e ideia inicial para estudar isso.   ·
    ░░  A biblioteca random do python[6] possui um mecanismo simples, ela pode  ░░
    ░░  utilizar das fontes de entropia do sistema operacional para gerar       ░░
    ·  números aleatórios (/dev/urandom no Linux e CryptGenRandom no Windows)  ·
    ░░  para gerar a seed. CASO esses mecanismos estejam indisponíveis, o       ░░
    ·  script utiliza outras fontes para gerar a seed (Como horário atual, e   ·
    ░░  outras informações, não consegui concluir isso). Eu queria deletar o    ░
    ░░  /dev/urandom da minha máquina e forçar a lib utilizar outras fontes     ░░
    ·  para gerar a seed, em paralelo deixar algum tipo de loop para manipular ░░
    ░░  essas "outras fontes" (como forçar o horário do meu PC a ficar          ·
    ░░  exatamente o mesmo), mas falhei nisso. Ainda sim é um projeto que eu    ░░
    ░░  gostaria de retomar. Mas gostaria de encerrar mostrando que de fato,    ░░
    ░░  a aleatoriedade pode ser exploitada:                                    ░░
    ░░  -->                                                                     ░
    ░░                                                                          ·  <! -- 3 [A pseudo-aleatoriedade pode ser exploitada?]                   ·                                                                          ·
    ░░  No livro "A arte de invadir" de Kevin Mitnick, na história "Invadindo   ░░  os cassinos por um milhão de pratas", é mostrado um ataque divertido    ░░
    ·  que envolve a fraqueza dos geradores de números pseudo-aleatórios.      ·
    ·  Nessa história, Kevin conta que alguns programadores compraram um caça  ░░
    ░░  níquel e decidiram fazer a engenharia reversa para entender seu         ░
    ░░  funcionamento e encontraram uma "vulnerabilidade", o vetor de ataque    ·  foi o GNA (Gerador de números aleatórios). Nessa história, a falha      ░░
    ░░  estava de fato no gerador de números, pois o mesmo não podia ser        ░
    ░░  verdadeiramente pseudo-aleatório, pois o lucro da casa não pode         ░░
    ░░  depender de sorte. Mas vou dar um exemplo tosco, imagine que de alguma  ░░
    ·  forma, você consegue descobrir a seed, é possível encontrar quais serão ░
    ░░  os próximos números a serem gerados, pois é possível determinar a       ░░
    ░░  posição que o gerador está na lista de números. Parte do ataque         ░░
    ░░  mostrado nesse capitulo do livro envole algo semelhante a isso.         ░░                                                                          ░░
    ·  Eu fiz 3 programas bem simples                                          ░░
    ·  1- Gerador.py: Esse programa vai definir a seed 'Tr4moia2024', gerar    ░░
    ░░  5000 números pseudo-aleatórios entre 1 e 100 e salvá-los em uma lista.  ░░                                                                          ░░
    ·    root@tramoia:~/tramoia# cat gerador.py                                ·
    ·    import random                                                         ░
    ░░    random.seed("Tr4moia2024")                                            ·
    ░░    numeros_aleatorios = [random.randint(1, 100) for _ in range(5000)]    ·
    ░░    with open("numeros.txt", "w") as f:                                   ░
    ░░        for num in numeros_aleatorios:                                    ░░
    ░░            f.write(f"{num}\n")                                           ░░
    ░░                                                                          ░░  2- Encontrar.py: Esse script tem como função ler a lista de números     ░░  aleatórios, solicitar os últimos 10 números gerados, para que eles      ░
    ░░  sejam encontrados na lista e sejam retornados os próximos 10.           ░░
    ·                                                                          ·
    ·    root@tramoia:~/tramoia# cat encontrar.py                              ░░
    ░░    with open("numeros.txt", "r") as f:                                   ·
    ░░      numeros_aleatorios = [int(line.strip()) for line in f.readlines()]  ·
    ·    def encontrar_sequencia(lista, sequencia):                            ░░
    ·      """Encontra a sequência de números na lista e retorna os            ░
    ░░      próximos 10 números."""                                             ░░
    ░░      for i in range(len(lista) - len(sequencia)):                        ░        if lista[i:i + len(sequencia)] == sequencia:                      ░░          return lista[i + len(sequencia):i + len(sequencia) + 10]        ░
    ░░      return None                                                         ░░
    ·    entrada = input("Digite 10 números separados por espaço: ")           ░
    ░░    sequencia_usuario = list(map(int, entrada.split()))                   ·
    ░░    proximos_numeros = encontrar_sequencia(numeros_aleatorios,            ░░
    ░░                                          └►sequencia_usuario)            ░░
    ·    if proximos_numeros:                                                  ░░
    ·        print(f"Os próximos 10 números são: {proximos_numeros}")          ·
    ░░    else:                                                                 ░░        print("Sequência não encontrada.")                                ·
    ░░
    ░░  3- apenasgere.py: A única coisa que esse script vai fazer é gerar uma   ░░
    ░░  quantidade aleatória de números em um intervalo de 1 a 100 (Ou seja,    ░░
    ░░  serão gerados X números entre 1 e 5000).                                ░
    ░░                                                                          ░░
    ·    root@tramoia:~/tramoia# cat apenasgere.py                             ░░
    ░░    import time                                                           ░
    ·    import random                                                         ░░
    ░░    soma = 0                                                              ░░
    ·    numero_aleatorio = random.randint(1, 5000)                            ░
    ·    print(f"Número aleatório gerado: {numero_aleatorio}")                 ░
    ░░    random.seed("Tr4moia2024")                                            ░    while soma < numero_aleatorio:                                        ░░
    ░░        print(f"{random.randint(1, 100)} ")                               ░
    ░░        soma = soma + 1                                                   ░
    ░░                                                                          ·
    ·  Exemplo de execução:                                                    ·
    ░░                                                                          ·
    ░░    root@tramoia:~/tramoia#  python3 gerador.py                           ░░
    ·    # Foram gerados os 5000 números aleatórios                            ░░
    ·    # entre 1 e 100 com a seed Tr4moia2024.                               ░░
    ░░                                                                          ·
    ░░    root@tramoia:~/tramoia# python3 eunaosei.py                           ░░
    ░░    Número aleatório gerado: 2207 #Será gerado 2207 números aleatórios    ░░
    ·    36                                                                    ░░
    ░░    56                                                                    ░░
    ░░    18                                                                    ·
    ░░    85                                                                    ░░
    ░░    96                                                                    ░
    ░░    82                                                                    ·    21                                                                    ░░
    ░░    [...]                                                                 ░░
    ·    46  # Esse é o número 1                                               ░░
    ░░    85                                                                    ░
    ░░    27                                                                    ░░
    ·    49                                                                    ░
    ░░    9                                                                     ·    5                                                                     ░░
    ·    23                                                                    ·
    ░░    36                                                                    ░░
    ░░    67                                                                    ·
    ░░    85  # Esse é o número 10                                              ░░
    ░░    54                                                                    ░░
    ░░    69                                                                    ·
    ·    64                                                                    ░░
    ·    38                                                                    ░
    ·    16                                                                    ·
    ░░    35                                                                    ░░
    ░░    52                                                                    ░░
    ░░    99                                                                    ·
    ░░    67                                                                    ░░
    ░░    35                                                                    ░░
    ░░                                                                          ·
    ░░  Teoricamente, se o nosso script de previsão de números estiver certo,   ░░
    ·  deverá ser retornado 54 69 64 38 16 35 52 99 67 35.                     ░░
    ░░                                                                          ░░
    ·  root@tramoia:~/tramoia# python3 encontrar.py                            ░
    ░░  Digite 10 números separados por espaço: 46 85 27 49 9 5 23 36 67 85     ·  Os próximos 10 números são: [54, 69, 64, 38, 16, 35, 52, 99, 67, 35]    ░░
    ░░                                                                          ░░
    ·  O que acabou de acontecer? O encontrar.py achou os números na lista e   ·
    ░░  conseguiu retornar os próximos 10 números, e foram exatamente iguais    ░░
    ░░  aos retornado pelo script 2. Isso significa que, se o script 2 fosse um ░
    ░░  caça-níquel, estaríamos milionários! =D                                 ░░
    ·                                                                          ░░
    ░░  -->                                                                     ░
    ·
    ░░                                                                          ░░
    ░░
    ░░  <! -- 4 [A próxima ideia: tentando gerar números mais aleatórios]       ░                                                                          ░░
    ░░    <! -- 4.1 [Ideia de melhoria]                                         ░
    ░░
    ░░  Eu fiquei um pouco decepcionado e resolvi tentar gerar números          ░░
    ░░  verdadeiramente aleatórios para aumentar a aleatoriedade. Mas como um   ░░
    ·  computador vai gerar números verdadeiramente aleatórios? Sozinho, é     ░░
    ░░  impossível, mas existem várias maneiras de conseguir isso, podemos,     ░░
    ░░  por exemplo, utilizar fatores externos como ruídos elétricos. Existem   ░░
    ·  técnicas como Avalanche Noise[7][8].                                    ░░                                                                          ░░                                                                          ░░
    ░░  Eu optei por utilizar ruídos elétricos (Também adicionei ruído sonoro   ░░
    ░░  e luminoso, porém a oscilação era praticamente nula, não sei até que    ░░
    ·  ponto eles estavam ajudando ou atrapalhando) e o Process ID do programa ·
    ░░  que executa o Mersenne-Twister. Integrei os valores em uma versão em    ░░
    ░░  Python do Mersenne-Twister.                                             ░
    ░░                                                                          ░░
    ·  Para captar os ruídos elétricos, utilizei uma bobina (que, neste caso,  ░░
    ░░  é uma forma minimamente formal de se referir a uma bola de papel        ░░
    ░░  alumínio amassado) e um Arduino; os ruídos eram enviados via serial.    ░░
    ░░                                                                          ░░
    ░░    Repositório do projeto :                                              ░░
    ░░    https://github.com/Gutierre0x80/HPRNG                                 ░░
    ░░                                                                          ░░
    ·  A montagem física ficou assim:                                          ░░
    ░░                                                                          ░░
    ░░                                                        +-----+           ░░                           +----[PWR]-------------------| USB |--+        ░░
    ░░                           |                            +-----+  |        ·                           |         GND/RST2  [ ][ ]            |        ░░
    ░░                           |       MOSI2/SCK2  [ ][ ]  A5/SCL[ ] |   C5   ░░
    ·    *****                  |          5V/MISO2 [ ][ ]  A4/SDA[ ] |   C4   ░░
    ·  ***   ***                |                             AREF[ ] |        ░
    ░░  **     **                |                              GND[ ] |        ░░
    ░░  ***   ***                | [ ]N/C                    SCK/13[ ] |   B5   ·
    ·    *****                  | [ ]IOREF                 MISO/12[ ] |   .    ░
    ░░     | |                   | [ ]RST                   MOSI/11[ ]~|   .    ·
    ░░     | |                   | [ ]3V3    +---+               10[ ]~|   .    ░     | |                   | [ ]5v     | A |                9[ ]~|   .    ░░
    ░░     | |                   | [ ]GND   -| R |-               8[ ] |   B0   ░░
    ░░     | |                   | [ ]GND   -| D |-                    |        ░░     | |                   | [ ]Vin   -| U |-               7[ ] |   D7   ░
    ░░   __| |__                 |          -| I |-               6[ ]~|   .    ░░
    ·  |_______|----------------|-[X]A0    -| N |-               5[ ]~|   .    ░░
    ░░  ______________           | [ ]A1    -| O |-               4[ ] |   .    ░░
    ·  |SensorSonoro|-----------|-[X]A2     +---+           INT1/3[ ]~|   .    ░  |____________|          -|-[X]A3                     INT0/2[ ] |   .    ░
    ░░  ________________       | | [ ]A4/SDA  RST SCK MISO     TX>1[ ] |   .    ░  |SensorLuminoso|-------- | [ ]A5/SCL  [ ] [ ] [ ]      RX<0[ ] |   D0   ·  |______________|         |            [ ] [ ] [ ]              |        ·
    ·                           |  UNO_R3    GND MOSI 5V  ____________/        ░░
    ·                            \_______________________/                     ░░
    ░░                                                                          ·
    ░░                    https://github.com/busyDuckman/ascii-art-arduinos/    ░
    ░░
    ·                                                                          ·  O código do Arduino ficou extremamente simples, basicamente lê os       ░░
    ░░  valores dos 3 "sensores" cada 0.5 segundos e envia por serial:          ·                                                                          ░░
    ░░                                                                          ░░    const int noisePin = A0;                                              ░░
    ░░    const int micPin = A2;                                                ░░
    ·    const int ldrPin = A3;                                                ·
    ░░                                                                          ·                                                                          ·
    ·    void setup() {                                                        ░      Serial.begin(9600);                                                 ·
    ░░      delay(2000);                                                        ░░
    ░░    }                                                                     ·
    ░░
    ░░    void loop() {                                                         ░░
    ░░      int ldrValue = analogRead(ldrPin);                                  ░░
    ░░      Serial.println(ldrValue);                                           ░
    ░░      delay(500);                                                         ░░
    ░░
    ·      int micValue = analogRead(micPin);                                  ░░
    ░░      Serial.println(micValue);                                           ░
    ░░      delay(500);                                                         ░░
    ░░                                                                          ░░      int noiseValue = analogRead(noisePin);                              ░░
    ░░      Serial.println(noiseValue);                                         ░░      delay(500);                                                         ░░    }                                                                     ░░
    ░░                                                                          ░░
    ·                                                                          ░░
    ░░  O Mersenne-Twister modificado ficou assim:                              ░░
    ░░                                                                          ░░
    ░░                                                                          ·
    ░░    import time                                                           ·    import os                                                             ░
    ░░    import serial                                                         ░░                                                                          ░░
    ░░    (w, n, m, r) = (32, 624, 397, 31)                                     ░░
    ░░    a = 0x9908B0DF                                                        ░░    (u, d) = (11, 0xFFFFFFFF)                                             ░░    (s, b) = (7, 0x9D2C5680)                                              ░░    (t, c) = (15, 0xEFC60000)                                             ·
    ·    l = 18                                                                ·
    ░░    f = 1812433253                                                        ░░
    ░░                                                                          ░░    MT = [0 for _ in range(n)]                                            ░░    index = n + 1                                                         ░░
    ░░    lower_mask = 0x7FFFFFFF                                               ░░    upper_mask = 0x80000000                                               ░                                                                          ░░
    ░░    def mt_seed(seed):                                                    ░░
    ░░        global index                                                      ░░
    ░░        index = n                                                         ░░
    ·        MT[0] = seed                                                      ░░
    ░░        for i in range(1, n):                                             ░░            temp = f * (MT[i-1] ^ (MT[i-1] >> (w-2))) + i                 ░░
    ░░            MT[i] = temp & 0xFFFFFFFF                                     ░░
    ░░
    ░░    def extract_number(serial_port):                                      ░        global index                                                      ·
    ·        if index >= n:                                                    ░
    ░░            twist()                                                       ░░
    ·            index = 0                                                     ░░
    ░░                                                                          ░░
    ░░        noise_value = int(read_serial_data(serial_port))                  ░
    ·        ldr_value = int(read_serial_data(serial_port))                    ░░
    ░░        mic_value = int(read_serial_data(serial_port))                    ░░
    ░░        current_millis = current_time_millis()                            ░
    ·        pid = get_pid()                                                   ░░
    ░░                                                                          ░░
    ░░        y = MT[index] ^ ldr_value ^ mic_value ^ noise_value ^             ░░
    ░░            └►current_millis ^ pid                                        ░░
    ·            #Eu confesso que isso foi extremamente mal feito =D           ░░        y = y ^ ((y >> u) & d)                                            ·
    ░░        y = y ^ ((y << s) & b)                                            ░░
    ·        y = y ^ ((y << t) & c)                                            ░░
    ░░        y = y ^ (y >> l)                                                  ░░                                                                          ·        index += 1                                                        ░░
    ░░        return y & 0xFFFFFFFF, ldr_value, mic_value, noise_value,         ·
    ░░         └►pid, current_millis                                            ░░
    ░░                                                                          ·
    ░░    def twist():                                                          ·
    ·        for i in range(n):                                                ·            x = (MT[i] & upper_mask) + (MT[(i + 1) % n] & lower_mask)     ·
    ·            xA = x >> 1                                                   ░░
    ░░            if x % 2 != 0:                                                ·
    ░░                xA = xA ^ a                                               ░░
    ·            MT[i] = MT[(i + m) % n] ^ xA                                  ░░
    ░░                                                                          ░░
    ░░    def current_time_millis():                                            ·
    ░░        return round(time.time() * 1000)                                  ·
    ░░                                                                          ░░
    ·    def get_pid():                                                        ░░        return os.getpid()                                                ░░                                                                          ░░
    ░░    def read_serial_data(serial_port):                                    ░░
    ░░        try:                                                              ░░
    ░░            data = serial_port.readline().decode('latin-1').strip()       ░░            return int(data)                                              ░░
    ·        except ValueError:                                                ░            print("Error converting data to integer. Default value used.")·
    ·            return 0                                                      ░░                                                                          ░░
    ░░    def main():                                                           ░░
    ░░        serial_port = serial.Serial('COM5', 9600, timeout=1)              ░
    ░░        time.sleep(2)                                                     ░░
    ░░                                                                          ░░
    ░░        while True:                                                       ░░
    ·            random_number, ldr_value, mic_value, noise_value, pid,        ░░
    ░░              └►current_millis = extract_number(serial_port)              ░
    ░░            print(f"Random: {random_number} | LDR: {ldr_value} |          ░░
    ░░            └►Mic: {mic_value} | Noise: {noise_value} | PID: {pid}        ░            └►| Time: {current_millis}")                                  ░░
    ░░            time.sleep(1)                                                 ·
    ░░                                                                          ·
    ░░    if __name__ == '__main__':                                            ░░
    ·        main()                                                            ░░
    ░░                                                                          ░░
    ░░
    ·    # Creditos: yinengy[13]                                               ░░
    ░░                                                                          ░░
    ░░  -->                                                                     ░░    <! -- 4.2 [Tentativa fracassada :( ]                                  ░
    ·                                                                          ░░
    ·  Existem várias falhas nessa ideia, e nem vou entrar em detalhes sobre   ░░
    ·  a maneira como os ruídos foram integrados ao Mersenne-Twister, ainda    ░░  que fosse adicionado corretamente, é preciso considerar que o Arduino   ░░
    ░░  possui poucos bits de entrada analógica (10 bits, um intervalo de       ░░
    ·  0-1023, o que é extremamente baixo quando falamos de aleatoriedade).    ░░
    ░░  Para ser mais prático, imagine que você deseja gerar valores entre      ░
    ░░  12123 e 239823433426 para sua                                           ░░
    ░░  "super_criptografia_que_não_pode_ser_quebrada4.0", mas seu gerador      ·  utiliza uma entrada de apenas 10 bits para gerar a seed, muito          ░░  inseguro, correto?                                                      ░░                                                                          ░░
    ·  Fique totalmente a vontade para melhorar o script ou me xingar por ter  ░
    ░░  criado essa integração ruim                                             ░
    ░░  -->                                                                     ░░
    ░░  -->                                                                     ·
    ░░  <! -- 5 [Finalização]                                                   ░░
    ·                                                                          ·
    ░░    <! -- 5.1 [Conclusão]                                                 ·
    ·  Podemos concluir que a aleatoriedade é sim uma área complexa e que não  ░
    ░░  é tão simples melhorar ou criar uma implementação funcional e segura.   ░░  Espero que essa tentativa falha tenha mostrado a você um ramo a qual    ·
    ░░  eu não domino, mas que acho fascinante... "Anyone who considers         ·  arithmetical methods of producing random digits is, of course, in a     ░░
    ░░  state of sin" - John Von Neumann[9][10]. Recomendo altamente a leitura  ░░
    ░░  do artigo "Entropia para a criação de criptografia" escrito por         ░░
    ░░  Giulia Riceto Mendes, o mesmo faz parte do Tramoia.                     ░  -->                                                                     ░░
    ·    <! -- 5.2 - [Como você pode terminar ou melhorar esse projeto]        ░░  Não posso oferecer uma solução para algo que  não consegui resolver,    ·
    ░░  contudo, o próximo passo nesse projeto seria a implementação do ruído   ·
    ░░  de avalanche, No entanto, existem duas dificuldades: a primeira, que é  ░░  superável, é montar e validar o hardware responsável por gerar o ruído  ░░
    ░░  de avalanche, acredito que um osciloscópio será necessário nesta etapa. ░
    ·  A segunda e maior dificuldade seria processar esses dados, uma vez que  ░░
    ░░  temos poucos bits de entrada disponíveis. Claro, você não precisa se    ░░  limitar a um Arduino ou esp32 (No caso do esp, são 12 bits de resolução,░
    ░░  o que dá um intervalo de 0-4095, porém continua sendo um valor baixo),  ░░
    ░░  acredito que existem outros microcontroladores, como o Teensy           ·
    ·  3.6[11][12], que talvez oferecem uma resolução maior.                   ·  -->                                                                     ·
    ░░  -->                                                                     ░░
    ░░                                                                          ░░  <! --- [Referências]                                                    ░░
    ·                                                                          ░░
    ░░  [1] - https://torvaney.github.io/projects/human-rng                     
    ·  [2] - https://flothesof.github.io/...-number-generator.html               [3] - https://www.reddit.com/r...6y/ask..pick_a_random_number/          ·  [4] - https://en.wikipedia.org/wiki/Linear_congruential_generator       ░░
    ░░  [5] - https://pt.wikipedia.org/wiki/Mersenne_Twister                    ░░  [6] - https://github.com/python/cpython/blob/main/Lib/random.py         ░░
    ░░  [7] - https://betrusted.io/avalanche-noise.html                         ░░
    ░░  [8] - https://www.vishay.com/...avalanchebreakdown.pdf                 
    ░░  [9] - https://en.wikiquote.org/wiki/John_von_Neumann                    
    ░░  [10] - https://ieeexplore.ieee.org/abstract/document/10461442/          ·
    ░░  [11] - https://www.pjrc.com/store/teensy36.html                         ░░  [12] - https://forum.pjrc.com/i...elution-pwm-duty-cycle-issue.62420/   ░░
    ░░  [13] - https://github.com/yinengy/Mersenne-Twister-in-Python           
    ░░  -->                                                                     ░░    
    ··░                                                                          ░··