~/bend-docscommunity

spec/crypto/aes/poly.bend source

spec/crypto/aes/poly.bend on the hub · documented module

import Base# Polynomials over GF(2), as FIPS 197 section 4 and SP 800-38D section 6.3 use# them. A polynomial is the list of its coefficients, the coefficient of x^0# first; a residue modulo a polynomial m(x) of degree n is a Word(n) of n# coefficients (Base's Word: a Bool vector, index 0 first).# Coefficient-wise sum (XOR); the longer tail is kept.def add(a: List<&2, Bool>, b: List<&2, Bool>) -> List<&2, Bool>:  match a b:    case Nil{} _:      b    case x <> xs Nil{}:      x <> xs    case x <> xs y <> ys:      Bool.xor(x, y) <> add(xs, ys)# c * a for a constant c in GF(2).def scale(+c: Bool, a: List<&2, Bool>) -> List<&2, Bool>:  match a:    case Nil{}:      Nil{}    case x <> xs:      Bool.and(c, x) <> scale(c, xs)# The schoolbook product: (c + x*q(x)) * b(x) = c*b(x) + x*(q(x)*b(x)).def mul(a: List<&2, Bool>, +b: List<&2, Bool>) -> List<&2, Bool>:  match a:    case Nil{}:      Nil{}    case c <> q:      add(scale(c, b), False{} <> mul(q, b))# The coefficient of x^(n-1) of a residue.def top(n: Nat, w: Word(n)) -> Bool:  match n w:    case 0n WNil{}:      False{}    case 1n WCon{b, t}:      b    case 2n+p WCon{b, t}:      top(1n+p, t)def wscale(n: Nat, c: Bool, w: Word(n)) -> Word(n):  match c:    case True{}:      w    case False{}:      Word.zero(n)# The constant polynomial c as a residue.def constant(n: Nat, c: Bool) -> Word(n):  match n:    case 0n:      WNil{}    case 1n+p:      WCon{c, Word.zero(p)}# Multiplication by x modulo m(x) = x^n + low(x) (deg low < n): shift every# coefficient up one degree; the coefficient that reaches x^n is replaced by# low(x), since x^n = low(x) modulo m(x).def times_x(+n: Nat, +low: Word(n), +r: Word(n)) -> Word(n):  Word.xor(n, wscale(n, top(n, r), low), Word.shl(n, r))# p(x) modulo m(x) = x^n + low(x), by Horner's rule:# p(x) = c + x*q(x), so p mod m = c + x*(q mod m) mod m.def reduce(+n: Nat, +low: Word(n), p: List<&2, Bool>) -> Word(n):  match p:    case Nil{}:      Word.zero(n)    case c <> q:      Word.xor(n, constant(n, c), times_x(n, low, reduce(n, low, q)))# The coefficients of a residue, as a polynomial.def coefficients(n: Nat, w: Word(n)) -> List<&2, Bool>:  match n w:    case 0n WNil{}:      Nil{}    case 1n+p WCon{b, t}:      b <> coefficients(p, t)