def verify(self, signature, hashData): N = numBits(self.q) digest_len = len(hashData) * 8 digest = bytesToNumber(hashData) if N < digest_len: digest >>= digest_len - N signature = compatHMAC(signature) # get r, s keys if not signature: return False body, rest = remove_sequence(signature) if rest: return False r, rest = remove_integer(body) s, rest = remove_integer(rest) if rest: return False if gmpyLoaded or GMPY2_LOADED: r = mpz(r) s = mpz(s) # check the signature if 0 < r < self.q and 0 < s < self.q: w = invMod(s, self.q) u1 = (digest * w) % self.q u2 = (r * w) % self.q v = ((powMod(self.g, u1, self.p) * \ powMod(self.public_key, u2, self.p)) % self.p) % self.q return r == v return False
def _decode_key(self, data): s, padding = der.remove_sequence(data) if padding: if padding not in self.ALLOWED_PADDINGS: raise ValueError("weird padding: %s" % u(binascii.hexlify(data))) data = data[:-len(padding)] key = SigningKey.from_der(data) self.signing_key = key self.verifying_key = key.get_verifying_key() self.size = 256
def _decode_key(self, data): s, padding = der.remove_sequence(data) if padding: if padding not in self.ALLOWED_PADDINGS: raise ValueError("weird padding: %s" % u(binascii.hexlify(data))) data = data[:-len(padding)] key = SigningKey.from_der(data) self.signing_key = key self.verifying_key = key.get_verifying_key() self.size = 256
def rs_from_der(der_encoded_signature): """ Given a DER encoded signature, returns the r and s factors DER format (in hex) : 0x30 b1 0x02 b2 r 0x02 b3 s 0x30 : 1-byte header (2 hex in string format) b1 : 1-byte header, length, in bytes, of the remaining list of bytes (from the first 0x02 to the end) 0x02 : 1-byte header b2 : 1-byte indicating length, in bytes, of r value r : r coordinate as big-endian positive signed integer (i.e. must start between 0x00 and 0x7F) 0x02 : 1-byte header b3 : 1-byte indicating length, in bytes, of s value s : s coordinate as big-endian positive signed integer (i.e. must start between 0x00 and 0x7F) INFO : After hitting my head against the wall and developing this to extract r and s by hand, I found out python-ecdsa had DER decoding functions for that. #RTFC :param der_encoded_signature: :return: r, s """ # Look if library is available try: __import__("ecdsa.der") except ImportError: array = binascii.hexlify(base64.b64decode(der_encoded_signature)) # r r_length = 2 * int(array[6:8], 16) r = array[8:8 + r_length] # s s_offset = 8 + r_length s = array[s_offset + 4:] # Cast them to integers # r = long(r, 16) # s = long(s, 16) r = int(r, 16) s = int(s, 16) else: rs, _ = der.remove_sequence(der.unpem(der_encoded_signature)) r, tail = der.remove_integer(rs) # s, point_str_bitstring = der.remove_integer(tail) s, _ = der.remove_integer(tail) if verbosity >= 2: print("r : " + str(r)) print("s : " + str(s)) return r, s
def set_privkey(self, key): if len(key) >= 214: seq1, rest = der.remove_sequence(key) integer, rest = der.remove_integer(seq1) secret, rest = der.remove_octet_string(rest) tag1, cons1, rest, = der.remove_constructed(rest) tag2, cons2, rest, = der.remove_constructed(rest) point_str, rest = der.remove_bitstring(cons2) self.compressed = ord(point_str[1]) != 4 self.prikey = ecdsa.SigningKey.from_string(secret, curve=secp256k1) else: self.prikey = ecdsa.SigningKey.from_der(key) self.pubkey = self.prikey.get_verifying_key()
ec["publicKey"] = ec_pkcs8_privateKey["publicKey"] der = DER_Encode(ec) #print; dumpasn1(der) #print; dumpasn1(der_test_keys["ec_rfc5915"]) print print "Reencoded PKCS #8 {} static data".format( "matches" if der == der_test_keys["ec_rfc5915"] else "doesn't match") # Paranoia: Make sure we really can load the RFC 5915 we just generated. sk = SigningKey.from_der(der) print print "ECDSA Python library parse of reencoded PKCS #8 data: {!r}".format( sk) # Same thing with ecdsa package ASN.1 utilities. car, cdr = ECDSA_DER.remove_sequence(der_test_keys["ec_pkcs8"]) assert cdr == "" version, cdr = ECDSA_DER.remove_integer(car) assert version == 0 car, ec = ECDSA_DER.remove_sequence(cdr) oid, cdr = ECDSA_DER.remove_object(car) assert oid == oid_ecPublicKey oid, cdr = ECDSA_DER.remove_object(cdr) curve = find_curve(oid) assert cdr == "" car, cdr = ECDSA_DER.remove_octet_string(ec) assert cdr == "" car, cdr = ECDSA_DER.remove_sequence(car) assert cdr == "" version, cdr = ECDSA_DER.remove_integer(car) assert version == 1