Last active
July 10, 2026 18:04
-
-
Save jedisct1/7c5d492f8b5323712ab5adf0be6c6696 to your computer and use it in GitHub Desktop.
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
| # RS256 (RSA-SHA256, PKCS#1 v1.5) JWT signer in pure xvcl. | |
| # | |
| # The 2048-bit RSA key is hardcoded; the payload is signed at VCL RUNTIME. | |
| # Fastly VCL has no loops and no big integers, so xvcl unrolls a 1024-bit | |
| # Montgomery modular multiply (subroutine `mm`) and drives it with a fixed | |
| # square-and-multiply call sequence derived from the CRT exponents dp, dq. | |
| # Bignums are little-endian, stored as 10-digit decimal fields packed in one | |
| # header (limb i = substr(buf, 10*i, 10)); radix is 2^31, 34 limbs per prime. | |
| #const KC = 34 | |
| #const W = 31 | |
| #const MASK = 2147483647 | |
| #const FW = 10 | |
| #const P = 146940757555455584418374027822873203142565789710512619045156457640662925045088053709103347848419427162426921942975985473781757837029163145484077630514618829047184792111261700717338304682388932551821457994258731734097938799732652362736347872127999604450371008549967089201948910503944524733484401689040260486639 | |
| #const Q = 141770948727367031483039085955552651424361338049959442434001649684293351969295044009721187332495226292552568637644569830980040621217052145126495878743748962493279511556021202415730806307854671331995394379508908560299609088390016852410028858859430364096044673000441077772913472358214722037176236194039239572441 | |
| #const DP = 87776122152959865028837524073998856063419260896544829989148575006092937616768424167381585439030961960142386242055126955965058479360585745190596993408560241365461303177804664866916051848739556593546519660912691894017123244438006124002705080274334444888041482120369586266797349547872563571588275962040330771799 | |
| #const DQ = 69631888377332153995568078151628611268424967735632459412363689239478747982660759138027607291235314999633407569420953938834803661387547362550571064297763635102250243335471054283228694084922013755673890316645746031211134427059313860296113934690727436255665989886799790231965328924707778623596836395470178412153 | |
| #const QINV = 88376931446830195567607250260008915644980370263293821248747910177919294282505901963504996595391302633966982471805538102838941058646258299903767688454113406838568289543590639667945298377587186904806850845651157526048587066769617866700387908372585220894286897791674408684282145102411826625522566341152899496276 | |
| #const NPP = 1838221041 | |
| #const NPQ = 127249303 | |
| #const PREFIX = 8517306873408580822992635312440950711239255839406135638915695785157155190387115319509921306392695908259568017376177003703892468439867471313010266082044366152587365883633222577111472049055629505468998539970395284077667422034489754083521773830038551567748404355586664429892872238799740447530419140178373250649717644114389439609482724683280601140209723930557484934686269386505204448139030367437035720725484614708959520972713569161083070860431372724706744245785484250797231413335964222081666399605681989457294305123939770973418464768689184 | |
| #const HB = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9" | |
| #const RP = 1 << (W * KC) | |
| #const CP = (PREFIX << 256) % P | |
| #const CQ = (PREFIX << 256) % Q | |
| #const CPL = [(CP >> (W*i)) & MASK for i in range(KC)] | |
| #const CQL = [(CQ >> (W*i)) & MASK for i in range(KC)] | |
| #const PL = [(P >> (W*i)) & MASK for i in range(KC)] | |
| #const QL = [(Q >> (W*i)) & MASK for i in range(KC)] | |
| #const QINVR = (QINV * RP) % P | |
| #const DPB = format(DP, 'b') | |
| #const DQB = format(DQ, 'b') | |
| #const PL_S = "".join([str(v).zfill(FW) for v in [(P >> (W*i)) & MASK for i in range(KC)]]) | |
| #const QL_S = "".join([str(v).zfill(FW) for v in [(Q >> (W*i)) & MASK for i in range(KC)]]) | |
| #const QINVR_S = "".join([str(v).zfill(FW) for v in [(QINVR >> (W*i)) & MASK for i in range(KC)]]) | |
| #const R2P_S = "".join([str(v).zfill(FW) for v in [(((RP*RP) % P) >> (W*i)) & MASK for i in range(KC)]]) | |
| #const R2Q_S = "".join([str(v).zfill(FW) for v in [(((RP*RP) % Q) >> (W*i)) & MASK for i in range(KC)]]) | |
| #const ONEP_S = "".join([str(v).zfill(FW) for v in [((RP % P) >> (W*i)) & MASK for i in range(KC)]]) | |
| #const ONEQ_S = "".join([str(v).zfill(FW) for v in [((RP % Q) >> (W*i)) & MASK for i in range(KC)]]) | |
| #const ONE_S = "".join([str(v).zfill(FW) for v in [(1 >> (W*i)) & MASK for i in range(KC)]]) | |
| sub ciosrow { | |
| declare local var.x INTEGER; | |
| declare local var.c INTEGER; | |
| declare local var.m INTEGER; | |
| declare local var.bi INTEGER; | |
| declare local var.np INTEGER; | |
| #for i in range(KC) | |
| declare local var.a{{i}} INTEGER; | |
| declare local var.n{{i}} INTEGER; | |
| #endfor | |
| #for i in range(KC + 2) | |
| declare local var.t{{i}} INTEGER; | |
| #endfor | |
| #for i in range(KC) | |
| set var.a{{i}} = std.atoi(substr(req.http.A, {{i*FW}}, {{FW}})); | |
| set var.n{{i}} = std.atoi(substr(req.http.MOD, {{i*FW}}, {{FW}})); | |
| #endfor | |
| #for i in range(KC + 2) | |
| set var.t{{i}} = std.atoi(substr(req.http.T, {{i*FW}}, {{FW}})); | |
| #endfor | |
| set var.bi = std.atoi(req.http.BI); | |
| set var.np = std.atoi(req.http.NP); | |
| set var.c = 0; | |
| #for j in range(KC) | |
| set var.x = var.a{{j}}; | |
| set var.x *= var.bi; | |
| set var.x += var.t{{j}}; | |
| set var.x += var.c; | |
| set var.c = var.x; | |
| set var.c >>= 31; | |
| set var.x &= {{MASK}}; | |
| set var.t{{j}} = var.x; | |
| #endfor | |
| set var.x = var.t{{KC}}; | |
| set var.x += var.c; | |
| set var.c = var.x; | |
| set var.c >>= 31; | |
| set var.x &= {{MASK}}; | |
| set var.t{{KC}} = var.x; | |
| set var.t{{KC+1}} = var.c; | |
| set var.m = var.t0; | |
| set var.m *= var.np; | |
| set var.m &= {{MASK}}; | |
| set var.x = var.t0; | |
| set var.c = var.m; | |
| set var.c *= var.n0; | |
| set var.x += var.c; | |
| set var.c = var.x; | |
| set var.c >>= 31; | |
| #for j in range(1, KC) | |
| set var.x = var.t{{j}}; | |
| set var.bi = var.m; | |
| set var.bi *= var.n{{j}}; | |
| set var.x += var.bi; | |
| set var.x += var.c; | |
| set var.c = var.x; | |
| set var.c >>= 31; | |
| set var.x &= {{MASK}}; | |
| set var.t{{j-1}} = var.x; | |
| #endfor | |
| set var.x = var.t{{KC}}; | |
| set var.x += var.c; | |
| set var.c = var.x; | |
| set var.c >>= 31; | |
| set var.x &= {{MASK}}; | |
| set var.t{{KC-1}} = var.x; | |
| set var.x = var.t{{KC+1}}; | |
| set var.x += var.c; | |
| set var.t{{KC}} = var.x; | |
| set var.t{{KC+1}} = 0; | |
| set req.http.T = ""; | |
| #for i in range(KC + 2) | |
| set req.http.T = req.http.T + std.strpad(std.itoa(var.t{{i}}), {{FW}}, "0"); | |
| #endfor | |
| } | |
| sub mm { | |
| set req.http.T = "{{"0" * (FW * (KC + 2))}}"; | |
| #for i in range(KC) | |
| set req.http.BI = substr(req.http.O, {{i*FW}}, {{FW}}); | |
| call ciosrow; | |
| #endfor | |
| set req.http.A = substr(req.http.T, 0, {{KC*FW}}); | |
| } | |
| sub sq { set req.http.O = req.http.A; call mm; } | |
| sub mul { set req.http.O = req.http.BP; call mm; } | |
| sub red { | |
| declare local var.x INTEGER; | |
| declare local var.brw INTEGER; | |
| #for i in range(KC) | |
| declare local var.t{{i}} INTEGER; | |
| declare local var.n{{i}} INTEGER; | |
| declare local var.s{{i}} INTEGER; | |
| #endfor | |
| #for i in range(KC) | |
| set var.t{{i}} = std.atoi(substr(req.http.A, {{i*FW}}, {{FW}})); | |
| set var.n{{i}} = std.atoi(substr(req.http.MOD, {{i*FW}}, {{FW}})); | |
| #endfor | |
| set var.brw = 0; | |
| #for i in range(KC) | |
| set var.x = var.t{{i}}; | |
| set var.x -= var.n{{i}}; | |
| set var.x -= var.brw; | |
| set var.brw = var.x; | |
| set var.brw >>= 31; | |
| set var.brw &= 1; | |
| set var.x &= {{MASK}}; | |
| set var.s{{i}} = var.x; | |
| #endfor | |
| if (var.brw == 0) { | |
| #for i in range(KC) | |
| set var.t{{i}} = var.s{{i}}; | |
| #endfor | |
| } | |
| set req.http.A = ""; | |
| #for i in range(KC) | |
| set req.http.A = req.http.A + std.strpad(std.itoa(var.t{{i}}), {{FW}}, "0"); | |
| #endfor | |
| } | |
| sub macrow { | |
| declare local var.x INTEGER; | |
| declare local var.c INTEGER; | |
| declare local var.qi INTEGER; | |
| #for j in range(KC) | |
| declare local var.h{{j}} INTEGER; | |
| #endfor | |
| #for i in range(2 * KC + 1) | |
| declare local var.p{{i}} INTEGER; | |
| #endfor | |
| #for j in range(KC) | |
| set var.h{{j}} = std.atoi(substr(req.http.H, {{j*FW}}, {{FW}})); | |
| #endfor | |
| #for i in range(2 * KC + 1) | |
| set var.p{{i}} = std.atoi(substr(req.http.P, {{i*FW}}, {{FW}})); | |
| #endfor | |
| set var.qi = std.atoi(req.http.QI); | |
| set var.c = 0; | |
| #for j in range(KC) | |
| set var.x = var.h{{j}}; | |
| set var.x *= var.qi; | |
| set var.x += var.p{{j}}; | |
| set var.x += var.c; | |
| set var.c = var.x; | |
| set var.c >>= 31; | |
| set var.x &= {{MASK}}; | |
| set var.p{{j}} = var.x; | |
| #endfor | |
| #for j in range(KC, 2 * KC + 1) | |
| set var.x = var.p{{j}}; | |
| set var.x += var.c; | |
| set var.c = var.x; | |
| set var.c >>= 31; | |
| set var.x &= {{MASK}}; | |
| set var.p{{j}} = var.x; | |
| #endfor | |
| set req.http.P = ""; | |
| #for i in range(2 * KC + 1) | |
| set req.http.P = req.http.P + std.strpad(std.itoa(var.p{{i}}), {{FW}}, "0"); | |
| #endfor | |
| } | |
| sub qhmul { | |
| set req.http.P = "{{"0" * (FW * (2 * KC + 1))}}"; | |
| #for i in range(KC) | |
| set req.http.P = "{{"0" * FW}}" + substr(req.http.P, 0, {{2 * KC * FW}}); | |
| set req.http.QI = "{{QL[KC - 1 - i]}}"; | |
| call macrow; | |
| #endfor | |
| } | |
| sub do_sign { | |
| declare local var.x INTEGER; | |
| declare local var.c INTEGER; | |
| declare local var.borrow INTEGER; | |
| declare local var.w INTEGER; | |
| declare local var.tmp INTEGER; | |
| #for i in range(16) | |
| declare local var.hw{{i}} INTEGER; | |
| #endfor | |
| #for i in range(KC) | |
| declare local var.h{{i}} INTEGER; | |
| #endfor | |
| #for i in range(69) | |
| declare local var.p{{i}} INTEGER; | |
| #endfor | |
| #for i in range(KC) | |
| declare local var.sq{{i}} INTEGER; | |
| #endfor | |
| #for i in range(128) | |
| declare local var.o{{i}} INTEGER; | |
| #endfor | |
| set req.http.SI = "{{HB}}." + digest.base64url_nopad(req.http.X-Payload); | |
| set req.http.HASH = digest.hash_sha256(req.http.SI); | |
| #for wi in range(16) | |
| set var.hw{{wi}} = std.strtol(substr(req.http.HASH, {{4*(15-wi)}}, 4), 16); | |
| #endfor | |
| #for j in range(KC) | |
| #if (W*j)//16 < 16 | |
| set var.w = var.hw{{(W*j)//16}}; | |
| #if (W*j)//16 + 1 < 16 | |
| set var.tmp = var.hw{{(W*j)//16 + 1}}; | |
| set var.tmp <<= 16; | |
| set var.w += var.tmp; | |
| #endif | |
| #if (W*j)//16 + 2 < 16 | |
| set var.tmp = var.hw{{(W*j)//16 + 2}}; | |
| set var.tmp <<= 32; | |
| set var.w += var.tmp; | |
| #endif | |
| #if (W*j) % 16 != 0 | |
| set var.w >>= {{(W*j) % 16}}; | |
| #endif | |
| set var.w &= {{MASK}}; | |
| set var.h{{j}} = var.w; | |
| #else | |
| set var.h{{j}} = 0; | |
| #endif | |
| #endfor | |
| set var.c = 0; | |
| #for i in range(KC) | |
| set var.x = {{CPL[i]}}; | |
| set var.x += var.h{{i}}; | |
| set var.x += var.c; | |
| set var.c = var.x; | |
| set var.c >>= 31; | |
| set var.x &= {{MASK}}; | |
| set var.p{{i}} = var.x; | |
| #endfor | |
| set req.http.A = ""; | |
| #for i in range(KC) | |
| set req.http.A = req.http.A + std.strpad(std.itoa(var.p{{i}}), {{FW}}, "0"); | |
| #endfor | |
| set req.http.MOD = "{{PL_S}}"; | |
| call red; | |
| set req.http.MP = req.http.A; | |
| set var.c = 0; | |
| #for i in range(KC) | |
| set var.x = {{CQL[i]}}; | |
| set var.x += var.h{{i}}; | |
| set var.x += var.c; | |
| set var.c = var.x; | |
| set var.c >>= 31; | |
| set var.x &= {{MASK}}; | |
| set var.p{{i}} = var.x; | |
| #endfor | |
| set req.http.A = ""; | |
| #for i in range(KC) | |
| set req.http.A = req.http.A + std.strpad(std.itoa(var.p{{i}}), {{FW}}, "0"); | |
| #endfor | |
| set req.http.MOD = "{{QL_S}}"; | |
| call red; | |
| set req.http.MQ = req.http.A; | |
| set req.http.MOD = "{{PL_S}}"; | |
| set req.http.NP = "{{NPP}}"; | |
| set req.http.A = req.http.MP; | |
| set req.http.O = "{{R2P_S}}"; | |
| call mm; | |
| set req.http.BP = req.http.A; | |
| set req.http.A = "{{ONEP_S}}"; | |
| #for b in DPB | |
| call sq; | |
| #if b == "1" | |
| call mul; | |
| #endif | |
| #endfor | |
| set req.http.O = "{{ONE_S}}"; | |
| call mm; | |
| call red; | |
| set req.http.SP = req.http.A; | |
| set req.http.MOD = "{{QL_S}}"; | |
| set req.http.NP = "{{NPQ}}"; | |
| set req.http.A = req.http.MQ; | |
| set req.http.O = "{{R2Q_S}}"; | |
| call mm; | |
| set req.http.BP = req.http.A; | |
| set req.http.A = "{{ONEQ_S}}"; | |
| #for b in DQB | |
| call sq; | |
| #if b == "1" | |
| call mul; | |
| #endif | |
| #endfor | |
| set req.http.O = "{{ONE_S}}"; | |
| call mm; | |
| call red; | |
| set req.http.SQ = req.http.A; | |
| set var.borrow = 0; | |
| #for i in range(KC) | |
| set var.x = std.atoi(substr(req.http.SP, {{i*FW}}, {{FW}})); | |
| set var.tmp = std.atoi(substr(req.http.SQ, {{i*FW}}, {{FW}})); | |
| set var.x -= var.tmp; | |
| set var.x -= var.borrow; | |
| set var.borrow = var.x; | |
| set var.borrow >>= 31; | |
| set var.borrow &= 1; | |
| set var.x &= {{MASK}}; | |
| set var.p{{i}} = var.x; | |
| set var.sq{{i}} = std.atoi(substr(req.http.SQ, {{i*FW}}, {{FW}})); | |
| #endfor | |
| if (var.borrow == 1) { | |
| set var.c = 0; | |
| #for i in range(KC) | |
| set var.x = var.p{{i}}; | |
| set var.x += {{PL[i]}}; | |
| set var.x += var.c; | |
| set var.c = var.x; | |
| set var.c >>= 31; | |
| set var.x &= {{MASK}}; | |
| set var.p{{i}} = var.x; | |
| #endfor | |
| } | |
| set req.http.A = ""; | |
| #for i in range(KC) | |
| set req.http.A = req.http.A + std.strpad(std.itoa(var.p{{i}}), {{FW}}, "0"); | |
| #endfor | |
| set req.http.MOD = "{{PL_S}}"; | |
| set req.http.NP = "{{NPP}}"; | |
| set req.http.O = "{{QINVR_S}}"; | |
| call mm; | |
| call red; | |
| set req.http.H = req.http.A; | |
| call qhmul; | |
| #for i in range(2 * KC + 1) | |
| set var.p{{i}} = std.atoi(substr(req.http.P, {{i*FW}}, {{FW}})); | |
| #endfor | |
| set var.c = 0; | |
| #for i in range(67) | |
| set var.x = var.p{{i}}; | |
| #if i < KC | |
| set var.x += var.sq{{i}}; | |
| #endif | |
| set var.x += var.c; | |
| set var.c = var.x; | |
| set var.c >>= 31; | |
| set var.x &= {{MASK}}; | |
| set var.p{{i}} = var.x; | |
| #endfor | |
| #for i in range(128) | |
| set var.w = var.p{{(16*i)//31}}; | |
| #if (16*i)//31 + 1 < 67 | |
| set var.tmp = var.p{{(16*i)//31 + 1}}; | |
| set var.tmp <<= 31; | |
| set var.w += var.tmp; | |
| #endif | |
| #if (16*i) % 31 != 0 | |
| set var.w >>= {{(16*i) % 31}}; | |
| #endif | |
| set var.w &= 65535; | |
| set var.o{{i}} = var.w; | |
| #endfor | |
| set req.http.HEX = ""; | |
| #for i in range(128) | |
| set req.http.HEX = req.http.HEX + std.strpad(std.itoa(var.o{{127-i}}, 16), 4, "0"); | |
| #endfor | |
| set req.http.B64 = bin.hex_to_base64(req.http.HEX); | |
| set req.http.B64 = regsuball(req.http.B64, "[+]", "-"); | |
| set req.http.B64 = regsuball(req.http.B64, "[/]", "_"); | |
| set req.http.B64 = regsuball(req.http.B64, "=", ""); | |
| set req.http.X-Jwt = req.http.SI + "." + req.http.B64; | |
| } | |
| sub vcl_recv { | |
| #FASTLY RECV | |
| call do_sign; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment