Last active
February 16, 2025 03:27
-
-
Save WitherOrNot/d467df09161164f1f1846a61b55a7d6d to your computer and use it in GitHub Desktop.
PIDGENX validation implementation in SageMath (works on SageMath 9.0)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "cells": [ | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "The math in this notebook is described in [this patent](https://patentimages.storage.googleapis.com/a3/27/c1/3c0948a078cb28/US7587605.pdf). Be warned, the math is very complicated." | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "# Windows 7 Retail/GVLK, public key ID 170\n", | |
| "\n", | |
| "pubkey_data = {\n", | |
| " \"field\": {\n", | |
| " \"modulus\": 886368969471450739924935101400677,\n", | |
| " \"ec_base_order\": 886368969471450710152985728350703,\n", | |
| " \"k3_minpoly\": [\n", | |
| " 4,\n", | |
| " 1,\n", | |
| " 0,\n", | |
| " 1\n", | |
| " ],\n", | |
| " \"k6_minpoly\": [\n", | |
| " 2,\n", | |
| " 0,\n", | |
| " 1\n", | |
| " ]\n", | |
| " },\n", | |
| " \"h1_bases\": [\n", | |
| " 1,\n", | |
| " 3,\n", | |
| " 8,\n", | |
| " 15,\n", | |
| " 15,\n", | |
| " 15,\n", | |
| " 31,\n", | |
| " 3,\n", | |
| " 3,\n", | |
| " 3,\n", | |
| " 3,\n", | |
| " 3,\n", | |
| " 7,\n", | |
| " 63\n", | |
| " ],\n", | |
| " \"curve\": {\n", | |
| " \"a\": 26392827536965106777121445123290,\n", | |
| " \"b\": 372325368096095544195525883520589\n", | |
| " },\n", | |
| " \"points\": [\n", | |
| " {\n", | |
| " \"x\": [\n", | |
| " 365236101742748463929673543888206,\n", | |
| " 858097895593939865996182272259769,\n", | |
| " 148438159087534462792506738986740\n", | |
| " ],\n", | |
| " \"y\": [\n", | |
| " 776418047571862972603801173382237,\n", | |
| " 873677028107508092012208744232957,\n", | |
| " 622138327043805563266794621920098\n", | |
| " ]\n", | |
| " },\n", | |
| " {\n", | |
| " \"x\": [\n", | |
| " 940136574680879136511599445781,\n", | |
| " 566978253317108608042529258054523,\n", | |
| " 176284220413545220121710961573292\n", | |
| " ],\n", | |
| " \"y\": [\n", | |
| " 828856809691743749590800150937649,\n", | |
| " 225146018128364550960496522448712,\n", | |
| " 348601659612301002638949468744847\n", | |
| " ]\n", | |
| " },\n", | |
| " {\n", | |
| " \"x\": [\n", | |
| " 733747358623171948496764545320051,\n", | |
| " 728506535527490173098593825125337,\n", | |
| " 82462451162574422717677160727098\n", | |
| " ],\n", | |
| " \"y\": [\n", | |
| " 416331132638004657079841565104549,\n", | |
| " 366794872410090667339979925100938,\n", | |
| " 154519017608105570119249112044121\n", | |
| " ]\n", | |
| " },\n", | |
| " {\n", | |
| " \"x\": [\n", | |
| " 849718119860311390685018324089317,\n", | |
| " 69736499980142833460080381132368,\n", | |
| " 72139323263966224829624934948858\n", | |
| " ],\n", | |
| " \"y\": [\n", | |
| " 122550620604034160835298121626961,\n", | |
| " 232865179257577260620478614346661,\n", | |
| " 96495922331236902442197840422963\n", | |
| " ]\n", | |
| " },\n", | |
| " {\n", | |
| " \"x\": [\n", | |
| " 737949449696062407373114808812927,\n", | |
| " 526576673882551145431025311648593,\n", | |
| " 577710732700754839750249914833193\n", | |
| " ],\n", | |
| " \"y\": [\n", | |
| " 245977198113437420529250724111432,\n", | |
| " 316396368275232555978824338443046,\n", | |
| " 755792900000892204654488821885538\n", | |
| " ]\n", | |
| " },\n", | |
| " {\n", | |
| " \"x\": [\n", | |
| " 712586405875738967442641545880322,\n", | |
| " 615445286425878710157557053762371,\n", | |
| " 734183236086095230968388017605820\n", | |
| " ],\n", | |
| " \"y\": [\n", | |
| " 851284376759840359812981263306021,\n", | |
| " 769237654873203944088649987250083,\n", | |
| " 359324880331507581802773028306633\n", | |
| " ]\n", | |
| " },\n", | |
| " {\n", | |
| " \"x\": [\n", | |
| " 579665839598807564349118802507078,\n", | |
| " 793103874095793223248478622956780,\n", | |
| " 502860226530799804560661048077280\n", | |
| " ],\n", | |
| " \"y\": [\n", | |
| " 526775274489316486107329470634542,\n", | |
| " 828721161962151275145535457964404,\n", | |
| " 204415317809040518371881977645416\n", | |
| " ]\n", | |
| " },\n", | |
| " {\n", | |
| " \"x\": [\n", | |
| " 804790447447351785544412956578788,\n", | |
| " 119046642031064430140912082580578,\n", | |
| " 475159529884254928674792290619954\n", | |
| " ],\n", | |
| " \"y\": [\n", | |
| " 458245266057063984580129835988070,\n", | |
| " 338411981227059768831710308435687,\n", | |
| " 577923375329917551735757167190702\n", | |
| " ]\n", | |
| " },\n", | |
| " {\n", | |
| " \"x\": [\n", | |
| " 448295070796654878810211055051604,\n", | |
| " 482910785083759911781193909334072,\n", | |
| " 795628820954832750108065551162801\n", | |
| " ],\n", | |
| " \"y\": [\n", | |
| " 417757375223493128894380427308216,\n", | |
| " 755520039102173573177271365439537,\n", | |
| " 863842006193777913816171128026446\n", | |
| " ]\n", | |
| " },\n", | |
| " {\n", | |
| " \"x\": [\n", | |
| " 663389221842281261857262032548436,\n", | |
| " 846447543951704162020988219326272,\n", | |
| " 686142287698732386980948449542167\n", | |
| " ],\n", | |
| " \"y\": [\n", | |
| " 769015970121598916167134609518482,\n", | |
| " 738460771147019950148429256265493,\n", | |
| " 613009789239563486872501072748270\n", | |
| " ]\n", | |
| " },\n", | |
| " {\n", | |
| " \"x\": [\n", | |
| " 23530113060362511985797534739195,\n", | |
| " 718131004725002854064127778364823,\n", | |
| " 140870968646848990835780066321375\n", | |
| " ],\n", | |
| " \"y\": [\n", | |
| " 641031697928634900295866764583620,\n", | |
| " 295544383156746469642549388283327,\n", | |
| " 133766761871461067699690599056442\n", | |
| " ]\n", | |
| " },\n", | |
| " {\n", | |
| " \"x\": [\n", | |
| " 7518354584460889742005963384331,\n", | |
| " 340825540582760123772991939806390,\n", | |
| " 525549834323799848592419044187971\n", | |
| " ],\n", | |
| " \"y\": [\n", | |
| " 585295007893871934790357000030208,\n", | |
| " 117490751031779271453224407217079,\n", | |
| " 838852298106199238437827740364400\n", | |
| " ]\n", | |
| " },\n", | |
| " {\n", | |
| " \"x\": [\n", | |
| " 806036388470182281562651653929939,\n", | |
| " 266085928879449679004785507000719,\n", | |
| " 201474020142460453395308745398496\n", | |
| " ],\n", | |
| " \"y\": [\n", | |
| " 573468377549807523205344415925956,\n", | |
| " 667459718759242575444856430313959,\n", | |
| " 226975716159080217447594275999935\n", | |
| " ]\n", | |
| " },\n", | |
| " {\n", | |
| " \"x\": [\n", | |
| " 794167987155642331621801361756614,\n", | |
| " 809201520617560616339201020039820,\n", | |
| " 198696155869194654384403079624544\n", | |
| " ],\n", | |
| " \"y\": [\n", | |
| " 725959545288387914551997303844726,\n", | |
| " 49262476800238214847233993847181,\n", | |
| " 537326577113493149345527624223733\n", | |
| " ]\n", | |
| " }\n", | |
| " ],\n", | |
| " \"pairing_val\": [\n", | |
| " [\n", | |
| " 242940802691096077821709859741616,\n", | |
| " 178851543248946074944443141484182,\n", | |
| " 802059826004050667481466713086225\n", | |
| " ],\n", | |
| " [\n", | |
| " 701042518368651902930590425782509,\n", | |
| " 265571225406900742458432149860962,\n", | |
| " 699432283102586243018242179516873\n", | |
| " ]\n", | |
| " ]\n", | |
| "}" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "p = pubkey_data[\"field\"][\"modulus\"]\n", | |
| "a = pubkey_data[\"curve\"][\"a\"]\n", | |
| "b = pubkey_data[\"curve\"][\"b\"]\n", | |
| "order = pubkey_data[\"field\"][\"ec_base_order\"]\n", | |
| "h1_bases = list(map(lambda x: x+1, pubkey_data[\"h1_bases\"]))\n", | |
| "KCHARS = \"BCDFGHJKMPQRTVWXY2346789\"\n", | |
| "\n", | |
| "def decode_pkey(k):\n", | |
| " k = k.replace(\"-\", \"\")\n", | |
| " out = 0\n", | |
| " \n", | |
| " for c in k:\n", | |
| " out *= 24\n", | |
| " out += KCHARS.index(c)\n", | |
| " \n", | |
| " return out\n", | |
| "\n", | |
| "K = GF(p)\n", | |
| "Kx.<x> = K[]\n", | |
| "K3.<u> = K.extension(Kx(pubkey_data[\"field\"][\"k3_minpoly\"]))\n", | |
| "K3y.<y> = K3[]\n", | |
| "K6.<t> = K3.extension(K3y(pubkey_data[\"field\"][\"k6_minpoly\"]))\n", | |
| "\n", | |
| "E = EllipticCurve(K, [a, b])\n", | |
| "E6 = EllipticCurve(K6, [a, b])\n", | |
| "\n", | |
| "Qi = [E6(K3(point[\"x\"]) * t^-2, K3(point[\"y\"]) * t^-3) for point in pubkey_data[\"points\"]]\n", | |
| "\n", | |
| "# pairing_val = e_m(P, S)\n", | |
| "pairing_val = K6([K3(pubkey_data[\"pairing_val\"][0]), K3(pubkey_data[\"pairing_val\"][1])])\n", | |
| "\n", | |
| "assert is_prime(p)\n", | |
| "assert len(h1_bases) == len(Qi)\n", | |
| "assert h1_bases[0] == 2\n", | |
| "assert pairing_val^order == 1" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "pkey_chars = \"33PXH-7Y6KF-2VJC9-XBBR8-HVTHH\"\n", | |
| "\n", | |
| "# pkey = HASH(M)\n", | |
| "# HASH is a currently unknown hash function\n", | |
| "pkey = decode_pkey(pkey_chars)\n", | |
| "\n", | |
| "# h1_coeffs = H1(M)\n", | |
| "# During validation, coeffs must be found by a search that i havent implemented\n", | |
| "# h1_coeffs = [1, 0, 7, 1, 4, 15, 9, 1, 1, 0, 2, 1, 0, 19]\n", | |
| "\n", | |
| "# 10 bits unknown, 30 bits product ID, 1 bit unknown (upgrade?)\n", | |
| "key_data = (342 << 31 | 918500000 << 1 | 0)\n", | |
| "h1_coeffs = [1]\n", | |
| "\n", | |
| "for i in range(len(h1_bases) - 1):\n", | |
| " h1_coeffs.append(key_data % h1_bases[i + 1])\n", | |
| " key_data //= h1_bases[i + 1]\n", | |
| "\n", | |
| "print(h1_coeffs)\n", | |
| "\n", | |
| "# H2(M) = E.lift_x(HASH(M) % p)\n", | |
| "T = E6(E.lift_x(pkey % p))\n", | |
| "Q = sum(map(lambda x: x[0] * x[1], zip(h1_coeffs, Qi))) \n", | |
| "\n", | |
| "test_pairing = T.tate_pairing(Q, order, 6, q=p)\n", | |
| "\n", | |
| "print(test_pairing == pairing_val or test_pairing == 1/pairing_val)\n", | |
| "\n", | |
| "key_data = 0\n", | |
| "\n", | |
| "for i in range(len(h1_bases) - 1, 0, -1):\n", | |
| " key_data *= h1_bases[i]\n", | |
| " key_data += h1_coeffs[i]\n", | |
| " print(h1_bases[i], h1_coeffs[i], key_data)\n", | |
| "\n", | |
| "pid = (key_data & ((1 << 31) - 1)) >> 1" | |
| ] | |
| } | |
| ], | |
| "metadata": { | |
| "kernelspec": { | |
| "display_name": "SageMath 9.0", | |
| "language": "sage", | |
| "name": "sagemath" | |
| }, | |
| "language_info": { | |
| "codemirror_mode": { | |
| "name": "ipython", | |
| "version": 3 | |
| }, | |
| "file_extension": ".py", | |
| "mimetype": "text/x-python", | |
| "name": "python", | |
| "nbconvert_exporter": "python", | |
| "pygments_lexer": "ipython3", | |
| "version": "3.8.10" | |
| } | |
| }, | |
| "nbformat": 4, | |
| "nbformat_minor": 4 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment