Elliptic Curve Digital Signature Algorithm (ECDSA) supports the signing of data with Elliptic Curve methods.
Elliptic Curve Digital Signature Algorithm (ECDSA) |
Theory
With ECDSA, Alice will sign a message with her private key (\(d_A\)), and then Bob will use her public key (\(Q_A\)) to verify that she signed the message (and that the message has now changed):
Alice thus has a private key (\(d_A\)) and a public key (\(Q_A=d_A.G\)). She then signs a message (\(M\)) with the following:
- Create a hash of the message \(e=\textrm{HASH}(m)\).
- Let \(h\) be the \(L_{n}\) be the leftmost bits of \(e\), \(L_{n}\) has a bit length of the group order \(N\).
- Create a random number \(k\) which is between 1 and \(N-1\).
- Calculate a point on the curve as \((x_{1},y_{1})=k\times G\).
- Calculate \( r=x_{1} \pmod N \). If \(r=0\), go back to Step 3.
- Calculate \(s=k^{-1}(h+rd_{A}) \pmod N\). If \(s=0\), go back to Step 3.
- The signature is the pair \((r,s)\).
Bob will check with:
- Create a hash of the message \(e=\textrm{HASH}(m)\).
- Let \(h\) be the \(L_{n}\) leftmost bits of \(e\).
- Calculate \(c=s^{-1} \pmod N\)
- Calculate \(u_{1}=h \cdot c \pmod N\) and \(u_{2}=r \cdot c \pmod N\).
- Calculate the curve point (\(x_{1},y_{1})=u_{1}\times G+u_{2}\times Q_{A}\). If \((x_{1},y_{1})=O\) then the signature is invalid.
- The signature is valid if \(r\equiv x_{1}{\pmod {n}}\), invalid otherwise.
The following is an outlline of the code:
from ecdsa import SigningKey,NIST192p,NIST224p,NIST256p,NIST384p,NIST521p,SECP256k1 import base64 import sys import binascii msg="Hello" type = 1 cur=NIST192p if (len(sys.argv)>1): msg=str(sys.argv[1]) if (len(sys.argv)>2): type=int(sys.argv[2]) sk = SigningKey.generate(curve=cur) vk = sk.get_verifying_key() print("Secret key:\t",binascii.hexlify(sk.to_string())) print("Public key:\t",binascii.hexlify(vk.to_string())) signature = sk.sign(msg.encode()) print("Message:\t",msg) print("Type:\t\t",cur.name) print("=========================") print("Signature:\t",base64.b64encode(signature)) print("Signature:\t",binascii.hexlify(signature).decode()) print("=========================") print("Signatures match:\t",vk.verify(signature, msg.encode()))
A sample run is:
Secret key: b'996af3300b803ce0d4505807c7bcae4462658dbdc57fbda3' Public key: b'3c587e057148eed1b435a55d71df796b3bb2546c543f77cde98facd9a3378682dfc66cead94971b4b67943a5a7756cde' Message: Hello Type: NIST192p ========================= Signature: b'XAaOh3tmgoWczD75TdvPVmmQTXIMMSI9DjzImvgg61FBTYP155QJUnlqjoNTN/c7' Signature: 5c068e877b6682859ccc3ef94ddbcf5669904d720c31223d0e3cc89af820eb51414d83f5e7940952796a8e835337f73b ========================= Signatures match: True