.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/fraud/phishing/plot_02_address_poisoning.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code or to run this example in your browser via JupyterLite. .. rst-class:: sphx-glr-example-title .. _sphx_glr_api_gallery_fraud_phishing_plot_02_address_poisoning.py: Address poisoning with look-alike addresses (2022-2023) ======================================================= An Ethereum address is 40 hexadecimal digits, and wallets show only the first and last few. From late 2022, poisoners watched for payments, ground out an address matching the payee's ends, and sent the payer a worthless transfer from it, so that the look-alike appeared in the payer's history right next to the real one. The next payment copied from the history went to the poisoner; in May 2024 one victim sent 68 million dollars this way. Tsuchiya, Dong, Soska and Christin measured millions of such attempts. Matching :math:`k` digits takes about .. math:: \mathbb{E}[\text{trials}] = 16^{k} tries, a few seconds of computing for the eight digits a hurried user checks, and a detector needs only to compare new senders against the addresses the victim has paid. .. GENERATED FROM PYTHON SOURCE LINES 24-28 .. code-block:: Python import matplotlib.pyplot as plt import blockchainkit as bk .. GENERATED FROM PYTHON SOURCE LINES 29-31 The cost of a look-alike ------------------------ .. GENERATED FROM PYTHON SOURCE LINES 31-53 .. code-block:: Python payee = bk.fraud.candidate_address(2023, 0) digits, costs = [], [] for k in range(1, 5): prefix, suffix = (k + 1) // 2, k // 2 found = [ bk.fraud.grind_lookalike(payee, prefix=prefix, suffix=suffix, seed=s).trials for s in range(12 if k < 4 else 3) ] digits.append(k) costs.append(sum(found) / len(found)) print(f"{k} digits: about {costs[-1]:,.0f} trials (16^{k} = {16**k:,})") assert costs == sorted(costs) fig, ax = plt.subplots(figsize=(6, 4)) ax.semilogy(digits, costs, "o", color="#dc2626", label="measured") ax.semilogy(digits, [16**k for k in digits], color="black", label="16^k") ax.set(xlabel="hex digits matched", ylabel="trials", xticks=digits) ax.set_title("Each digit checked multiplies the work by 16") ax.legend() fig.tight_layout() .. image-sg:: /api/gallery/fraud/phishing/images/sphx_glr_plot_02_address_poisoning_001.png :alt: Each digit checked multiplies the work by 16 :srcset: /api/gallery/fraud/phishing/images/sphx_glr_plot_02_address_poisoning_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none 1 digits: about 18 trials (16^1 = 16) 2 digits: about 318 trials (16^2 = 256) 3 digits: about 5,402 trials (16^3 = 4,096) 4 digits: about 62,121 trials (16^4 = 65,536) .. GENERATED FROM PYTHON SOURCE LINES 54-56 Poisoning a history, and spotting it ------------------------------------ .. GENERATED FROM PYTHON SOURCE LINES 56-72 .. code-block:: Python fake = bk.fraud.grind_lookalike(payee, prefix=2, suffix=2, seed=7).address history = [ bk.fraud.Flow("victim", payee, 25_000, 0), bk.fraud.Flow(fake, "victim", 0, 1), # The poisoner's zero-value transfer. ] print("payee:", payee) print("fake: ", fake) latest = history[-1].sender # The address a hurried user copies. assert bk.fraud.looks_alike(latest, payee, prefix=2, suffix=2) suspects = bk.fraud.poisoning_suspects(history, "victim", prefix=2, suffix=2) print("suspects:", suspects) assert suspects == (fake,) plt.show() .. rst-class:: sphx-glr-script-out .. code-block:: none payee: 0x7ae9ac40a05f19d12331ae1d17d88c878fc2b531 fake: 0x7a2a49df20c31827a7251eff85a5e4ca91f55e31 suspects: ('0x7a2a49df20c31827a7251eff85a5e4ca91f55e31',) .. GENERATED FROM PYTHON SOURCE LINES 73-78 Exercise -------- A wallet shows six characters at each end. How long does a poisoner computing ten million addresses a second need to match all twelve? A worked solution is in :doc:`/exercises/fraud`. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 2.018 seconds) .. _sphx_glr_download_api_gallery_fraud_phishing_plot_02_address_poisoning.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: lite-badge .. image:: images/jupyterlite_badge_logo.svg :target: ../../../../lite/lab/index.html?path=api/gallery/fraud/phishing/plot_02_address_poisoning.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_02_address_poisoning.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_02_address_poisoning.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_02_address_poisoning.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_