Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
python-ecdsa — 순수 파이썬 ECDSA 서명/검증 및 ECDH 키 합의 | Kitploit
도구/GitHubGitHub/tlsfuzzer/python-ecdsa
Encryption/Decryption ToolsCryptographyUtilities & FrameworksAuthenticationLearning & Education
GitHubtlsfuzzer/python-ecdsa

python-ecdsa

순수 파이썬 ECDSA 서명/검증 및 ECDH 키 합의

저장소 보기
9753422개월 전Kitploit 검토 완료

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

순수 Python ECDSA 및 ECDH

GitHub CI Documentation Status Coverage Status condition coverage mutation score CodeQL Latest Version Code style: black

이것은 ECDSA(타원곡선 디지털 서명 알고리즘), EdDSA(Edwards-curve 디지털 서명 알고리즘) 및 ECDH(타원곡선 Diffie-Hellman)를 지원하는 ECC(타원곡선 암호)의 사용하기 쉬운 구현체로, 순수 Python으로 구현되었으며 MIT 라이선스로 배포됩니다. 이 라이브러리를 사용하면 키 쌍(서명 키와 검증 키)을 빠르게 생성하고, 메시지에 서명하고, 서명을 검증할 수 있습니다. 또한 교환된 공개 키를 기반으로 공유 비밀 키에 합의할 수도 있습니다. 키와 서명은 매우 짧아서 처리하기 쉽고 다른 프로토콜에 통합하기 쉽습니다.

참고: 이 라이브러리는 프로덕션 환경에서 사용하면 안 됩니다. 자세한 내용은 Security를 참조하세요.

기능

이 라이브러리는 192, 224, 256, 384, 521비트 키 길이를 가진 다섯 가지 널리 사용되는 NIST "Suite B" GF(p)(소수체) 곡선에 대해 키 생성, 서명, 검증 및 공유 비밀 도출을 제공합니다. OpenSSL 도구(openssl ecparam -list_curves)에서 알려진 이러한 곡선의 "짧은 이름"은 prime192v1, secp224r1, prime256v1, secp384r1, secp521r1입니다. 여기에는 비트코인에서 사용되는 256비트 곡선 secp256k1도 포함됩니다. 또한 160비트에서 512비트까지의 Brainpool 곡선의 일반(비-twisted) 변형도 지원합니다. 해당 곡선의 "짧은 이름"은 brainpoolP160r1, brainpoolP192r1, brainpoolP224r1, brainpoolP256r1, brainpoolP320r1, brainpoolP384r1, brainpoolP512r1입니다. SEC 표준의 일부 작은 곡선도 포함되어 있습니다(주로 라이브러리 테스트 속도를 높이기 위한 것입니다): , , , 입니다. Ed25519 및 Ed448 곡선에 대한 키 생성, 서명 및 검증도 지원됩니다. 다른 곡선은 포함되어 있지 않지만, 소수체 위의 더 많은 곡선에 대한 지원을 추가하는 것은 그리 어렵지 않습니다.

의존성

이 라이브러리는 Python과 'six' 패키지만 사용합니다. Python 2.6, 2.7 및 3.6+와 호환됩니다. 또한 pypy 및 pypy3와 같은 대체 구현에서도 실행을 지원합니다.

gmpy2 또는 gmpy가 설치되어 있으면 더 빠른 연산을 위해 사용됩니다. 이 중 하나는 이 라이브러리가 설치된 후에 설치할 수 있으며, python-ecdsa는 시작 시 해당 패키지의 존재를 감지하여 자동으로 사용합니다. 최적의 성능을 위해 Python3에서는 gmpy2를 선호해야 합니다.

OpenSSL 호환성 테스트를 실행하려면 'openssl' 도구가 PATH에 있어야 합니다. 이 릴리스는 OpenSSL 0.9.8o, 1.0.0a, 1.0.2f, 1.1.1d 및 3.0.1(그 외 다수)에서 성공적으로 테스트되었습니다.

설치

이 라이브러리는 PyPI에서 제공되며, pip를 사용하여 설치하는 것이 좋습니다:``` pip install ecdsa

root@kitploit:~
더 높은 성능이 필요하고 네이티브 코드 사용이 문제가 없다면, `gmpy2`와 함께 설치하도록 지정할 수 있습니다:```
pip install ecdsa[gmpy2]

