def sign_stream_claim(self, claim, claim_address, cert_claim_id): validate_claim_id(cert_claim_id) decoded_addr = decode_address(claim_address) to_sign = bytearray() to_sign.extend(decoded_addr) to_sign.extend(claim.serialized_no_signature) to_sign.extend(binascii.unhexlify(cert_claim_id)) digest = self.HASHFUNC(to_sign).digest() if not isinstance(self.private_key, ecdsa.SigningKey): raise Exception("Not given a signing key") sig_dict = { "version": V_0_0_1, "signatureType": self.CURVE_NAME, "signature": self.private_key.sign_digest_deterministic(digest, hashfunc=self.HASHFUNC), "certificateId": binascii.unhexlify(cert_claim_id) } msg = { "version": V_0_0_1, "stream": decode_b64_fields(claim.protobuf_dict)['stream'], "publisherSignature": sig_dict } return Claim.load(msg)
def test_validate_what_cant_be_serialized_back_even_by_loading_back_from_dictionary( self): cert = ClaimDict.generate_certificate(secp256k1_private_key, curve=SECP256k1) self.assertDictEqual(cert.claim_dict, secp256k1_cert) original = ClaimDict.load_dict(example_010).serialized altered = original + b'\x00\x01\x02\x30\x50\x80\x99' # pretend this extra trash is from some unknown protobuf # manually sign signer = get_signer(SECP256k1).load_pem(secp256k1_private_key) signature = signer.sign( b'example', decode_address(claim_address_2), altered, binascii.unhexlify(claim_id_1), ) detached_sig = Signature( NAMED_SECP256K1(signature, binascii.unhexlify(claim_id_1), altered)) signed = detached_sig.serialized self.assertEqual(signed[85:], altered) signed_copy = ClaimDict.deserialize(signed) signed_copy = ClaimDict.load_dict(signed_copy.claim_dict) self.assertEqual( signed_copy.validate_signature(claim_address_2, cert, name='example'), True) self.assertEqual(signed, signed_copy.serialized)
def decode_fields(claim_dictionary): """Decode hex and b58 encoded bytes in dictionaries given to ClaimDict""" claim_dictionary = deepcopy(claim_dictionary) claim_type = CLAIM_TYPES[claim_dictionary[CLAIM_TYPE]] claim_value = claim_dictionary[claim_type] if claim_type == CLAIM_TYPES[STREAM_TYPE]: claim_value['source']['source'] = binascii.unhexlify( claim_value['source']['source']) if 'fee' in claim_value['metadata']: try: address = decode_address( claim_value['metadata']['fee']['address']) except InvalidAddress as err: raise DecodeError("Invalid fee address: %s" % err) claim_value['metadata']['fee']['address'] = address elif claim_type == CLAIM_TYPES[CERTIFICATE_TYPE]: public_key = binascii.unhexlify(claim_value["publicKey"]) claim_value["publicKey"] = public_key if SIGNATURE in claim_dictionary: decoded_sig = binascii.unhexlify( claim_dictionary[SIGNATURE]['signature']) decoded_cert_id = binascii.unhexlify( claim_dictionary[SIGNATURE]['certificateId']) claim_dictionary[SIGNATURE]['signature'] = decoded_sig claim_dictionary[SIGNATURE]['certificateId'] = decoded_cert_id claim_dictionary[claim_type] = claim_value return claim_dictionary
def protobuf(self): pb = { "version": self.version, "currency": CURRENCY_MAP[self.currency], "address": decode_address(self.address), "amount": self.amount } return FeeHelper.load(pb)
async def main(address: str): try: decode_address(address) except: print(f"'{address}' is not a valid lbrycrd address") return 1 loop = asyncio.get_running_loop() storage = SQLiteStorage(os.path.expanduser("~/.lbrynet/lbrynet.sqlite")) await storage.open() blob_manager = BlobManager(loop, os.path.expanduser("~/.lbrynet/blobfiles"), storage) await blob_manager.setup() server = await loop.create_server( lambda: BlobServer(loop, blob_manager, address), '0.0.0.0', 4444) try: async with server: await server.serve_forever() finally: await storage.close()
def migrate(fee): if len(list(fee.keys())) == 3 and 'currency' in fee and 'amount' in fee and 'address' in fee: return FeeHelper.load({ "version": "_0_0_1", "currency": fee['currency'], "amount": fee['amount'], "address": decode_address(fee['address']) }) if len(list(fee.keys())) > 1: raise Exception("Invalid fee") currency = list(fee.keys())[0] amount = fee[currency]['amount'] address = fee[currency]['address'] return FeeHelper.load({ "version": "_0_0_1", "currency": currency, "amount": amount, "address": decode_address(address) })
def validate_claim_signature(self, claim, claim_address): decoded_address = decode_address(claim_address) # extract and serialize the stream from the claim, then check the signature signature = binascii.unhexlify(claim.signature) if signature is None: raise Exception("No signature to validate") to_sign = bytearray() to_sign.extend(decoded_address) to_sign.extend(claim.serialized_no_signature) to_sign.extend(binascii.unhexlify(self.certificate_claim_id)) return self.validate_signature(self.HASHFUNC(to_sign).digest(), signature)
def sign_stream_claim(self, claim, claim_address, cert_claim_id, name, detached=False): validate_claim_id(cert_claim_id) raw_cert_id = binascii.unhexlify(cert_claim_id) decoded_addr = decode_address(claim_address) if detached: assert name, "Name is required for detached signatures" assert self.CURVE_NAME == SECP256k1, f"Only SECP256k1 is supported, not: {self.CURVE_NAME}" signature = self.sign( name.lower().encode(), decoded_addr, claim.serialized_no_signature, raw_cert_id, ) else: signature = self.sign(decoded_addr, claim.serialized_no_signature, raw_cert_id) if detached: return Claim.load(decode_b64_fields( claim.protobuf_dict)), Signature( NAMED_SECP256K1(signature, raw_cert_id, claim.serialized_no_signature)) # -- Legacy signer (signature inside protobuf) -- if not isinstance(self.private_key, ecdsa.SigningKey): raise Exception("Not given a signing key") sig_dict = { "version": V_0_0_1, "signatureType": self.CURVE_NAME, "signature": signature, "certificateId": raw_cert_id } msg = { "version": V_0_0_1, "stream": decode_b64_fields(claim.protobuf_dict)['stream'], "publisherSignature": sig_dict } proto = Claim.load(msg) return proto, Signature.flagged_parse(proto.SerializeToString())
async def test_new_signature_model_from_unserializable_claim(self): address1, address2 = await self.account.receiving.get_addresses( limit=2, only_usable=True) sendtxid1 = await self.blockchain.send_to_address(address1, 5) sendtxid2 = await self.blockchain.send_to_address(address2, 5) await self.blockchain.generate(1) await asyncio.wait([ self.on_transaction_id(sendtxid1), self.on_transaction_id(sendtxid2) ]) self.assertEqual(d2l(await self.account.get_balance()), '10.0') cert, key = generate_certificate() cert_tx = await Transaction.claim('@bar', cert, l2d('1.0'), address1, [self.account], self.account) original = ClaimDict.load_dict(example_claim_dict).serialized altered = original + b'\x00\x01\x02\x30\x50\x80\x99' # pretend this extra trash is from some unknown protobuf # manually sign signer = get_signer(SECP256k1).load_pem(key) signature = signer.sign( b'foo', decode_address(address1), altered, binascii.unhexlify(cert_tx.outputs[0].claim_id), ) detached_sig = Signature( NAMED_SECP256K1(signature, binascii.unhexlify(cert_tx.outputs[0].claim_id), altered)) claim_tx = await Transaction.claim('foo', detached_sig, l2d('1.0'), address1, [self.account], self.account) await self.broadcast(cert_tx) await self.broadcast(claim_tx) await self.ledger.wait(claim_tx) await self.blockchain.generate(1) await self.ledger.wait(claim_tx) response = await self.ledger.resolve(0, 10, 'lbry://@bar/foo') self.assertIn('lbry://@bar/foo', response) self.assertIn('claim', response['lbry://@bar/foo'])
def validate_claim_signature(self, claim, claim_address, name): to_sign = bytearray() if claim.detached_signature and claim.detached_signature.raw_signature: assert name is not None, "Name is required for verifying detached signatures." to_sign.extend(name.lower().encode()) signature = claim.detached_signature.raw_signature payload = claim.detached_signature.payload else: # extract and serialize the stream from the claim, then check the signature signature = binascii.unhexlify(claim.signature) payload = claim.serialized_no_signature decoded_address = decode_address(claim_address) if signature is None: raise Exception("No signature to validate") to_sign.extend(decoded_address) to_sign.extend(payload) to_sign.extend(binascii.unhexlify(self.certificate_claim_id)) return self.validate_signature(self.HASHFUNC(to_sign).digest(), signature)
def test_regtest_address_decode_error(self): with self.assertRaises(InvalidAddress): decode_address("bW5PZEvEBNPQRVhwpYXSjabFgbSw1oaHyR") with self.assertRaises(InvalidAddress): decode_address("mzGSynizDwSgURdnFjosZwakSVuZrdE8V5")
def test_regtest_address_encode_decode(self): valid_addr_hex = "6fcdac187757dbf05500f613ada6fdd953d59b9acbf3c9343f" self.assertEqual(encode_address(binascii.unhexlify(valid_addr_hex)), b"mzGSynizDwSgURdnFjosZwakSVuZrdE8V4") self.assertEqual(decode_address("mzGSynizDwSgURdnFjosZwakSVuZrdE8V4"), binascii.unhexlify(valid_addr_hex))
def test_mainnet_address_encode_decode(self): valid_addr_hex = "55be482f953ed0feda4fc5c4d012681b6119274993dc96bf10" self.assertEqual(encode_address(binascii.unhexlify(valid_addr_hex)), b"bW5PZEvEBNPQRVhwpYXSjabFgbSw1oaHyR") self.assertEqual(decode_address("bW5PZEvEBNPQRVhwpYXSjabFgbSw1oaHyR"), binascii.unhexlify(valid_addr_hex))