code wiki / _hdl_build / nx_vault_shamir.nx

nx_vault_shamir.nx source

↩ module page · 60 lines · 2323 B

1// nx_vault_shamir.nx -- sovereign SHAMIR threshold secret sharing (HashiCorp Vault "Shamir seal/unseal" gap 2// from vault_capability_census.tsv) -- the iconic multi-operator unseal: split a master key into N shares; 3// ANY K reconstruct it; K-1 shares reveal a WRONG value (no quorum -> no unseal). Real finite-field math 4// over GF(p), p = 2^31-1 (Mersenne prime): products of two field elements stay < 2^62 so they fit i64 with 5// no overflow. Shares = poly(1..N); reconstruct = Lagrange interpolation at x=0. license_tier: ORIGINAL 6import "nx_syscalls.nx" 7 8const SH_P: i64 = 2147483647 // 2^31 - 1 (Mersenne prime); secrets must be < SH_P 9 10func sh_mod(x: i64) -> i64 { var r: i64 = x % SH_P; if r < 0 { r = r + SH_P } return r } 11func sh_add(a: i64, b: i64) -> i64 { return sh_mod(a + b) } 12func sh_sub(a: i64, b: i64) -> i64 { return sh_mod(a - b) } 13func sh_mul(a: i64, b: i64) -> i64 { return sh_mod(a * b) } // a,b < 2^31 -> a*b < 2^62, fits i64 14 15// modular inverse via extended Euclid (a^{-1} mod p). 16func sh_inv(a: i64) -> i64 { 17 var t: i64 = 0 18 var newt: i64 = 1 19 var r: i64 = SH_P 20 var newr: i64 = sh_mod(a) 21 while newr != 0 { 22 let q: i64 = r / newr 23 let t2: i64 = t - q * newt 24 t = newt; newt = t2 25 let r2: i64 = r - q * newr 26 r = newr; newr = r2 27 } 28 if t < 0 { t = t + SH_P } 29 return t 30} 31 32// evaluate the share polynomial at x (Horner). coeffs[0]=secret, coeffs[1..k-1]=random; degree k-1. 33func sh_eval(coeffs: *i64, k: i64, x: i64) -> i64 { 34 var acc: i64 = 0 35 var i: i64 = k - 1 36 while i >= 0 { acc = sh_add(sh_mul(acc, x), coeffs[i]); i = i - 1 } 37 return acc 38} 39 40// reconstruct the secret = poly(0) from k shares (xs[],ys[]) via Lagrange interpolation at x=0. 41func sh_reconstruct(xs: *i64, ys: *i64, k: i64) -> i64 { 42 var secret: i64 = 0 43 var j: i64 = 0 44 while j < k { 45 var num: i64 = 1 46 var den: i64 = 1 47 var m: i64 = 0 48 while m < k { 49 if m != j { 50 num = sh_mul(num, sh_sub(0, xs[m])) // (0 - x_m) 51 den = sh_mul(den, sh_sub(xs[j], xs[m])) // (x_j - x_m) 52 } 53 m = m + 1 54 } 55 let basis: i64 = sh_mul(num, sh_inv(den)) 56 secret = sh_add(secret, sh_mul(ys[j], basis)) 57 j = j + 1 58 } 59 return secret 60}