또는 (더 느린, 레거시 옵션):``` pip install ecdsa[gmpy]

root@kitploit:~
## 속도

다음 표는 이 라이브러리가 키 쌍을 생성하는 데
(`keygen`), 데이터에 서명하는 데 (`sign`), 해당 서명을 검증하는 데 (`verify`),
공유 비밀 키를 도출하는 데 (`ecdh`), 그리고
키별 사전 계산 없이 서명을 검증하는 데 (`no PC verify`) 걸리는 시간을 보여줍니다.
모든 값은 초 단위입니다.
편의를 위해 해당 값들의 역수도 함께 제공됩니다:
초당 생성할 수 있는 키 수(`keygen/s`), 초당 만들 수 있는 서명 수
(`sign/s`), 초당 검증할 수 있는 서명 수
(`verify/s`), 초당 도출할 수 있는 공유 비밀 키 수
(`ecdh/s`), 그리고 키별 사전 계산 없이
초당 검증할 수 있는 서명 수(`no PC verify/s`). 원시
서명의 크기(일반적으로 서명이 인코딩될 수 있는 가장 작은
방식)도 `siglen` 열에 제공됩니다.
`tox -e speed`를 사용하여 이 표를 자신의 컴퓨터에서 생성할 수 있습니다.
Intel Core i7 4790K @ 4.0GHz에서 저는 다음과 같은 성능을 얻고 있습니다:```
                  siglen    keygen   keygen/s      sign     sign/s    verify   verify/s  no PC verify  no PC verify/s
        NIST192p:     48   0.00032s   3134.06   0.00033s   2985.53   0.00063s   1598.36       0.00129s         774.43
        NIST224p:     56   0.00040s   2469.24   0.00042s   2367.88   0.00081s   1233.41       0.00170s         586.66
        NIST256p:     64   0.00051s   1952.73   0.00054s   1867.80   0.00098s   1021.86       0.00212s         471.27
        NIST384p:     96   0.00107s    935.92   0.00111s    904.23   0.00203s    491.77       0.00446s         224.00
        NIST521p:    132   0.00210s    475.52   0.00215s    464.16   0.00398s    251.28       0.00874s         114.39
       SECP256k1:     64   0.00052s   1921.54   0.00054s   1847.49   0.00105s    948.68       0.00210s         477.01
 BRAINPOOLP160r1:     40   0.00025s   4003.88   0.00026s   3845.12   0.00053s   1893.93       0.00105s         949.92
 BRAINPOOLP192r1:     48   0.00033s   3043.97   0.00034s   2975.98   0.00063s   1581.50       0.00135s         742.29
 BRAINPOOLP224r1:     56   0.00041s   2436.44   0.00043s   2315.51   0.00078s   1278.49       0.00180s         556.16
 BRAINPOOLP256r1:     64   0.00053s   1892.49   0.00054s   1846.24   0.00114s    875.64       0.00229s         437.25
 BRAINPOOLP320r1:     80   0.00073s   1361.26   0.00076s   1309.25   0.00143s    699.29       0.00322s         310.49
 BRAINPOOLP384r1:     96   0.00107s    931.29   0.00111s    901.80   0.00230s    434.19       0.00476s         210.20
 BRAINPOOLP512r1:    128   0.00207s    483.41   0.00212s    471.42   0.00425s    235.43       0.00912s         109.61
       SECP112r1:     28   0.00015s   6672.53   0.00016s   6440.34   0.00031s   3265.41       0.00056s        1774.20
       SECP112r2:     28   0.00015s   6697.11   0.00015s   6479.98   0.00028s   3524.72       0.00058s        1716.16
       SECP128r1:     32   0.00018s   5497.65   0.00019s   5272.89   0.00036s   2747.39       0.00072s        1396.16
       SECP160r1:     42   0.00025s   3949.32   0.00026s   3894.45   0.00046s   2153.85       0.00102s         985.07
         Ed25519:     64   0.00076s   1324.48   0.00042s   2405.01   0.00109s    918.05       0.00344s         290.50
           Ed448:    114   0.00176s    569.53   0.00115s    870.94   0.00282s    355.04       0.01024s          97.69

                       ecdh     ecdh/s
        NIST192p:   0.00104s    964.89
        NIST224p:   0.00134s    748.63
        NIST256p:   0.00170s    587.08
        NIST384p:   0.00352s    283.90
        NIST521p:   0.00717s    139.51
       SECP256k1:   0.00154s    648.40
 BRAINPOOLP160r1:   0.00082s   1220.70
 BRAINPOOLP192r1:   0.00105s    956.75
 BRAINPOOLP224r1:   0.00136s    734.52
 BRAINPOOLP256r1:   0.00178s    563.32
 BRAINPOOLP320r1:   0.00252s    397.23
 BRAINPOOLP384r1:   0.00376s    266.27
 BRAINPOOLP512r1:   0.00733s    136.35
       SECP112r1:   0.00046s   2180.40
       SECP112r2:   0.00045s   2229.14
       SECP128r1:   0.00054s   1868.15
       SECP160r1:   0.00080s   1243.98

