With a digital signature, we sign a message with a private key, and then prove it with the related public key. The signature takes the form of (\(r,s\)). In this case we will generate signatures for the main methods used in ECDSA and EdDSA.
ECDSA and EdDSA Signatures |
Code
The code used is:
from ecpy.curves import Curve import secrets from ecpy.keys import ECPrivateKey from ecpy.ecdsa import ECDSA from ecpy.eddsa import EDDSA import hashlib from ecpy.formatters import decode_sig import sys,binascii curve = Curve.get_curve('secp256k1') G = curve.generator order = curve.order t=0 msg = 'hello' if (len(sys.argv)>1): msg=str(sys.argv[1]) if (len(sys.argv)>2): t=int(sys.argv[2]) msg=msg.encode() if (t==1): curve = Curve.get_curve('NIST-P192') elif (t==2): curve = Curve.get_curve('NIST-P224') elif (t==3): curve = Curve.get_curve('NIST-P256') elif (t==4): curve = Curve.get_curve('Ed25519') elif (t==5): curve = Curve.get_curve('secp192k1') elif (t==6): curve = Curve.get_curve('secp160k1') elif (t==7): curve = Curve.get_curve('secp224k1') elif (t==8): curve = Curve.get_curve('Brainpool-p256r1') elif (t==9): curve = Curve.get_curve('Brainpool-p224r1') elif (t==10): curve = Curve.get_curve('Brainpool-p192r1') elif (t==11): curve = Curve.get_curve('Brainpool-p160r1') elif (t==12): curve = Curve.get_curve('secp256r1') elif (t==13): curve = Curve.get_curve('Ed448') if (t!=4 and t!=13): print (f"Name: {curve.name}, y^2=x^3+a*x+b (mod p) Type: {curve.type}, Size: {curve.size}, a={curve.a}, b={curve.b}, G={curve.generator}, field={curve.field}, order={curve.order}") else: print (f"Name: {curve.name}, a*x^2+y^2=1+d*x^2*y^2 (mod p) Type: {curve.type}, Size: {curve.size}, a={curve.a}, d={curve.d}, G={curve.generator}, field={curve.field}, order={curve.order}") sk = ECPrivateKey(secrets.randbits(32*8), curve) if (curve.size==192): sk = ECPrivateKey(secrets.randbits(24*8), curve) elif (curve.size==224): sk = ECPrivateKey(secrets.randbits(28*8), curve) elif (curve.size==160): sk = ECPrivateKey(secrets.randbits(20*8), curve) elif (curve.size==448): sk = ECPrivateKey(secrets.randbits(56*8), curve) pk = sk.get_public_key() if (t==4): signer = EDDSA(hashlib.sha512) pk = signer.get_public_key(sk, hashlib.sha512) sig = signer.sign(msg,sk) rtn=signer.verify(msg,sig,pk) elif (t==13): signer = EDDSA(hashlib.shake_256, hash_len=114) pk = signer.get_public_key(sk, hashlib.shake_256, hash_len=114) sig = signer.sign(msg, sk) rtn = signer.verify(msg, sig, pk) else: signer = ECDSA() sig = signer.sign(msg,sk) rtn=signer.verify(msg,sig,pk) print("Message: ",msg) print("\nPrivate key:", hex(sk.d)) print(f"Public key: ({hex(pk.W.x)},{hex(pk.W.y)}") print(f"Signature verification: {rtn}") print("\nSignature:", binascii.hexlify(sig).decode()) if (t!=4 and t!=13): sig_len = sig[1]+2 r_offset = 4 r_len = sig[3] s_offset = 4+r_len+2 s_len = sig[4+r_len+1] r = int.from_bytes(sig[r_offset:r_offset+r_len], 'big') s = int.from_bytes(sig[s_offset:s_offset+s_len], 'big') print (f"\n(r,s) = ({r},{s})") r,s = decode_sig(sig, fmt='DER') print (f"\n(r,s) - Check = ({r},{s})") else: l = len(sig)>>1 r = int.from_bytes(sig[0:l], 'little') s = int.from_bytes(sig[l:], 'little') print (f"\n(r,s) = ({r},{s})")
A sample run:
Name: secp256k1, y^2=x^3+a*x+b (mod p) Type: weierstrass, Size: 256, a=0, b=7, G=(0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 , 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8), field=115792089237316195423570985008687907853269984665640564039457584007908834671663, order=115792089237316195423570985008687907852837564279074904382605163141518161494337 Message: b'hello' Private key: 0x5d1ab21f17f6caed1c29d6cc019cf7dda1071cc4b37dcba654c47af98cc99a34 Public key: (0xda92763477b34b6443cca901a1bc794e7c65b85c5cc6e9d443e992b7062adf84,0x56cc5919829f80b80a2f91806d2bf565a033f91e25e7fc052d1cb71167ed2fd6 Signature verification: True Signature: 304402200c3b07c8b068eca31eb15cf8a608737855051e9582a40ed889e53815ecada901022069b84613fe6bbd8220d2509f7c42e19da1a95f45770d22b77c48d0bf7ec4ce27 (r,s) = (5532051882613009013454805533407030651295281449899719376852625570987602979073,47818432622439099370009880209558293062203021294593318635492502307350283341351)
and Ed448:
Name: Ed448, a*x^2+y^2=1+d*x^2*y^2 (mod p) Type: twistededward, Size: 448, a=1, d=726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358, G=(0x4f1970c66bed0ded221d15a622bf36da9e146570470f1767ea6de324a3d3a46412ae1af72ab66511433b80e18b00938e2626a82bc70cc05e , 0x693f46716eb6bc248876203756c9c7624bea73736ca3984087789c1e05a0c2d73ad3ff1ce67c39c4fdbd132c4ed7c8ad9808795bf230fa14), field=726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018365439, order=181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779 Message: b'hello' Private key: 0x31a037add317c687b4765ad8db14cda8d016d02d328c1d85b2a3e39bc6727b9e2aaeb3e64cf0cbecc9ad4d1ceb755c7d8589f5d867efbb04 Public key: (0x972e36a0e3c8d1fd7d56e4d97987733e617283751e44a10fef88446ae4d043d011a1dd2984ad3fa352e7e735d8dd5d162fe4e02aec331d7,0xb6014fd194985443b584aa938308ced3e08395447358d80aced4560d60f26a5b78f5952b89373d482a135c3bd189fc988632721d956d336c Signature verification: True Signature: 5f5a3e0fa856adaa5364e6286597ead0447089079f865959981d4168b1f610b51fd3a26cf748f7d9e105da77796573bcc3fa3af4f5456c1e80bc305cf9e4252a392dc157e8d43d90f0300a38f5648f2641a98d80aeb8ca6d9519d758f7f8a0a6c9da9d0f294fb215c2436c5022ee6f7f3900 (r,s) = (93121733947056327907665489481668249791943809936437750349071038045653315352609199077452776334031756827652939852030325331545642803985799775,163248550059559477898666947236960607854615136440383872090895197693307102325686319248853139683367591735022090614536751873847799383339196)