11
focar em
503
Seguidores

Como quebrar o prêmio do quebra-cabeça da chave privada do OKX para o Dia Mundial do Pi (com código completo)

Criado em: 2023-03-14 23:25:45, atualizado em: 2024-11-29 18:57:29
comments   6
hits   1558

Como quebrar o prêmio do quebra-cabeça da chave privada do OKX para o Dia Mundial do Pi (com código completo)

Vi no grupo de especialistas ao lado que a OKX está realizando um evento de resolução de mistérios do Dia Mundial do Pi, o tema é o seguinte

Como quebrar o prêmio do quebra-cabeça da chave privada do OKX para o Dia Mundial do Pi (com código completo)

Como programador sênior, depois de ver as notícias, os cantos da minha boca se levantaram levemente, e eu abri meu MacBook Pro e comecei a trabalhar sem dizer nada.

analisar

Os oficiais disseram que há 61 bits da chave na parte da imagem que se sobrepõe a pi. Como todos sabemos, o comprimento da chave privada é de 32 bytes, que é convertido em hexadecimal, que é de 64 bits mais o prefixo 0x , um total de 66 bits, 61 bits já estão lá. À primeira vista, o “0X” na primeira linha da imagem obviamente não é pi, mas o prefixo da chave privada. Então, há 5 dígitos (0123456789ABCDEF) de arranjo aleatório desses personagens. Não há problema com a execução de força bruta, então vamos começar

Use as ferramentas integradas do Mac para simplesmente ajustar a nitidez e a cor

Como quebrar o prêmio do quebra-cabeça da chave privada do OKX para o Dia Mundial do Pi (com código completo)

Parece com isso. O Mac pode reconhecer automaticamente os caracteres na imagem. Vamos copiá-los diretamente:

3.141592653589793230X1D64338
А694502884197169399375105820
974925E123078164062862089986
28033DB034211706409914808651
32823066470ED424609550582231
8B3
81284
•探索,
038
永无止境
027
493
05%
0128
4756482337867831731712019091
47D9E56692346034861045432664
8213393607743749141273724587
006606315588174881BEEA209628
2925409192744436789259036001

Isso definitivamente não é utilizável. Vamos corrigi-lo manualmente. Os que estão bloqueados pela imagem e não são confirmados são marcados como*Não. Não tenho certeza, te conto mais tarde. Outros que são bloqueados pela imagem podem ser julgados observando o formato do traço de outras fontes. Neste momento, usamos Python para calcular a diferença entre os dois. O mesmo é usado_’ significa que apenas diferentes

img = '''
3.141592653589793230X1D64338
A694502884197169399375105820
974925E123078164062862089986
28033DB034211706409914808651
32823066470ED424609550582231
8B32594081284811174502841027
0193**2*D2299964462294895493
0381960EFC8103F9365933446128
4756482337867831731712019091
47D9E56692346034861045432664
82133936077A3749141273724587
006606315588174881BEEA209628
2925409192744436789259036001
'''
# 真实圆周率
real='''
3.14159265358979323846264338
3279502884197169399375105820
9749445923078164062862089986
2803482534211706798214808651
3282306647093844609550582231
7253594081284811174502841027
0193852110555964462294895493
0381964428810975665933446128
4756482337867831652712019091
4564856692346034861045432664
8213393607260249141273724587
0066063155881748815209209628
2925409171536436789259036001
'''

items = img.strip().split('\n')
diffStr = ''
for pos, line in enumerate(real.strip().split('\n')):
    for i, c in enumerate(line):
        imgLine = list(items[pos])
        if line[i] == imgLine[i]:
            imgLine[i] = '_'
        else:
            diffStr += imgLine[i]
        items[pos] = ''.join(imgLine)
print('\n'.join(items))
print(diffStr, 'Len:', len(diffStr))

Os resultados da execução são os seguintes:

___________________0X1D_____
A694________________________
____25E1____________________
____3DB0________4099________
___________ED42_____________
8B32________________________
____**_*D2299_______________
______0EFC___3F93___________
________________731_________
_7D9E_______________________
__________7A37______________
__________________BEEA______
________92744_______________
0X1DA69425E13DB04099ED428B32***D22990EFC3F937317D9E7A37BEEA92744 Len: 64

Há 3 dígitos extras, que são incertos. Vamos removê-los e tentar. Porque depois de eliminá-los, os outros 61 dígitos estão todos corretos. Apenas as diferenças mais certas são mantidas, e o prefixo final é o seguinte