gmpy2가 로드된 상태에서 성능을 테스트하려면 tox -e speedgmpy2를 사용하세요. 같은 머신에서 gmpy2를 사용한 성능은 다음과 같습니다:``` siglen keygen keygen/s sign sign/s verify verify/s no PC verify no PC verify/s NIST192p: 48 0.00017s 5933.40 0.00017s 5751.70 0.00032s 3125.28 0.00067s 1502.41 NIST224p: 56 0.00021s 4782.87 0.00022s 4610.05 0.00040s 2487.04 0.00089s 1126.90 NIST256p: 64 0.00023s 4263.98 0.00024s 4125.16 0.00045s 2200.88 0.00098s 1016.82 NIST384p: 96 0.00041s 2449.54 0.00042s 2399.96 0.00083s 1210.57 0.00172s 581.43 NIST521p: 132 0.00071s 1416.07 0.00072s 1389.81 0.00144s 692.93 0.00312s 320.40 SECP256k1: 64 0.00024s 4245.05 0.00024s 4122.09 0.00045s 2206.40 0.00094s 1068.32 BRAINPOOLP160r1: 40 0.00014s 6939.17 0.00015s 6681.55 0.00029s 3452.43 0.00057s 1769.81 BRAINPOOLP192r1: 48 0.00017s 5920.05 0.00017s 5774.36 0.00034s 2979.00 0.00069s 1453.19 BRAINPOOLP224r1: 56 0.00021s 4732.12 0.00022s 4622.65 0.00041s 2422.47 0.00087s 1149.87 BRAINPOOLP256r1: 64 0.00024s 4233.02 0.00024s 4115.20 0.00047s 2143.27 0.00098s 1015.60 BRAINPOOLP320r1: 80 0.00032s 3162.38 0.00032s 3077.62 0.00063s 1598.83 0.00136s 737.34 BRAINPOOLP384r1: 96 0.00041s 2436.88 0.00042s 2395.62 0.00083s 1202.68 0.00178s 562.85 BRAINPOOLP512r1: 128 0.00063s 1587.60 0.00064s 1558.83 0.00125s 799.96 0.00281s 355.83 SECP112r1: 28 0.00009s 11118.66 0.00009s 10775.48 0.00018s 5456.00 0.00033s 3020.83 SECP112r2: 28 0.00009s 11322.97 0.00009s 10857.71 0.00017s 5748.77 0.00032s 3094.28 SECP128r1: 32 0.00010s 10078.39 0.00010s 9665.27 0.00019s 5200.58 0.00036s 2760.88 SECP160r1: 42 0.00015s 6875.51 0.00015s 6647.35 0.00029s 3422.41 0.00057s 1768.35 Ed25519: 64 0.00030s 3322.56 0.00018s 5568.63 0.00046s 2165.35 0.00153s 654.02 Ed448: 114 0.00060s 1680.53 0.00039s 2567.40 0.00096s 1036.67 0.00350s 285.62

root@kitploit:~
                   ecdh     ecdh/s
    NIST192p:   0.00050s   1985.70
    NIST224p:   0.00066s   1524.16
    NIST256p:   0.00071s   1413.07
    NIST384p:   0.00127s    788.89
    NIST521p:   0.00230s    434.85
   SECP256k1:   0.00071s   1409.95

BRAINPOOLP160r1: 0.00042s 2374.65 BRAINPOOLP192r1: 0.00051s 1960.01 BRAINPOOLP224r1: 0.00066s 1518.37 BRAINPOOLP256r1: 0.00071s 1399.90 BRAINPOOLP320r1: 0.00100s 997.21 BRAINPOOLP384r1: 0.00129s 777.51 BRAINPOOLP512r1: 0.00210s 475.99 SECP112r1: 0.00022s 4457.70 SECP112r2: 0.00024s 4252.33 SECP128r1: 0.00028s 3589.31 SECP160r1: 0.00043s 2305.02

root@kitploit:~
(`gmpy` 버전도 있으며, `tox -e speedgmpy`로 실행할 수 있습니다.)

비교를 위해, 일부 곡선에 특화된 어셈블리를 포함한 고도로 최적화된 구현(예: OpenSSL 1.1.1d의 구현)은 동일한 머신에서 다음과 같은 성능 수치를 제공합니다.
`openssl speed ecdsa` 및 `openssl speed ecdh`를 실행하여 이를 재현하세요:```
                              sign    verify    sign/s verify/s
 192 bits ecdsa (nistp192)   0.0002s   0.0002s   4785.6   5380.7
 224 bits ecdsa (nistp224)   0.0000s   0.0001s  22475.6   9822.0
 256 bits ecdsa (nistp256)   0.0000s   0.0001s  45069.6  14166.6
 384 bits ecdsa (nistp384)   0.0008s   0.0006s   1265.6   1648.1
 521 bits ecdsa (nistp521)   0.0003s   0.0005s   3753.1   1819.5
 256 bits ecdsa (brainpoolP256r1)   0.0003s   0.0003s   2983.5   3333.2
 384 bits ecdsa (brainpoolP384r1)   0.0008s   0.0007s   1258.8   1528.1
 512 bits ecdsa (brainpoolP512r1)   0.0015s   0.0012s    675.1    860.1

                              sign    verify    sign/s verify/s
 253 bits EdDSA (Ed25519)   0.0000s   0.0001s  28217.9  10897.7
 456 bits EdDSA (Ed448)     0.0003s   0.0005s   3926.5   2147.7

                               op      op/s
 192 bits ecdh (nistp192)   0.0002s   4853.4
 224 bits ecdh (nistp224)   0.0001s  15252.1
 256 bits ecdh (nistp256)   0.0001s  18436.3
 384 bits ecdh (nistp384)   0.0008s   1292.7
 521 bits ecdh (nistp521)   0.0003s   2884.7
 256 bits ecdh (brainpoolP256r1)   0.0003s   3066.5
 384 bits ecdh (brainpoolP384r1)   0.0008s   1298.0
 512 bits ecdh (brainpoolP512r1)   0.0014s    694.8

