ECPy
Advanced tools
+16
-1
| Metadata-Version: 1.1 | ||
| Name: ECPy | ||
| Version: 1.0.1 | ||
| Version: 1.1.0 | ||
| Summary: Pure Pyhton Elliptic Curve Library | ||
@@ -58,2 +58,17 @@ Home-page: https://github.com/cslashm/ECPy | ||
| 1.1.0 | ||
| ----- | ||
| Fix DER encoding for length greater than 128 | ||
| Declare ONE infinity point per curve. | ||
| Consider global (non attached to a curve) infinity point as deprecated | ||
| Fix infinity point management in ECDSA | ||
| Fix issue #13 | ||
| 1.0.1beta | ||
@@ -60,0 +75,0 @@ --------- |
+15
-0
@@ -50,2 +50,17 @@ ECPy | ||
| 1.1.0 | ||
| ----- | ||
| Fix DER encoding for length greater than 128 | ||
| Declare ONE infinity point per curve. | ||
| Consider global (non attached to a curve) infinity point as deprecated | ||
| Fix infinity point management in ECDSA | ||
| Fix issue #13 | ||
| 1.0.1beta | ||
@@ -52,0 +67,0 @@ --------- |
+1
-1
@@ -29,3 +29,3 @@ # Copyright 2016 Cedric Mesnil, Ubinity SAS | ||
| setup(name='ECPy', | ||
| version='1.0.1', | ||
| version='1.1.0', | ||
| description='Pure Pyhton Elliptic Curve Library', | ||
@@ -32,0 +32,0 @@ long_description=long_description, |
+20
-12
@@ -44,3 +44,3 @@ # encoding: UTF-8 | ||
| - Short Weierstrass form: y²=x³+a*x+b | ||
| - Twisted Edward a*x²+y2=1+d*x²*y² | ||
| - Twisted Edward a*x²+y²=1+d*x²*y² | ||
| - Montgomery: b.y²=x³+a*x²+x. | ||
@@ -115,2 +115,4 @@ | ||
| self._infinity_point = Point(0,0,self._domain['name'],False) | ||
| self._infinity_point._at_infinity = True | ||
@@ -125,2 +127,7 @@ def __getattr__(self, name): | ||
| @property | ||
| def infinity(self): | ||
| return self._infinity_point | ||
| def is_on_curve(self, P): | ||
@@ -409,3 +416,3 @@ """Check if P is on this curve | ||
| else: | ||
| return _infinity_point | ||
| return self.infinity | ||
@@ -433,3 +440,3 @@ def _mul_point(self, k, P): | ||
| else: | ||
| return _infinity_point | ||
| return self.infinity | ||
@@ -663,3 +670,3 @@ def _neg_point(self, P): | ||
| else: | ||
| return _infinity_point | ||
| return self.infinity | ||
@@ -686,3 +693,3 @@ def _mul_point(self, k, P): | ||
| else: | ||
| return _infinity_point | ||
| return self.infinity | ||
@@ -827,3 +834,3 @@ def _neg_point(self, P): | ||
| if Q.has_y and P == -Q: | ||
| return _infinity_point | ||
| return self.infinity | ||
@@ -882,3 +889,3 @@ if P == Q: | ||
| else: | ||
| return _infinity_point | ||
| return self.infinity | ||
@@ -1080,4 +1087,2 @@ def _neg_point(self, P): | ||
| if isinstance(Q,Point) : | ||
| if self._curve.name != Q._curve.name: | ||
| raise ECPyException('__add__: points on same curve') | ||
| if self.is_infinity: | ||
@@ -1087,2 +1092,4 @@ return Q | ||
| return self | ||
| if self._curve.name != Q._curve.name: | ||
| raise ECPyException('__add__: points on same curve') | ||
| return self.curve._add_point(self,Q) | ||
@@ -1093,4 +1100,2 @@ raise ECPyException('__add__: type not supported: %s'%type(Q)) | ||
| if isinstance(Q,Point) : | ||
| if self._curve.name != Q._curve.name: | ||
| raise ECPyException('__sub__: points on same curve') | ||
| if self.is_infinity: | ||
@@ -1100,2 +1105,4 @@ return -Q | ||
| return self | ||
| if self._curve.name != Q._curve.name: | ||
| raise ECPyException('__sub__: points on same curve') | ||
| return self.curve._add_point(self,-Q) | ||
@@ -1108,3 +1115,4 @@ raise ECPyException('__sub__: type not supported: %s'%type(Q)) | ||
| return self | ||
| if scal%self.curve.order == 0: | ||
| scal = scal%self.curve.order | ||
| if scal == 0: | ||
| return Point.infinity() | ||
@@ -1111,0 +1119,0 @@ return self.curve._mul_point(scal,self) |
+44
-19
@@ -52,3 +52,3 @@ # Copyright 2016 Cedric Mesnil <cedric.mesnil@ubinity.com>, Ubinity SAS | ||
| def sign_rfc6979(self, msg, pv_key, hasher, canonical=False): | ||
| """ Signs a message hash according to RFC6979 | ||
| """ Signs a message hash according to RFC6979 | ||
@@ -67,5 +67,5 @@ Args: | ||
| return sig | ||
| return None | ||
| def sign_k(self, msg, pv_key, k,canonical=False): | ||
@@ -80,3 +80,3 @@ """ Signs a message hash with provided random | ||
| return self._do_sign(msg, pv_key, k, canonical) | ||
| def _do_sign(self, msg, pv_key, k, canonical=False): | ||
@@ -91,4 +91,7 @@ if (pv_key.curve == None): | ||
| msg = int.from_bytes(msg, 'big') | ||
| Q = G*k | ||
| if Q.is_infinity: | ||
| return None | ||
| kinv = pow(k,n-2,n) | ||
@@ -105,5 +108,5 @@ r = Q.x % n | ||
| s = n-s | ||
| sig = encode_sig(r,s,self.fmt) | ||
| # r = r.to_bytes((r.bit_length()+7)//8, 'big') | ||
@@ -119,5 +122,5 @@ # s = s.to_bytes((s.bit_length()+7)//8, 'big') | ||
| return sig | ||
| def verify(self,msg,sig,pu_key): | ||
| """ Verifies a message signature. | ||
| """ Verifies a message signature. | ||
@@ -134,5 +137,5 @@ Args: | ||
| r,s = decode_sig(sig, self.fmt) | ||
| if (r == None or | ||
| r > n or | ||
| s > n ) : | ||
| if (r == None or s == None or | ||
| r == 0 or r >= n or | ||
| s == 0 or s >= n ) : | ||
| return False | ||
@@ -148,2 +151,4 @@ | ||
| GQ = u1G+u2Q | ||
| if GQ.is_infinity: | ||
| return False | ||
| x = GQ.x % n | ||
@@ -153,9 +158,12 @@ | ||
| if __name__ == "__main__": | ||
| import binascii | ||
| try: | ||
| ### ECDSA | ||
| signer = ECDSA() | ||
| ### ECDSA secp256k1 | ||
| cv = Curve.get_curve('secp256k1') | ||
| pu_key = ECPublicKey(Point(0x65d5b8bf9ab1801c9f168d4815994ad35f1dcb6ae6c7a1a303966b677b813b00, | ||
| 0xe6b865e529b8ecbf71cf966e900477d49ced5846d7662dd2dd11ccd55c0aff7f, | ||
@@ -181,3 +189,3 @@ cv)) | ||
| # 008dffe3c592a0c7e5168dcb3d4121a60ee727082be4fbf79eae564929156305fc | ||
| msg = int(0xba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad) | ||
@@ -188,3 +196,2 @@ sig = int(0x304502200623b4159c7112125be51716d1e706d68e52f5b321da68d8b86b3c7c7019a9da0221008dffe3c592a0c7e5168dcb3d4121a60ee727082be4fbf79eae564929156305fc) | ||
| signer = ECDSA() | ||
| assert(signer.verify(msg,sig,pu_key)) | ||
@@ -212,3 +219,3 @@ | ||
| sig = signer.sign(msg,pv_key) | ||
| assert(signer.verify(msg,sig,pu_key)) | ||
| assert(signer.verify(msg,sig,pu_key)) | ||
@@ -218,3 +225,21 @@ #sign with krfc | ||
| assert(sig == expected_sig) | ||
| ### ECDSA secp256k1 | ||
| cv = Curve.get_curve('secp521r1') | ||
| pv_key = ECPrivateKey(0x018cd813ca254d350b6e4a4a0a0fe2a27eac701d8ccfb1564085d612f315d5aa6c055390cfb7bedf7fc8c02af2360423e8c8a2e3cb045f844f3ec0a6c75025f4a4fa, | ||
| cv) | ||
| pu_key = ECPublicKey(Point(0x016d523c74262368b2f066859dfd36645cfd7aa7f7c782732c8bee450cd9d42384bb3b9b480df9b440374856a37061d023ff99861796d7b5d146c5c5c3f9a0e34872, | ||
| 0x002377c7bee60c8dd47ce351c6e3f05d47fd0a1d62c8e2d0a61413e2ee453a38debf67de2da37bcdbd7e80ea5082021ad3f32c829f12d72240bc9f997b483366035a, | ||
| cv)) | ||
| W = pv_key.d * cv.generator | ||
| assert(W == pu_key.W) | ||
| msg = int(0xba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad) | ||
| msg = msg.to_bytes(32,'big') | ||
| sig = signer.sign(msg,pv_key) | ||
| assert(signer.verify(msg,sig,pu_key)) | ||
| ##OK! | ||
@@ -221,0 +246,0 @@ print("All internal assert OK!") |
+86
-44
@@ -29,3 +29,3 @@ # Copyright 2016 Cedric Mesnil <cedric.mesnil@ubinity.com>, Ubinity SAS | ||
| """ ECSchnorr signer implementation according to: | ||
| - `BSI:TR03111 <https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TR03111/BSI-TR-03111_pdf.html>`_ | ||
@@ -36,3 +36,3 @@ - `ISO/IEC:14888-3 <http://www.iso.org/iso/iso_catalogue/catalogue_ics/catalogue_detail_ics.htm?csnumber=43656>`_ | ||
| In order to select the specification to be conform to, choose | ||
| In order to select the specification to be conform to, choose | ||
| the corresponding string option: "BSI", "ISO", "ISOx", "LIBSECP", "Z" | ||
@@ -42,3 +42,3 @@ | ||
| - "BSI": compute r,s according to to BSI : | ||
| - "BSI": compute r,s according to to BSI : | ||
| 1. k = RNG(1:n-1) | ||
@@ -51,3 +51,3 @@ 2. Q = [k]G | ||
| 5. Output (r, s) | ||
| - "ISO": compute r,s according to ISO : | ||
| - "ISO": compute r,s according to ISO : | ||
| 1. k = RNG(1:n-1) | ||
@@ -60,3 +60,3 @@ 2. Q = [k]G | ||
| 5. Output (r, s) | ||
| - "ISOx": compute r,s according to optimized ISO variant: | ||
| - "ISOx": compute r,s according to optimized ISO variant: | ||
| 1. k = RNG(1:n-1) | ||
@@ -69,3 +69,3 @@ 2. Q = [k]G | ||
| 5. Output (r, s) | ||
| - "LIBSECP": compute r,s according to bitcoin lib: | ||
| - "LIBSECP": compute r,s according to bitcoin lib: | ||
| 1. k = RNG(1:n-1) | ||
@@ -90,3 +90,3 @@ 2. Q = [k]G | ||
| - "BSI": verify r,s according to to BSI : | ||
| - "BSI": verify r,s according to to BSI : | ||
| 1. Verify that r in {0, . . . , 2**t - 1} and s in {1, 2, . . . , n - 1}. | ||
@@ -98,3 +98,3 @@ If the check fails, output False and terminate. | ||
| 4. Output True if v = r, and False otherwise. | ||
| - "ISO": verify r,s according to ISO : | ||
| - "ISO": verify r,s according to ISO : | ||
| 1. check... | ||
@@ -105,3 +105,3 @@ 2. Q = [s]G - [r]W | ||
| 4. Output True if v = r, and False otherwise. | ||
| - "ISOx": verify r,s according to optimized ISO variant: | ||
| - "ISOx": verify r,s according to optimized ISO variant: | ||
| 1. check... | ||
@@ -112,8 +112,8 @@ 2. Q = [s]G - [r]W | ||
| 4. Output True if v = r, and False otherwise. | ||
| - "LIBSECP": | ||
| - "LIBSECP": | ||
| 1. Signature is invalid if s >= order. | ||
| Signature is invalid if r >= p. | ||
| 2. h = H(r || m). | ||
| 2. h = H(r || m). | ||
| Signature is invalid if h == 0 or h >= order. | ||
| 3. R = [h]Q + [s]G. | ||
| 3. R = [h]Q + [s]G. | ||
| Signature is invalid if R is infinity or R's y coordinate is odd. | ||
@@ -129,3 +129,3 @@ 4. Signature is valid if the serialization of R's x coordinate equals r. | ||
| Default is "ISO" | ||
| Args: | ||
@@ -136,3 +136,3 @@ hasher (hashlib): callable constructor returning an object with update(), digest() interface. Example: hashlib.sha256, hashlib.sha512... | ||
| """ | ||
| def __init__(self, hasher, option="ISO", fmt="DER"): | ||
@@ -146,5 +146,5 @@ if not option in ("ISO","ISOx","BSI","LIBSECP","Z"): | ||
| self.fmt = fmt | ||
| self.maxtries=10 | ||
| self.maxtries = 100 | ||
| self.option = option | ||
| def sign(self, msg, pv_key): | ||
@@ -162,3 +162,3 @@ """ Signs a message hash. | ||
| if sig: | ||
| return sig | ||
| return sig | ||
| return None | ||
@@ -175,3 +175,3 @@ | ||
| return self._do_sign(msg, pv_key,k) | ||
| def _do_sign(self, msg, pv_key, k): | ||
@@ -184,7 +184,7 @@ if (pv_key.curve == None): | ||
| size = curve.size>>3 | ||
| Q = G*k | ||
| hasher = self._hasher() | ||
| if self.option == "ISO": | ||
| xQ = (Q.x).to_bytes(size,'big') | ||
| xQ = (Q.x).to_bytes(size,'big') | ||
| yQ = (Q.y).to_bytes(size,'big') | ||
@@ -194,22 +194,28 @@ hasher.update(xQ+yQ+msg) | ||
| r = int.from_bytes(r,'big') | ||
| if r % n == 0: | ||
| return None | ||
| s = (k+r*pv_key.d)%n | ||
| if r==0 or s==0: | ||
| if s==0: | ||
| return None | ||
| elif self.option == "ISOx": | ||
| xQ = (Q.x).to_bytes(size,'big') | ||
| xQ = (Q.x).to_bytes(size,'big') | ||
| hasher.update(xQ+msg) | ||
| r = hasher.digest() | ||
| r = int.from_bytes(r,'big') | ||
| if r % n == 0: | ||
| return None | ||
| s = (k+r*pv_key.d)%n | ||
| if r==0 or s==0: | ||
| if s==0: | ||
| return None | ||
| elif self.option == "BSI": | ||
| xQ = Q.x.to_bytes(size,'big') | ||
| xQ = Q.x.to_bytes(size,'big') | ||
| hasher.update(msg+xQ) | ||
| r = hasher.digest() | ||
| r = int.from_bytes(r,'big') | ||
| if r%n == 0: | ||
| return None | ||
| s = (k-r*pv_key.d)%n | ||
| if r==0 or s==0: | ||
| if s==0: | ||
| return None | ||
@@ -225,2 +231,4 @@ | ||
| h = int.from_bytes(h,'big') | ||
| if h > n: | ||
| return None | ||
| r = Q.x % n | ||
@@ -242,10 +250,12 @@ s = (k - h*pv_key.d)%n | ||
| r = int.from_bytes(r,'big') % n | ||
| if r % n == 0: | ||
| return None | ||
| s = (k - r*pv_key.d) %n | ||
| if r==0 or s==0: | ||
| if s==0: | ||
| return None | ||
| return encode_sig(r, s, self.fmt) | ||
| def verify(self,msg,sig,pu_key): | ||
| """ Verifies a message signature. | ||
| """ Verifies a message signature. | ||
@@ -261,8 +271,6 @@ Args: | ||
| size = curve.size>>3 | ||
| r,s = decode_sig(sig, self.fmt) | ||
| if (r == None or | ||
| r > (pow(2,size*8)-1) or | ||
| s == 0 or | ||
| s > n-1 ) : | ||
| if (r == None or r > (pow(2,size*8)-1) or | ||
| s == 0 or s >= n ) : | ||
| return False | ||
@@ -273,3 +281,3 @@ hasher = self._hasher() | ||
| rW = r*pu_key.W | ||
| Q = sG - rW | ||
| Q = sG - rW | ||
| xQ = Q.x.to_bytes(size,'big') | ||
@@ -280,7 +288,7 @@ yQ = Q.y.to_bytes(size,'big') | ||
| v = int.from_bytes(v,'big') | ||
| elif self.option == "ISOx": | ||
| sG = s * G | ||
| rW = r*pu_key.W | ||
| Q = sG - rW | ||
| Q = sG - rW | ||
| xQ = Q.x.to_bytes(size,'big') | ||
@@ -290,7 +298,7 @@ hasher.update(xQ+msg) | ||
| v = int.from_bytes(v,'big') | ||
| elif self.option == "BSI": | ||
| sG = s * G | ||
| rW = r*pu_key.W | ||
| Q = sG + rW | ||
| Q = sG + rW | ||
| xQ = (Q.x).to_bytes(size,'big') | ||
@@ -302,3 +310,3 @@ hasher.update(msg+xQ) | ||
| elif self.option == "LIBSECP": | ||
| rb = r.to_bytes(size,'big') | ||
| rb = r.to_bytes(size,'big') | ||
| hasher.update(rb+msg) | ||
@@ -332,5 +340,5 @@ h = hasher.digest() | ||
| return v == r | ||
| if __name__ == "__main__": | ||
| import sys | ||
| import sys,random | ||
| try: | ||
@@ -400,3 +408,3 @@ cv = Curve.get_curve('NIST-P256') | ||
| expect_s = 0xacd417b277ab7e7d993cc4a601dd01a71696fd0dd2e93561d9de9b69dd4dc75c | ||
| signer = ECSchnorr(hashlib.sha256,"LIBSECP","ITUPLE") | ||
@@ -407,3 +415,37 @@ sig = signer.sign_k(msg,pv_key,k) | ||
| assert(signer.verify(msg,sig,pu_key)) | ||
| def _round8(v): | ||
| v += 7 | ||
| return v-v%8 | ||
| CURVES = ["secp256k1", "secp256r1", "Brainpool-p256r1", "Brainpool-p256t1"] | ||
| MODES = ["LIBSECP", "ISO", "ISOx", "BSI", "Z"] | ||
| SUCCESS_LIMIT = 100 | ||
| hashname = "sha256" | ||
| for curvename in CURVES: | ||
| for modename in MODES: | ||
| print(f"CURVE={curvename}, MODE={modename}, HASH={hashname}") | ||
| i = 1 | ||
| while i < SUCCESS_LIMIT: | ||
| hasher = eval(f"hashlib.{hashname}")() | ||
| hasherclass = eval(f"hashlib.{hashname}") | ||
| curveobj = Curve.get_curve(curvename) | ||
| curvesize = _round8(curveobj.size)//8 | ||
| signer = ECSchnorr(hasherclass, option=modename) | ||
| d = random.randint(0, curveobj.order) | ||
| priv_key = ECPrivateKey(d, curveobj) | ||
| pub_key = priv_key.get_public_key() | ||
| msg = random.randint(0, pow(2, 256)) | ||
| msg = msg.to_bytes(32, 'big') | ||
| hasher.update(msg) | ||
| msg = hasher.digest() | ||
| sig_host = signer.sign(msg, priv_key) | ||
| try: | ||
| assert(signer.verify(msg, sig_host, pub_key)) | ||
| except AssertionError: | ||
| print(f"failed at {i}th round") | ||
| break | ||
| else: | ||
| i += 1 | ||
| # ##OK! | ||
@@ -410,0 +452,0 @@ print("All internal assert OK!") |
+90
-39
@@ -38,18 +38,34 @@ # Copyright 2016 Cedric Mesnil <cedric.mesnil@ubinity.com>, Ubinity SAS | ||
| """ | ||
| if fmt=="DER": | ||
| r = r.to_bytes((r.bit_length()+7)//8, 'big') | ||
| s = s.to_bytes((s.bit_length()+7)//8, 'big') | ||
| if (r[0] & 0x80) == 0x80 : | ||
| r = b'\0'+r | ||
| if (s[0] & 0x80) == 0x80 : | ||
| s = b'\0'+s | ||
| sig = (b'\x30'+int((len(r)+len(s)+4)).to_bytes(1,'big') + | ||
| b'\x02'+int(len(r)).to_bytes(1,'big') + r + | ||
| b'\x02'+int(len(s)).to_bytes(1,'big') + s ) | ||
| def _int2bin(x, size=None): | ||
| if not size: | ||
| size = (x.bit_length()+7)//8 | ||
| return x.to_bytes(size, 'big') | ||
| if fmt=="DER": | ||
| def _strip_leading_zero(x): | ||
| while x[0] == 0: | ||
| x = x[1:] | ||
| if x[0] &0x80: | ||
| x = b'\0'+x | ||
| return x | ||
| def _tlv(t,v): | ||
| """ | ||
| t(bin),v(bin) -> tlv(bin) | ||
| """ | ||
| l = _int2bin(len(v)) | ||
| if len(v) > 0x80: | ||
| l = bytes([0x80 + len(l)])+l | ||
| return t+l+v | ||
| r = _tlv(b'\x02', _strip_leading_zero(_int2bin(r))) | ||
| s = _tlv(b'\x02', _strip_leading_zero(_int2bin(s))) | ||
| sig = _tlv(b'\x30',r+s) | ||
| return sig | ||
| if fmt=="BTUPLE": | ||
| r = r.to_bytes((r.bit_length()+7)//8, 'big') | ||
| s = s.to_bytes((s.bit_length()+7)//8, 'big') | ||
| r = _int2bin(r) | ||
| s = _int2bin(s) | ||
| return (r,s) | ||
@@ -59,8 +75,8 @@ | ||
| return (r,s) | ||
| if fmt=="RAW": | ||
| if size == 0: | ||
| raise ECPyException("size must be specified when encoding in RAW") | ||
| r = r.to_bytes(size, 'big') | ||
| s = s.to_bytes(size, 'big') | ||
| r = _int2bin(r, size) | ||
| s = _int2bin(s, size) | ||
| return r+s | ||
@@ -75,3 +91,3 @@ | ||
| def decode_sig(sig,fmt="DER") : | ||
@@ -81,35 +97,67 @@ """ encore signature according format | ||
| Args: | ||
| rs (bytes,ints,tuple) : r,s value | ||
| rs (bytes,ints,tuple) : r,s value | ||
| fmt (str): 'DER'|'BTUPLE'|'ITUPLES'|'RAW'|'EDDSA' | ||
| Returns: | ||
| ints: (r,s) | ||
| Returns: | ||
| ints: (r,s) | ||
| """ | ||
| def _untlv(tlv): | ||
| t = tlv[0] | ||
| l = tlv[1] | ||
| tlv = tlv[2:] | ||
| if l & 0x80 : | ||
| l = l&0x7F | ||
| if l == 1: | ||
| l = tlv[0] | ||
| tlv = tlv[1:] | ||
| elif l ==2: | ||
| l = tlv[0]<<8 | tlv[1] | ||
| tlv = tlv[2:] | ||
| elif l ==3: | ||
| l = tlv[0]<<16 | tlv[1]<<8 | tlv[2] | ||
| tlv = tlv[3:] | ||
| elif l ==4: | ||
| l = tlv[0]<<24 | tlv[1]<<16 | tlv[2]<<8 | tlv[3] | ||
| tlv = tlv[4:] | ||
| else : | ||
| return None,None,None,None | ||
| if len(tlv)<l: | ||
| return None,None,None,None | ||
| v = tlv[0:l] | ||
| return t,l,v, tlv[l:] | ||
| if fmt=="DER": | ||
| 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] | ||
| if ( sig[0] != 0x30 or | ||
| sig_len != r_len+s_len+6 or | ||
| sig[r_offset-2] != 0x02 or | ||
| sig[s_offset-2] != 0x02 ): | ||
| t,l,v, tail = _untlv(sig) | ||
| if t != 0x30 or len(tail) != 0: | ||
| return None,None | ||
| r = int.from_bytes(sig[r_offset:r_offset+r_len], 'big') | ||
| s = int.from_bytes(sig[s_offset:s_offset+s_len], 'big') | ||
| tr,lr,vr , tail = _untlv(v) | ||
| ts,ls,vs , tail = _untlv(tail) | ||
| if ts != 0x02 or tr != 0x02 or len(tail) != 0: | ||
| return None,None | ||
| r = int.from_bytes(vr, 'big') | ||
| s = int.from_bytes(vs, 'big') | ||
| return r,s | ||
| if fmt=="ITUPLE": | ||
| return (sig[0],sig[1]) | ||
| if fmt=="BTUPLE": | ||
| if fmt=="ITUPLE": | ||
| return sig[0], sig[1] | ||
| if fmt=="BTUPLE": | ||
| r = int.from_bytes(sig[0], 'big') | ||
| s = int.from_bytes(sig[1], 'big') | ||
| s = int.from_bytes(sig[1], 'big') | ||
| return r,s | ||
| if fmt=="RAW": | ||
| l = len(sig)>>1 | ||
| l = len(sig) | ||
| if l & 1: | ||
| return None,None | ||
| l = l>>1 | ||
| r = int.from_bytes(sig[0:l], 'big') | ||
@@ -120,5 +168,8 @@ s = int.from_bytes(sig[l:], 'big') | ||
| if fmt=="EDDSA": | ||
| l = len(sig)>>1 | ||
| l = len(sig) | ||
| if l & 1: | ||
| return None,None | ||
| l = l>>1 | ||
| r = int.from_bytes(sig[0:l], 'little') | ||
| s = int.from_bytes(sig[l:], 'little') | ||
| return r,s |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
143294
2.9%3007
3.55%