0X1DA69425E13DB04099ED428B32D22990EFC3F937317D9E7A37BEEA92744

Em seguida, ainda precisamos usar Python para escalar violentamente o saldo na cadeia OK e comparar qual chave privada tem o saldo. Na verdade, você também pode primeiro selecionar a chave pública com transferência de 314USDT, que é mais rápida. De acordo com o site oficial , ainda tem gás. Basta verificar o saldo diretamente. O código está bagunçado.

import sys
import web3,time,logging
from eth_account import Account
from web3 import Web3
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s')
w3 = Web3(Web3.HTTPProvider("https://exchainrpc.okex.org"))
logging.info(w3.clientVersion)
found = None

def get_balance_gas(key):
    global found
    _counter += 1
    address = Account.from_key(key).address
    logging.info('fetch address %s %s' % (found, address))
    while True:
        try:
            balance = w3.eth.get_balance(address)
            break
        except:
            logging.warning(traceback.format_exc())
            time.sleep(1)
            continue
    if balance != 0:
        found = key
        raise BaseException('Found balance: %s %s' % (address, balance))
    return balance

from concurrent.futures import ThreadPoolExecutor
executor = ThreadPoolExecutor(max_workers=50)
keys = []
prefix = '1DA69425E13DB04099ED428B32D22990EFC3F937317D9E7A37BEEA92744'
# 无所谓优化算法了, 争分夺秒跑密钥
ch = '0123456789ABCDEF'
for a in range(0, 16):
    for b in range(0, 16):
        for c in range(0, 16):
            for d in range(0, 16):
                for e in range(0, 16):
                    keys.append("0x"+prefix+ch[a]+ch[b]+ch[c]+ch[d]+ch[e])
print('all keys:', len(keys))
tasks = [None for t in keys]
for idx, key in enumerate(keys):
    tasks[idx] = executor.submit(get_balance_gas, key)
for t in tasks:
    t.result()
    

Você pode ver que ele precisa ser percorrido 1048576 vezes. Usar multithreading é muito mais rápido. Execute-o em um dos meus servidores.

2023-03-15 00:20:19,491 exchain-v1.6.8.5
all keys: 1048576
2023-03-15 00:20:20,372 fetch address None 0xc20C41f06F2428a0FD84ef03Ec6960992F5f8016
2023-03-15 00:20:20,473 fetch address None 0xcFa87ee54bc1c14c09a3AB3f41640bBab5C5480a
2023-03-15 00:20:20,483 fetch address None 0x126E922652f8B276F231D0eCA94d98685a26a45D
以下省略......

Esperando ansiosamente~~~~, más notícias, não há resultado antes da saída da estratégia, todos exibidos são Nenhum

Uma reviravolta repentina nos acontecimentos

Não deveria ser o caso. Não consegui descobrir. Comecei a ler as discussões de todos no Twitter e descobri que todos tinham seguido passos semelhantes aos meus. Mas o estranho é que ninguém disse que a descriptografia foi bem-sucedida , e o oficial ainda não havia anunciado. Os primeiros 61 dígitos corretos. Nesse momento, uma resposta estranha chamou minha atenção porque havia uma diferença no meio.D2299Não há objeção, tenho certeza, mas ele também parece muito confiante.

Como quebrar o prêmio do quebra-cabeça da chave privada do OKX para o Dia Mundial do Pi (com código completo)

Mas o 61º dígito dado por essa pessoa é D2290. Ele também disse que tinha verificado cuidadosamente. Não importa. Vamos tentar a sorte. É um desperdício de eletricidade de qualquer maneira.

Como quebrar o prêmio do quebra-cabeça da chave privada do OKX para o Dia Mundial do Pi (com código completo)

Com uma atitude desafiadora, encontrei várias outras pessoas que deixaram mensagens dizendo que tinham encontrado 61 pessoas, e todas pareciam muito confiantes.

Como quebrar o prêmio do quebra-cabeça da chave privada do OKX para o Dia Mundial do Pi (com código completo)

Coletei todos os prefixos encontrados na área de comentários e os percorri com o código anterior. O código básico não mudou muito, então não vou colá-lo novamente.