Keys and signature can be serialized in different ways (see Usage, below). For a NIST192p key, the three basic representations require strings of the following lengths (in bytes):

root@kitploit:~
to_string:  signkey= 24, verifykey= 48, signature=48
compressed: signkey=n/a, verifykey= 25, signature=n/a
DER:        signkey=106, verifykey= 80, signature=55
PEM:        signkey=278, verifykey=162, (no support for PEM signatures)

History

2006년, Peter Pearson은 sci.crypt에 보낸 메시지에서 ECDSA의 순수 파이썬 구현을 발표했으며, 그의 다운로드 사이트에서 받을 수 있습니다. 2010년에는 Brian Warner가 이 코드를 둘러싼 래퍼를 작성하여 사용하기 조금 더 쉽고 안전하게 만들었습니다. 2020년에는 Hubert Kario가 내부적으로 야코비안 좌표를 사용하는 타원 곡선 암호 구현을 포함하여 성능을 약 20배 향상시켰습니다. 지금 보고 계신 것은 이 래퍼의 README입니다.

Testing

전체 테스트 스위트를 실행하려면 다음을 수행하십시오:

root@kitploit:~
tox -e coverage

Intel Core i7 4790K @ 4.0GHz에서 테스트 실행에는 약 18초가 걸립니다. 테스트 스위트는 hypothesis를 사용하므로 테스트 스위트 실행 시간에 어느 정도 내재적인 변동성이 있습니다.

test_pyecdsa.py와 test_ecdh.py의 한 부분은 "openssl" CLI 도구를 실행하여 OpenSSL과의 호환성을 확인합니다. OpenSSL과의 호환성을 테스트하려면 해당 도구가 PATH에 있는지 확인하십시오(OpenSSL이 없거나 너무 오래되었거나 업스트림 릴리스에서 지원하는 모든 곡선을 지원하지 않는 경우 위의 coverage 실행에서 건너뛴 테스트를 볼 수 있습니다).

