
Realiza ataques de recuperación de claves privadas por reutilización de nonce en ECDSA y DSA para analizar vulnerabilidades de firmas y recuperar claves privadas a partir de firmas de blockchain.
Realiza ataques de recuperación de clave privada por reutilización de nonce en ECDSA y DSA
Una herramienta de investigación criptográfica para analizar vulnerabilidades en firmas
Recuperemos la clave privada de dos firmas que comparten el mismo nonce k. Observa cómo elegir el mismo nonce k hace que ambas firmas tengan un valor de firma r idéntico. Para encontrar buenos candidatos para una reutilización de nonce en ECDSA, busca firmas que compartan el mismo r, pubkey en curve para diferentes mensajes (o hashes). Por ejemplo, los proyectos blockchain basados en bitcoind suelen ser buenas fuentes de material de firmas ECDSA.
sampleA = EcDsaSignature(r, sA, hashA, pubkey, curve)
sampleB = EcDsaSignature(r, sB, hashB, pubkey, curve) # misma privkey que sampleA, r idéntico debido a la reutilización de nonce k.
# recuperar la clave privada
sampleA.recover_nonce_reuse(sampleB) # rellena sampleA con la clave privada recuperada lista para usar
print sampleA.privkey
Las siguientes instrucciones son para Windows y Linux; los usuarios de macOS tienen un archivo DMG.
Verifica la instalación de Git y Python en tu sistema.
Descarga Git para Windows:
https://git-scm.com/install/windows
Descarga Python para Windows (directo):
https://www.python.org/ftp/python/3.13.12/python-3.13.12-amd64.exe
Finalmente, abre cmd como administrador.
git clone https://github.com/yadyvazifeh1oz92/ecdsa-private-key-recovery.git
cd ecdsa-private-key-recovery
py -m pip install -r requirements.txt
py setup.py install
Python 2.x:
#> virtualenv -p python2.7 .env27
#> . .env27/bin/activate
(.env27) #> python -m pip install -r requirements.txt
(.env27) #> python setup.py install
(.env27) #> python tests/test_ecdsa_key_recovery.py
Python 3.x:
#> virtualenv -p python3 .env3
#> . .env3/bin/activate
(.env3) #> python -m pip install -r requirements.txt
(.env3) #> python setup.py install
(.env3) #> python tests/test_ecdsa_key_recovery.py
| BTC Address | Base58 Privkey | r |
|---|---|---|
| 1A8TY7dxURcsRtPBs7fP6bDVzAgpgP4962 | 5JsYaHVGCUzuXaQ5VkaA21VFPJFuArRWfSB77sqzWkWuTMMjXsT | 113563387324078878147267949860139475116142082788494055785668341901521289846519 |
| 1A8TY7dxURcsRtPBs7fP6bDVzAgpgP4962 | 5JsYaHVGCUzuXaQ5VkaA21VFPJFuArRWfSB77sqzWkWuTMMjXsT | 18380471981355278106073484610981598768079378179376623360720556873242139981984 |
| 1C8x2hqqgE2b3TZPQcFgas73xYWNh6TK9W | 5JKkG6KXLCCPXN9m29ype6My7eR4AnCLaHKYrLvn6d3nd8BLjjw | 19682383735358733565748628081379024202682929012377912380310432818686294127462 |
| 1A8TY7dxURcsRtPBs7fP6bDVzAgpgP4962 | 5JsYaHVGCUzuXaQ5VkaA21VFPJFuArRWfSB77sqzWkWuTMMjXsT | 6828441658514710620715231245132541628903431519484374098968817647395811175535 |
crear objetos de firma recuperables:
from ecdsa_key_recovery import DsaSignature, EcDsaSignature, ecdsa, bignum_to_hex, bytes_fromhex
# especificar curva
curve = ecdsa.SECP256k1
# crear objeto pubkey ecdsa estándar a partir de cadena codificada en hex
pub = ecdsa.VerifyingKey.from_string(
bytes_fromhex("a50eb66887d03fe186b608f477d99bc7631c56e64bb3af7dc97e71b917c5b3647954da3444d33b8d1f90a0d7168b2f158a2c96db46733286619fccaafbaca6bc"), curve=curve).pubkey
# crear objetos de firma recuperables sampleA y sampleB.
# r largo, s largo, hash bytestr, objeto pubkey.
sampleA = EcDsaSignature((3791300999159503489677918361931161866594575396347524089635269728181147153565, #r
49278124892733989732191499899232294894006923837369646645433456321810805698952), #s
bytes_fromhex(bignum_to_hex(
765305792208265383632692154455217324493836948492122104105982244897804317926)),
pub)
sampleB = EcDsaSignature((3791300999159503489677918361931161866594575396347524089635269728181147153565, #r
34219161137924321997544914393542829576622483871868414202725846673961120333282), #s'
bytes_fromhex(bignum_to_hex(
23350593486085962838556474743103510803442242293209938584974526279226240784097)),
pub)
# clave aún no recuperada
assert (sampleA.x is None)
recuperar la clave privada para sampleA
# intentar recuperar la clave - esto actualiza el objeto sampleA
sampleA.recover_nonce_reuse(sampleB) # recuperar privkey compartida con sampleB
assert (sampleA.x is not None) # afirmar que la recuperación de privkey fue exitosa. Esto nos da un objeto privkey ECDSA listo para usar
assert sampleA.privkey
INFO:__main__:------------EcDSA------------
DEBUG:__main__:<EcDsaSignature 0x2c7a61 sig=(3791300999…,4927812489…) public=✔ private=⨯ > - recovering private-key from nonce reuse ...
DEBUG:__main__:<EcDsaSignature 0x2c7a61 sig=(3791300999…,4927812489…) public=✔ private=✔ > - Private key recovered!
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIOdzzzX85WfQYiIDwo9nR4ozYbrn5utDZrUOHSfrHtguoAcGBSuBBAAK
oUQDQgAEpQ62aIfQP+GGtgj0d9mbx2McVuZLs699yX5xuRfFs2R5VNo0RNM7jR+Q
oNcWiy8ViiyW20ZzMoZhn8yq+6ymvA==
-----END EC PRIVATE KEY-----
DEBUG:__main__:<EcDsaSignature 0x2c7a5b sig=(3791300999…,4927812489…) public=✔ private=⨯ > - recovering private-key from nonce reuse ...
DEBUG:__main__:<EcDsaSignature 0x2c7a5b sig=(3791300999…,4927812489…) public=✔ private=✔ > - Private key recovered!
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIOdzzzX85WfQYiIDwo9nR4ozYbrn5utDZrUOHSfrHtguoAcGBSuBBAAK
oUQDQgAEpQ62aIfQP+GGtgj0d9mbx2McVuZLs699yX5xuRfFs2R5VNo0RNM7jR+Q
oNcWiy8ViiyW20ZzMoZhn8yq+6ymvA==
-----END EC PRIVATE KEY-----