def export_recovery_seed(self, allow_algs): for alg in allow_algs: if alg == 0: if self._recovery_seed_pri_key is None: self._initialize_recovery_seed() S = fastecdsa.keys.get_public_key(self._recovery_seed_pri_key, P256) S_enc = encode_pub(S) signed_data = struct.pack('>B16s65s', alg, self._aaguid, S_enc) sig = DEREncoder.encode_signature( *ecdsa.sign( signed_data, self._attestation_key, hashfunc=hashlib.sha256 ) ) payload = { 1: alg, 2: [], 3: self._aaguid, 4: sig, -1: S_enc, } return cbor.encode(payload) raise UnknownKeyAgreementScheme(allow_algs)
def sign(signing_key: SigningKey, message_digest_bytes: bytes) -> bytes: r, s = ecdsa.sign( message_digest_bytes.hex(), signing_key, curve=curve.secp256k1, prehashed=True, ) return DEREncoder.encode_signature(r, s)
def signVote(self, privateKey): # Assina a cédula r, s = ecdsa.sign(self.voteHash, privateKey, curve=curve.secp256k1, hashfunc=hl.sha256) # Transforma a assinatura para DER self.signature = DEREncoder.encode_signature(r, s)
def authenticator_make_credential(self, args_cbor): args = cbor.decode(args_cbor) clientDataJSON_hash = args[0x01] rp_id = args[0x02]['id'] extension_inputs = args[0x06] rp_id_hash = sha256(rp_id.encode('utf-8')) flags = 0b11000001 # ED, AT, UP sign_count = 0 credential_id = secrets.token_bytes(32) (credential_private_key, credential_public_key) = fastecdsa.keys.gen_keypair(P256) self._credentials[credential_id] = credential_private_key attested_cred_data = pack_attested_credential_data( self._aaguid, credential_id, credential_public_key, ) authData_without_extensions = struct.pack( f'>32sBL{len(attested_cred_data)}s', rp_id_hash, flags, sign_count, attested_cred_data, ) extensions = {} if "recovery" in extension_inputs: extensions["recovery"] = self.process_recovery_extension( rp_id, authData_without_extensions, clientDataJSON_hash, extension_inputs["recovery"], ) authData = authData_without_extensions + cbor.encode(extensions) attStmt = { 0x01: 'packed', 0x02: authData, 0x03: { 'alg': -7, 'sig': DEREncoder.encode_signature( *ecdsa.sign( authData + clientDataJSON_hash, credential_private_key, hashfunc=hashlib.sha256 ) ), }, } return cbor.encode(attStmt)
def test_encode_decode_all_curves(self): for curve in CURVES: d = randint(1, curve.q) Q = d * curve.G r, s = sign("sign me", d, curve=curve) encoded = DEREncoder.encode_signature(r, s) decoded_r, decoded_s = DEREncoder.decode_signature(encoded) self.assertEqual(decoded_r, r) self.assertEqual(decoded_s, s)
def build_authorization_header(self): """Build authorization headers.""" if len(self.required_authorization_headers) > 0: self.authorization_parameters['headers'] = '{}'.format(' '.join([ header.lower() for header in self.required_authorization_headers ])) self.build_signing_string() signing_bytestring = self.signing_string.encode(self.encoding) if self.signing_algorithm == 'RSA': signer = RSA.import_key(self.private_key_string) if self.hashing_algorithm == 'SHA256': hash_obj = SHA256.new(signing_bytestring) elif self.hashing_algorithm == 'SHA512': hash_obj = SHA512.new(signing_bytestring) else: raise Exception("Invalid key type") signature = pkcs1_15.new(signer).sign(hash_obj) else: private_key, public_key = PEMEncoder.decode_private_key( self.private_key_string) if self.hashing_algorithm == 'SHA256': hash_function = hashlib.sha256 elif self.hashing_algorithm == 'SHA512': hash_function = hashlib.sha512 else: raise Exception("Invalid key type") if self.signing_algorithm.lower() == 'p256': r, s = ecdsa.sign(signing_bytestring, private_key, curve=curve.P256, hashfunc=hash_function) else: raise Exception("Invalid key type") signature = DEREncoder.encode_signature(r, s) base64_signature = base64.b64encode(signature).decode(self.encoding) self.authorization_parameters['signature'] = '{}'.format( base64_signature) authorization_rows = [] for key, value in self.authorization_parameters.items(): if isinstance(value, str): authorization_rows.append('{}="{}"'.format(key, value)) elif isinstance(value, int) or isinstance(value, float): authorization_rows.append('{}={}'.format(key, value)) elif isinstance(value, bool): if value is True: authorization_rows.append('{}=true') else: authorization_rows.append('{}=false') authorization_header = 'Signature {}'.format( ','.join(authorization_rows)) self.headers['Authorization'] = authorization_header
def sign(signing_key: SigningKey, message_digest_bytes: bytes) -> bytes: r, s = ecdsa.sign( message_digest_bytes, signing_key, curve=curve.secp256k1, prehashed=True, ) # Both (r, s) and (r, -s mod q = q - s) are valid, canonical signatures. # (r, s) is fully canonical only when s <= q - s. s_inverse = curve.secp256k1.q - s if s > s_inverse: s = s_inverse return DEREncoder.encode_signature(r, s)
def der_encode_sig(r, s): """ Create DER encoded signature string with signature r and s value :param r: r value of signature :type r: int :param s: s value of signature :type s: int :return bytes: """ if USE_FASTECDSA: return DEREncoder.encode_signature(r, s) else: ecdsa.der.sigencode_der(r, s)
def sign(message: bytes, private_key: PrivateKey) -> Signature: digest = hashes.sha512half(message) signing_key = int.from_bytes(private_key, byteorder='big') r, s = ecdsa.sign( digest.hex(), signing_key, curve=curve.secp256k1, prehashed=True, ) # Both (r, s) and (r, -s mod G = G - s) are valid, canonical signatures. # (r, s) is fully canonical only when s <= G - s. s_inverse = GROUP_ORDER - s if s > s_inverse: s = s_inverse signature = DEREncoder.encode_signature(r, s) return t.cast(Signature, signature)
def authenticator_get_assertion(self, args_cbor): args = cbor.decode(args_cbor) rp_id = args[0x01] clientDataJSON_hash = args[0x02] extension_inputs = args[0x04] rp_id_hash = sha256(rp_id.encode('utf-8')) flags = 0b10000001 # ED, UP sign_count = 0 extensions = {} authData_without_extensions = struct.pack( f'>32sBL', rp_id_hash, flags, sign_count, ) if "recovery" in extension_inputs: extensions["recovery"] = self.process_recovery_extension( rp_id, authData_without_extensions, clientDataJSON_hash, extension_inputs["recovery"] ) authData = authData_without_extensions + cbor.encode(extensions) sig = None for cred_descriptor in args[0x03]: if cred_descriptor['id'] in self._credentials: sig = DEREncoder.encode_signature( *ecdsa.sign( authData + clientDataJSON_hash, self._credentials[cred_descriptor['id']], hashfunc=hashlib.sha256 ) ) break if sig is None: raise NoCredentialAvailable() return cbor.encode({ 0x01: cred_descriptor, 0x02: authData, 0x03: sig, })
def der_encode_sig(r, s): """ Create DER encoded signature string with signature r and s value. :param r: r value of signature :type r: int :param s: s value of signature :type s: int :return bytes: """ if USE_FASTECDSA: return DEREncoder.encode_signature(r, s) else: rb = ecdsa.der.encode_integer(r) sb = ecdsa.der.encode_integer(s) return ecdsa.der.encode_sequence(rb, sb)
def _generate_recovery_signature( self, rp_id, authData_without_extensions, clientDataHash, allow_credentials, ): if self._recovery_seed_pri_key is None: return InvalidState() for cred in allow_credentials: cred_id = cred['id'] alg = cred_id[0] if alg == 0: try: cred_pri = self._derive_private_key( self._recovery_seed_pri_key, cred_id, rp_id) sig = DEREncoder.encode_signature( *ecdsa.sign( authData_without_extensions + clientDataHash, cred_pri, hashfunc=hashlib.sha256 ) ) except RpIdMismatch: continue else: continue extension_output = { 'action': 'recover', 'credId': cred_id, 'sig': sig, 'state': self._state, } return extension_output raise NoCredentialAvailable()
def test_encode_signature(self): self.assertEqual( DEREncoder.encode_signature(r=1, s=2), b"\x30" # SEQUENCE b"\x06" # Length of Sequence b"\x02" # INTEGER b"\x01" # Length of r b"\x01" # r b"\x02" # INTEGER b"\x01" # Length of s b"\x02", # s ) # Check that we add a zero byte when the number's highest bit is set self.assertEqual(DEREncoder.encode_signature(r=128, s=128), b"0\x08\x02\x02\x00\x80\x02\x02\x00\x80") # Check a value on a standard curve like secp256k1 works # see https://github.com/btccom/secp256k1-go/blob/master/secp256k1/sign_vectors.yaml secp256k1_vectors = [ ( 0x31a84594060e103f5a63eb742bd46cf5f5900d8406e2726dedfc61c7cf43ebad, unhexlify( "9e5755ec2f328cc8635a55415d0e9a09c2b6f2c9b0343c945fbbfe08247a4cbe" ), unhexlify( "30440220132382ca59240c2e14ee7ff61d90fc63276325f4cbe8169fc53ade4a407c2fc802204d86fbe3bde69" "75dd5a91fdc95ad6544dcdf0dab206f02224ce7e2b151bd82ab"), ), ( 0x7177f0d04c79fa0b8c91fe90c1cf1d44772d1fba6e5eb9b281a22cd3aafb51fe, unhexlify( "2d46a712699bae19a634563d74d04cc2da497b841456da270dccb75ac2f7c4e7" ), unhexlify( "3045022100d80cf7abc9ab601373780cee3733d2cb5ff69ba1452ec2d2a058adf9645c13be0220011d1213b7d" "152f72fd8759b45276ba32d9c909602e5ec89550baf3aaa8ed950"), ), ( 0x989e500d6b1397f2c5dcdf43c58ac2f14df753eb6089654e07ff946b3f84f3d5, unhexlify( "c94f4ec84be928017cbbb447d2ab5b5d4d69e5e5fd03da7eae4378a1b1c9c402" ), unhexlify( "3045022100d0f5b740cbe3ee5b098d3c5afdefa61bb0797cb4e7b596afbd38174e1c653bb602200329e9f1a09" "632de477664814791ac31544e04715db68f4b02657ba35863e711"), ), ( 0x39dfc615f2b718397f6903b0c46c47c5687e97d3d2a5e1f2b200f459f7b1219b, unhexlify( "dfeb2092955572ce0695aa038f58df5499949e18f58785553c3e83343cd5eb93" ), unhexlify( "30440220692c01edf8aeab271df3ed4e8d57a170f014f8f9d65031aac28b5e1840acfb5602205075f9d1fdbf5" "079ee052e5f3572d518b3594ef49582899ec44d065f71a55192"), ), ] for private_key, digest, expected in secp256k1_vectors: r, s = sign(digest, private_key, curve=secp256k1, prehashed=True) encoded = DEREncoder.encode_signature(r, s) self.assertEqual(encoded, expected)
def sign(self, message_bytes): r, s = ecdsa.sign(message_bytes, self.private_key, curve=self.public_key.curve) return DEREncoder.encode_signature(r, s).hex()
def address(self): return base64.b64encode(DEREncoder.encode_signature( self.public_key.x, self.public_key.y))
def _sign_transaction(self, transaction): r, s = ecdsa.sign(transaction.data, self.private_key, curve=Wallet._curve) signature = base64.b64encode(DEREncoder.encode_signature(r, s)) transaction.add_signature(signature)