Security

이 라이브러리는 보안을 염두에 두고 설계되지 않았습니다. 보호가 필요한 데이터를 처리하는 경우 OpenSSL을 둘러싼 품질 좋은 래퍼를 사용하는 것이 좋습니다. pyca/cryptography가 그러한 래퍼의 한 예입니다. 이 라이브러리의 주요 사용 사례는 상호운용성 테스트를 위한 휴대용 라이브러리이자 교육용 도구입니다.

이 라이브러리는 부채널 공격(side-channel attack)으로부터 보호하지 않습니다.

공격자가 키 쌍을 생성하거나 메시지에 서명하는 데 걸리는 시간을 측정하지 못하게 하십시오. 키 쌍 생성이나 서명이 수행되는 동안 공격자가 동일한 물리적 머신에서 코드를 실행하지 못하게 하십시오(가상 머신도 포함). 공격자가 키 쌍을 생성하거나 메시지에 서명하는 동안 컴퓨터가 사용하는 전력량을 측정하지 못하게 하십시오. 공격자가 키 쌍을 생성하거나 메시지에 서명하는 동안 컴퓨터에서 발생하는 RF 간섭을 측정하지 못하게 하십시오. 참고: 개인 키를 로드하는 것만으로도 키 쌍 생성이 발생합니다. 다른 작업이나 공격 벡터도 공격에 취약할 수 있습니다. 정교한 공격자가 개인 키를 사용하는 단 한 번의 작업만 관찰해도 개인 키를 완전히 재구성할 수 있습니다.

또한 순수 파이썬 암호화 라이브러리는 동일한 부채널 공격에 취약할 수 있음을 유의하십시오. 이는 Python이 부채널 안전 기본 요소를 제공하지 않기 때문이며(hmac.compare_digest()는 예외), 부채널 안전 프로그래밍을 불가능하게 만듭니다.

이 라이브러리는 강력한 난수 소스에 의존합니다. os.urandom()이 암호학적으로 안전한 난수를 제공하지 않는 시스템에서는 이 라이브러리를 사용하지 마십시오.

Usage

SigningKey를 생성하는 것으로 시작합니다. 이를 사용하여 데이터를 바이트 문자열로 전달하고 서명(역시 바이트 문자열)을 돌려받는 방식으로 데이터에 서명할 수 있습니다. SigningKey에 대응하는 VerifyingKey를 요청할 수도 있습니다. VerifyingKey는 데이터 문자열과 서명 바이트 문자열을 모두 전달하여 서명을 검증하는 데 사용할 수 있습니다. 이때 True를 반환하거나 BadSignatureError를 발생시킵니다.```python from ecdsa import SigningKey sk = SigningKey.generate() # uses NIST192p vk = sk.verifying_key signature = sk.sign(b"message") assert vk.verify(signature, b"message")

root@kitploit:~
각 `SigningKey`/`VerifyingKey`는 NIST192p(기본값)와 같은 특정 곡선과  
연결됩니다. 더 긴 곡선은 더 안전하지만 사용하는 데 시간이 더 오래 걸리고,  
더 긴 키와 서명이 생성됩니다.```python
from ecdsa import SigningKey, NIST384p
sk = SigningKey.generate(curve=NIST384p)
vk = sk.verifying_key
signature = sk.sign(b"message")
assert vk.verify(signature, b"message")

