Eu vi alguns magnates no grupo dizendo que a OKX estava realizando um evento de mistério do Dia Mundial do Pi, com o tema de
Como programador veterano, quando vi as notícias, sorri e abri o meu MacBook Pro, e sem mais demoras, vamos começar!
Análise
Oficialmente, há 61 bits de chave na imagem e a parte da sobreposição da circunferência, como todos sabemos, o comprimento da chave privada é de 32 bytes, convertido em hex é de 64 bits mais o prefixo 0x, um total de 66 bits, já há 61 bits, para o primeiro olhar, o
Vamos usar uma ferramenta Mac para afiar a cor simplesmente:
Desta forma, o Mac pode reconhecer os caracteres na imagem automaticamente.
3.141592653589793230X1D64338
А694502884197169399375105820
974925E123078164062862089986
28033DB034211706409914808651
32823066470ED424609550582231
8B3
81284
• Exploration,
038
Never Ending
027
493
05%
0128
4756482337867831731712019091
47D9E56692346034861045432664
8213393607743749141273724587
006606315588174881BEEA209628
2925409192744436789259036001
Não pode ser usado diretamente. Vamos corrigir manualmente. Os não confirmados cobertos pela imagem estão marcados com *. Não sei. Vamos falar sobre isso mais tarde. As outras bloqueadas pela figura podem ser julgadas observando a forma do traço de outras fontes.
img = '''
3.141592653589793230X1D64338
A694502884197169399375105820
974925E123078164062862089986
28033DB034211706409914808651
32823066470ED424609550582231
8B32594081284811174502841027
0193**2*D2299964462294895493
0381960EFC8103F9365933446128
4756482337867831731712019091
47D9E56692346034861045432664
82133936077A3749141273724587
006606315588174881BEEA209628
2925409192744436789259036001
'''
# True Pi
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 aplicação são os seguintes:
Copy code
___________________0X1D_____
A694________________________
____25E1____________________
____3DB0________4099________
___________ED42_____________
8B32________________________
____**_*D2299_______________
______0EFC___3F93___________
________________731_________
_7D9E_______________________
__________7A37______________
__________________BEEA______
________92744_______________
0X1DA69425E13DB04099ED428B32***D22990EFC3F937317D9E7A37BEEA92744 Len: 64
Há mais três, e há apenas três incertos. Tente removê-los, porque os outros 61 bits estão bem após a exclusão, deixando apenas a diferença mais definida. Finalmente, o prefixo é o seguinte:
0X1DA69425E13DB04099ED428B32D22990EFC3F937317D9E7A37BEEA92744
Em seguida, usaremos Python e usaremos força para rastrear o saldo na cadeia OK. Podemos comparar qual chave privada tem o saldo. Na verdade, também podemos selecionar a chave pública com 314 USDT transferência primeiro, o que é mais rápido. Vendo informações no site oficial disse que podemos verificar o saldo diretamente se há gás, o código é um pouco confuso.
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'
# It doesn't matter how to optimize the algorithm. Run the secret key against the clock.
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()
Podemos ver que leva 1048576 iterações, mas é muito mais rápido com multi-threading, executando 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
The following is omitted...
Esperando ansiosamente, as más notícias chegaram, e não houve resultado antes da estratégia sair.
O caminho serpenteia ao longo das montanhas
Eu não acho que sim, eu não posso perceber, eu comecei a olhar para a discussão no twitter, e eu descobri que todos e eu cheguei aos mesmos passos, mas a coisa estranha é que ninguém disse que a descrição foi bem sucedida, e o oficial não anunciou os primeiros 61 bits corretos, então uma resposta estranha chamou minha atenção, porque há uma diferençaD2299
No meio, tenho a certeza, mas ele parece terrível.
No entanto, ele postou um D2290 de 61 bits. Ele também disse que ele tinha sido verificado cuidadosamente. Não importa. Tome uma chance. De qualquer forma, é um desperdício de eletricidade. Com a atitude de tentar, encontrei algumas outras pessoas que disseram que tinham encontrado 61 bits. Os prefixos encontrados na seção de comentários são coletados, com o código apenas atravessado, o código básico não foi alterado, e não será colado repetidamente.
prefixs =[
'1DA69425E13DB04099ED428B3202290EFC3F9317317D9E7A37BEEA92744',
'1DA69425E13DB04099ED428B32D2290EFC3F9373177D9E7A37BEEA92744',
'1DA69425E13DB04099ED428B320D2290EFC3F937317D9E7A37BEEA92744',
'1DA694255E3DB040990ED428B3208890EFC3F937317D9E7A37BEEA92744',
'1DA69425E13DB04099ED428B3202299EFC3F9317317D9E7A37BEEA92744',
'1DA69425E13DB01099ED428B3202290EFC3F9317317D9E7A37BEEA92744',
'1DA69425E13DB04099ED428B32D2290EFC3F9317317D9E7A37BEEA92744',
'1DA69425E13DB04099ED428B32D22990EFC3F937317D9E7A37BEEA92744',
]
Na verdade, há mais novas mensagens mais tarde, um valor de PI de um irmão é diferente do meu, é incrível! Vamos correr com estes primeiro, eu não posso acreditar nos meus olhos, mas saiu, significa que um dos prefixos acima é correto, o que é muito não científico, a chave privada é:
1DA69425E13DB04099ED428B32D2290EFC3F9373177D9E7A37BEEA92744C8155
Aqui é D229, mas a imagem é claramente D2299, e 731 é seguido por 7, aqui é dois, mas na verdade, este é o correto 61 bits, como ele calculou ele mesmo é desconhecido, incrivelmente curioso, mas eu não duvido da minha própria operação, eu vi um dos comentários disse que o serviço oficial ao cliente disse que Pi tem outra versão, era eu que era ignorante, com o que eu aprendi e a atual compreensão humana do universo compreensão, a circunferência deste número irracional pode representar o infinito do universo, sua parte fracionária nunca se repete ou termina, você pode interpretá-lo como o UUID do universo em que você está, se há outras versões, provavelmente de mundos paralelos.
Código de conversão de moeda Web3
Finalmente, é o código para transferir o bônus, desta vez, eu uso a plataforma FMZ Web3 diretamente, definir o endereço da cadeia para OKC, a chave privada adicionada à troca aleatoriamente, e então duas linhas serão feitas, executá-lo no modo de ferramenta de depuração diretamente.
Prova
Endereço da chave pública decodificada
>>> from eth_account import Account
>>> Account.from_key('0x1DA69425E13DB04099ED428B32D2290EFC3F9373177D9E7A37BEEA92744C8155').address
'0x0bd08825e05e540C9508961a32E58D14da47275A'
Veja o link:https://www.okx.com/cn/explorer/okc/address/0x0bd08825e05e540c9508961a32e58d14da47275a
TX depois de ser liderado por mim:https://www.okx.com/cn/explorer/okc/tx/0x4211418b09571011417257201aaf10fc3c5d638809a9456eb5aba5fe8c5d4e2c
Podemos ver que o endereço do destinatário é:
0x25f0a126be95f437ee71d7c4de725567c5f6c731
Para provar que este endereço é meu, usei o endereço deste destinatário para fazer uma transferência para um endereço de buraco negro.
O endereço do buraco negro é:
0x0000000000000000005757572e464d5a2e434f4d
Este endereço de buraco negro contém um URL decodificado como:
~ % python -c 'print(bytes.fromhex("0000000000000000005757572e464d5a2e434f4d"))'
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00WWW.FMZ.COM'
Pós-escritura
Este é o fim da história, e, em retrospectiva, sou grato pelo conhecimento que acumulei ao longo dos anos, caso contrário, não teria sido capaz de decifrá-lo tão rapidamente e teria sido derrotado por outros. Tenho a certeza que houve um erro no diagrama oficial, mas de qualquer forma, tive a sorte de decifrar a resposta antes de ser tornada pública, e espero que a OKX seja mais rigorosa na próxima vez que realizarem uma atividade similar.