prefixs =[
'1DA69425E13DB04099ED428B3202290EFC3F9317317D9E7A37BEEA92744',
'1DA69425E13DB04099ED428B32D2290EFC3F9373177D9E7A37BEEA92744',
'1DA69425E13DB04099ED428B320D2290EFC3F937317D9E7A37BEEA92744',
'1DA694255E3DB040990ED428B3208890EFC3F937317D9E7A37BEEA92744',
'1DA69425E13DB04099ED428B3202299EFC3F9317317D9E7A37BEEA92744',
'1DA69425E13DB01099ED428B3202290EFC3F9317317D9E7A37BEEA92744',
'1DA69425E13DB04099ED428B32D2290EFC3F9317317D9E7A37BEEA92744',
'1DA69425E13DB04099ED428B32D22990EFC3F937317D9E7A37BEEA92744',
]

Na verdade, há mais comentários novos. O valor de PI de um irmão é diferente do meu. É incrível. Vamos executar estes primeiro. Não acredito no que vejo. Realmente funciona. Isso significa que um dos prefixos acima está correto. Isso não é científico. A chave privada é:

1DA69425E13DB04099ED428B32D2290EFC3F9373177D9E7A37BEEA92744C8155

O dele é D229, mas a imagem mostra claramente D2299, e há um 7 depois do 731, mas ele tem dois. Mas acabou sendo os 61 dígitos corretos. Não sei como ele calculou. Estou muito curioso, mas não duvido da minha própria operação. Vi nos comentários que o serviço oficial de atendimento ao cliente disse que há outro versão de pi. Eu sou ignorante. O conhecimento aprendido e a compreensão atual do universo pelos humanos, o número irracional pi pode representar o infinito do universo, e sua parte decimal nunca se repetirá ou terminará. Você pode pensar nisso como o UUID do universo em que você está. Se houver outras versões, talvez de um mundo paralelo.

Esta é a resposta do serviço de atendimento ao cliente depois que outro Big Brother expressou dúvidas:

Como quebrar o prêmio do quebra-cabeça da chave privada do OKX para o Dia Mundial do Pi (com código completo)

É um aumento de conhecimento.

Código de transferência de moeda Web3

Finalmente, aqui está o código para transferir o bônus. Desta vez, usei diretamente a função Web3 da plataforma FMZ. Acabei de definir o endereço da cadeia para OKC. Ao adicionar a chave privada à troca, não importa de qualquer maneira. Então Eu posso fazer isso em duas linhas. Executar no modo depurador

Como quebrar o prêmio do quebra-cabeça da chave privada do OKX para o Dia Mundial do Pi (com código completo)

provar

Endereço de chave pública quebrado

>>> from eth_account import Account
>>> Account.from_key('0x1DA69425E13DB04099ED428B32D2290EFC3F9373177D9E7A37BEEA92744C8155').address
'0x0bd08825e05e540C9508961a32E58D14da47275A'

Ver link: https://www.okx.com/cn/explorer/okc/address/0x0bd08825e05e540c9508961a32e58d14da47275a

TX depois que o tirei: https://www.okx.com/cn/explorer/okc/tx/0x4211418b09571011417257201aaf10fc3c5d638809a9456eb5aba5fe8c5d4e2c

Você pode ver que o endereço do destinatário é

0x25f0a126be95f437ee71d7c4de725567c5f6c731

Como quebrar o prêmio do quebra-cabeça da chave privada do OKX para o Dia Mundial do Pi (com código completo)

Para provar que esse endereço é meu, usei o endereço do destinatário para transferir dinheiro para um endereço de buraco negro.

https://www.okx.com/cn/explorer/okc/tx/0xc32b5e299064456af3eb67c34a3b153f74a1bd18a31429052e3e3c5614bcdb6e

O endereço do buraco negro é 0x0000000000000000005757572e464d5a2e434f4d

Este endereço de buraco negro contém uma URL que, após decodificação, é

~ % python -c 'print(bytes.fromhex("0000000000000000005757572e464d5a2e434f4d"))'
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00WWW.FMZ.COM'

Posfácio

Este é o fim. Olhando para trás, sou grato pelo meu acúmulo de conhecimento ao longo dos anos. Caso contrário, a velocidade de craqueamento não seria tão rápida e outros teriam chegado na minha frente. Tenho certeza de que há um erro no diagrama oficial. De qualquer forma, tive sorte de ter descoberto a resposta antes que ela fosse tornada pública. Espero que a OKX seja mais rigorosa na próxima vez que realizar eventos semelhantes.