SigningKey는 여러 다른 형식으로 직렬화될 수 있습니다. 가장 짧은 방법은 s=sk.to_string()을 호출한 다음, 다시 생성하는 데 SigningKey.from_string(s, curve)를 사용합니다. 이 짧은 형식은 곡선을 기록하지 않으므로 from_string()에 원래 키에 사용한 것과 동일한 곡선을 전달해야 합니다. NIST192p 기반 서명 키의 짧은 형식은 단 24 바이트입니다. 점 인코딩이 유효하지 않거나 지정된 곡선 위에 있지 않으면, from_string()은 MalformedPointError를 발생시킵니다.```python from ecdsa import SigningKey, NIST384p sk = SigningKey.generate(curve=NIST384p) sk_string = sk.to_string() sk2 = SigningKey.from_string(sk_string, curve=NIST384p) print(sk_string.hex()) print(sk2.to_string().hex())

root@kitploit:~
참고: 메서드 이름은 `to_string()`이지만 실제로 반환하는 타입은 `bytes`입니다. "string"이라는 명칭은 Python 2에서 남은 것입니다.

`sk.to_pem()` 및 `sk.to_der()`는 서명 키를 OpenSSL이 사용하는 것과 동일한 형식으로 직렬화합니다. PEM 파일은 익숙한 ASCII-armored `"-----BEGIN EC PRIVATE KEY-----"` base64 인코딩 형식처럼 보이며, DER 형식은 동일한 데이터의 더 짧은 이진 형태입니다.

`SigningKey.from_pem()/.from_der()`는 이 직렬화를 되돌립니다. 이 형식에는 곡선 이름이 포함되므로 역직렬화기에 곡선 식별자를 전달할 필요가 없습니다. 파일이 손상된 경우 `from_der()` 및 `from_pem()`은 `UnexpectedDER` 또는` MalformedPointError`를 발생시킵니다.```python
from ecdsa import SigningKey, NIST384p
sk = SigningKey.generate(curve=NIST384p)
sk_pem = sk.to_pem()
sk2 = SigningKey.from_pem(sk_pem)
# sk and sk2 are the same key

마찬가지로, VerifyingKey도 같은 방식으로 직렬화할 수 있습니다: vk.to_string()/VerifyingKey.from_string(), to_pem()/from_pem(), 그리고 to_der()/from_der(). 동일한 curve= 인수는 VerifyingKey.from_string()에 필요합니다.```python from ecdsa import SigningKey, VerifyingKey, NIST384p sk = SigningKey.generate(curve=NIST384p) vk = sk.verifying_key vk_string = vk.to_string() vk2 = VerifyingKey.from_string(vk_string, curve=NIST384p)

vk and vk2 are the same key

from ecdsa import SigningKey, VerifyingKey, NIST384p sk = SigningKey.generate(curve=NIST384p) vk = sk.verifying_key vk_pem = vk.to_pem() vk2 = VerifyingKey.from_pem(vk_pem)

vk and vk2 are the same key

root@kitploit:~
서명을 계산하는 방법에는 여러 가지가 있습니다. 기본적으로 ECDSA는 서명할 데이터를 나타내는 숫자를 받아 서명을 나타내는 숫자 쌍을 반환합니다. `sk.sign()` 및 `vk.verify()`의 `hashfunc=` 인수는 임의의 문자열을 고정 길이 다이제스트로 변환한 다음 ECDSA가 서명할 수 있는 숫자로 변환하는 데 사용됩니다. 서명과 검증 모두 동일한 방식을 사용해야 합니다. 기본값은 `hashlib.sha1`이지만 NIST256p 또는 더 긴 곡선을 사용하는 경우 `hashlib.sha256`을 대신 사용할 수 있습니다.

서명을 표현하는 방법에도 여러 가지가 있습니다. 기본 `sk.sign()` 및 `vk.verify()` 메서드는 단순성과 오버헤드 최소화를 위해 서명을 짧은 문자열로 제공합니다. 다른 방식을 사용하려면 `sk.sign(sigencode=)` 및 `vk.verify(sigdecode=)` 인수를 사용하세요. `ecdsa.util` 모듈에는 여기서 유용한 헬퍼 함수가 있습니다.

또한 결정적(deterministic)인 "시드"로부터 `SigningKey`를 생성할 수도 있습니다. 이는 일관된 서명 키를 다른 비밀에서 파생하려는 프로토콜에서 사용할 수 있습니다. 예를 들어, 세 개의 별도 키가 필요하고 단일 마스터 비밀만 저장하려는 경우입니다. 약 `curve.baselen` 바이트의 엔트로피를 가진 균일하게 분포된 추측 불가능한 시드로 시작한 다음 `ecdsa.util`의 헬퍼 함수 중 하나를 사용하여 올바른 범위의 정수로 변환하고, 마지막으로 이를 `SigningKey.from_secret_exponent()`에 전달하면 됩니다. 다음과 같이:```python
import os
from ecdsa import NIST384p, SigningKey
from ecdsa.util import randrange_from_seed__trytryagain

def make_key(seed):
  secexp = randrange_from_seed__trytryagain(seed, NIST384p.order)
  return SigningKey.from_secret_exponent(secexp, curve=NIST384p)

seed = os.urandom(NIST384p.baselen) # or other starting point
sk1a = make_key(seed)
sk1b = make_key(seed)
# note: sk1a and sk1b are the same key
assert sk1a.to_string() == sk1b.to_string()
sk2 = make_key(b"2-"+seed)  # different key
assert sk1a.to_string() != sk2.to_string()

단일 키로 생성된 서명을 애플리케이션이 다수 검증해야 하는 경우, 내부 값 중 일부를 미리 계산하여 서명 검증 속도를 크게 높일 수 있습니다. 손익분기점은 약 100개의 서명을 검증할 때 나타납니다.

사전 계산을 수행하려면 VerifyingKey 인스턴스에서 precompute() 메서드를 호출하면 됩니다:```python from ecdsa import SigningKey, NIST384p sk = SigningKey.generate(curve=NIST384p) vk = sk.verifying_key vk.precompute() signature = sk.sign(b"message") assert vk.verify(signature, b"message")

root@kitploit:~
`precompute()`가 호출되면, 이 키로 수행되는 모든 서명 검증은
더 빠르게 실행됩니다.

## OpenSSL 호환성

OpenSSL 도구로 검증할 수 있는 서명을 생성하거나, 해당 도구로 생성된
서명을 검증하려면 다음을 사용하세요:```python
# openssl ecparam -name prime256v1 -genkey -out sk.pem
# openssl ec -in sk.pem -pubout -out vk.pem
# echo "data for signing" > data
# openssl dgst -sha256 -sign sk.pem -out data.sig data
# openssl dgst -sha256 -verify vk.pem -signature data.sig data
# openssl dgst -sha256 -prverify sk.pem -signature data.sig data

import hashlib
from ecdsa import SigningKey, VerifyingKey
from ecdsa.util import sigencode_der, sigdecode_der

with open("vk.pem") as f:
   vk = VerifyingKey.from_pem(f.read())

with open("data", "rb") as f:
   data = f.read()

with open("data.sig", "rb") as f:
   signature = f.read()

assert vk.verify(signature, data, hashlib.sha256, sigdecode=sigdecode_der)

with open("sk.pem") as f:
   sk = SigningKey.from_pem(f.read(), hashlib.sha256)

new_signature = sk.sign_deterministic(data, sigencode=sigencode_der)

with open("data.sig2", "wb") as f:
   f.write(new_signature)

# openssl dgst -sha256 -verify vk.pem -signature data.sig2 data

참고: OpenSSL 1.0.0 또는 이전 버전과의 호환성이 필요한 경우, ecdsa.util의 sigencode_string 및 sigdecode_string을 각각 서명 작성 및 읽기에 사용할 수 있습니다.

키는 openssl이 처리할 수 있는 형식으로도 작성할 수 있습니다:```python from ecdsa import SigningKey, VerifyingKey

with open("sk.pem") as f: sk = SigningKey.from_pem(f.read()) with open("sk.pem", "wb") as f: f.write(sk.to_pem())

with open("vk.pem") as f: vk = VerifyingKey.from_pem(f.read()) with open("vk.pem", "wb") as f: f.write(vk.to_pem())

root@kitploit:~
## Entropy

`SigningKey.generate()`로 서명 키를 생성하려면 어떤 형태의
엔트로피가 필요합니다 (`from_secret_exponent`/`from_string`/`from_der`/`from_pem`과는
달리, 이들은 결정적이며 엔트로피 소스가 필요하지 않습니다). 기본
소스는 `os.urandom()`이지만, `os.urandom`처럼 동작하는 다른 함수를 `entropy=` 인자로 전달하여
다르게 동작하도록 할 수 있습니다. 이는 반복 가능한 결과를 원하는 단위 테스트에서
유용할 수 있습니다. `ecdsa.util.PRNG` 유틸리티가 여기서 유용합니다.
시드를 받아 강력한 의사 난수 스트림을 생성합니다:```python
from ecdsa.util import PRNG
from ecdsa import SigningKey
rng1 = PRNG(b"seed")
sk1 = SigningKey.generate(entropy=rng1)
rng2 = PRNG(b"seed")
sk2 = SigningKey.generate(entropy=rng2)
# sk1 and sk2 are the same key

마찬가지로, ECDSA 서명 생성은 난수가 필요하며, 각 서명은 서로 다른 난수를 사용해야 합니다 (같은 숫자를 두 번 사용하면 개인 서명 키가 즉시 노출됩니다). sk.sign() 메서드는 entropy= 인자를 받으며, 이는 SigningKey.generate(entropy=)와 동일하게 동작합니다.

결정적 서명

SigningKey.sign_deterministic(data)를 .sign(data) 대신 호출하면, 코드는 무작위 서명 대신 결정적 서명을 생성합니다. 이는 RFC6979의 알고리즘을 사용하여 개인 키와 서명할 메시지에서 파생된 고유한 k 값을 안전하게 생성합니다. 동일한 키로 동일한 메시지에 서명할 때마다 동일한 서명(동일한 k 사용)을 얻게 됩니다.

이 방식은 엔트로피 소스의 실패에 취약하지 않으므로, 향후 버전에서는 기본값이 될 수 있습니다.

예제

NIST192p 키 쌍을 생성하고 즉시 둘 다 디스크에 저장합니다:```python from ecdsa import SigningKey sk = SigningKey.generate() vk = sk.verifying_key with open("private.pem", "wb") as f: f.write(sk.to_pem()) with open("public.pem", "wb") as f: f.write(vk.to_pem())

root@kitploit:~
디스크에서 서명 키를 로드하고, 이를 사용하여 메시지에 서명(SHA-1 사용)한 다음,
서명을 디스크에 기록합니다:```python
from ecdsa import SigningKey
with open("private.pem") as f:
    sk = SigningKey.from_pem(f.read())
with open("message", "rb") as f:
    message = f.read()
sig = sk.sign(message)
with open("signature", "wb") as f:
    f.write(sig)

디스크에서 검증 키, 메시지, 서명을 로드하고 서명을 검증합니다(SHA-1 해시 가정):```python from ecdsa import VerifyingKey, BadSignatureError vk = VerifyingKey.from_pem(open("public.pem").read()) with open("message", "rb") as f: message = f.read() with open("signature", "rb") as f: sig = f.read() try: vk.verify(sig, message) print "good signature" except BadSignatureError: print "BAD SIGNATURE"

root@kitploit:~
NIST521p 키 쌍 생성:```python
from ecdsa import SigningKey, NIST521p
sk = SigningKey.generate(curve=NIST521p)
vk = sk.verifying_key

마스터 시드로부터 세 개의 독립적인 서명 키를 생성합니다:```python from ecdsa import NIST192p, SigningKey from ecdsa.util import randrange_from_seed__trytryagain

def make_key_from_seed(seed, curve=NIST192p): secexp = randrange_from_seed__trytryagain(seed, curve.order) return SigningKey.from_secret_exponent(secexp, curve)

sk1 = make_key_from_seed("1:%s" % seed) sk2 = make_key_from_seed("2:%s" % seed) sk3 = make_key_from_seed("3:%s" % seed)

root@kitploit:~
디스크에서 검증 키를 로드하고 hex 인코딩을 사용하여
비압축 및 압축 형식으로 출력합니다(X9.62 및 SEC1 표준에 정의됨):```python
from ecdsa import VerifyingKey

with open("public.pem") as f:
    vk = VerifyingKey.from_pem(f.read())

print("uncompressed: {0}".format(vk.to_string("uncompressed").hex()))
print("compressed: {0}".format(vk.to_string("compressed").hex()))

압축 형식의 hex 문자열에서 검증 키를 로드하고, 비압축으로 출력합니다:```python from ecdsa import VerifyingKey, NIST256p

comp_str = '022799c0d0ee09772fdd337d4f28dc155581951d07082fb19a38aa396b67e77759' vk = VerifyingKey.from_string(bytearray.fromhex(comp_str), curve=NIST256p) print(vk.to_string("uncompressed").hex())

root@kitploit:~
원격 상대방과의 ECDH 키 교환:```python
from ecdsa import ECDH, NIST256p

ecdh = ECDH(curve=NIST256p)
ecdh.generate_private_key()
local_public_key = ecdh.get_public_key()
#send `local_public_key` to remote party and receive `remote_public_key` from remote party
with open("remote_public_key.pem") as e:
    remote_public_key = e.read()
ecdh.load_received_public_key_pem(remote_public_key)
secret = ecdh.generate_sharedsecret_bytes()
도구 다운로드
secp112r1
secp112r2
secp128r1
secp160r1