Rawsexprs: module { PATH: con "rawsexprs.dis"; Sexp: adt { pick { String => s: string; hint: string; Binary => data: array of byte; hint: string; List => l: cyclic list of ref Sexp; } unpack: fn(a: array of byte): (ref Sexp, array of byte, string); text: fn(e: self ref Sexp): string; packedsize: fn(e: self ref Sexp): int; pack: fn(e: self ref Sexp): array of byte; }; init: fn(); }; SPKI: module { PATH: con "/dis/lib/spki/spki.dis"; Hash: adt { alg: string; hash: array of byte; sexp: fn(h: self ref Hash): ref Sexprs->Sexp; text: fn(h: self ref Hash): string; eq: fn(h1: self ref Hash, h2: ref Hash): int; }; Key: adt { pk: ref Keyring->PK; # either pk/sk or hash might be nil sk: ref Keyring->SK; nbits: int; halg: string; # basic signature hash algorithm henc: string; # pre-signature encoding hash: list of ref Hash; hashed: fn(k: self ref Key, alg: string): array of byte; hashexp: fn(k: self ref Key, alg: string): ref Hash; ishash: fn(k: self ref Key): int; public: fn(k: self ref Key): ref Key; sigalg: fn(k: self ref Key): string; text: fn(k: self ref Key): string; sexp: fn(k: self ref Key): ref Sexprs->Sexp; eq: fn(k1: self ref Key, k2: ref Key): int; }; Name: adt { principal: ref Key; names: list of string; isprincipal: fn(n: self ref Name): int; local: fn(n: self ref Name): ref Name; islocal: fn(n: self ref Name): int; isprefix: fn(n1: self ref Name, n2: ref Name): int; text: fn(n: self ref Name): string; sexp: fn(n: self ref Name): ref Sexprs->Sexp; eq: fn(n1: self ref Name, n2: ref Name): int; }; Cert: adt { e: ref Sexprs->Sexp; # S-expression, if originally parsed issuer: ref Name; subject: ref Subject; valid: ref Valid; pick { A or KH or O => # auth, keyholder or object delegate: int; tag: ref Sexprs->Sexp; N => # name } text: fn(c: self ref Cert): string; sexp: fn(c: self ref Cert): ref Sexprs->Sexp; }; # the pick might move to a more general `Principal' structure, # allowing compound and quoting principals Subject: adt { pick{ P => key: ref Key; N => name: ref Name; O => hash: ref Hash; KH => holder: ref Name; T => k, n: int; subs: cyclic list of ref Subject; } eq: fn(s1: self ref Subject, s2: ref Subject): int; principal: fn(s: self ref Subject): ref Key; text: fn(s: self ref Subject): string; sexp: fn(s: self ref Subject): ref Sexprs->Sexp; }; Principal: adt[T] { pick{ N => name: ref Name; Q => quoter: T; quotes: cyclic ref Principal; } }; Signature: adt { hash: ref Hash; key: ref Key; # find by hash if necessary sa: string; # alg[-[encoding-]hash] sig: list of (string, array of byte); algs: fn(s: self ref Signature): (string, string, string); sexp: fn(s: self ref Signature): ref Sexprs->Sexp; text: fn(s: self ref Signature): string; }; Seqel: adt { pick{ C => c: ref Cert; K => k: ref Key; O => op: string; args: list of ref Sexprs->Sexp; S => sig: ref Signature; RV => # ok: list of (string, string); onetime: array of byte; valid: ref Valid; CRL => bad: list of (string, string); valid: ref Valid; Delta => hash: string; bad: list of (string, string); valid: ref Valid; E => exp: ref Sexprs->Sexp; } sexp: fn(se: self ref Seqel): ref Sexprs->Sexp; text: fn(se: self ref Seqel): string; }; Valid: adt { notbefore: string; notafter: string; intersect: fn(a: self Valid, b: Valid): (int, Valid); text: fn(a: self Valid): string; sexp: fn(a: self Valid): ref Sexprs->Sexp; }; Toplev: adt { pick { C => v: ref Cert; Sig => v: ref Signature; K => v: ref Key; Seq => v: list of ref Seqel; } sexp: fn(t: self ref Toplev): ref Sexprs->Sexp; text: fn(t: self ref Toplev): string; }; init: fn(); # parse structures parse: fn(s: ref Sexprs->Sexp): (ref Toplev, string); parseseq: fn(s: ref Sexprs->Sexp): list of ref Seqel; parsecert: fn(s: ref Sexprs->Sexp): ref Cert; parsesig: fn(s: ref Sexprs->Sexp): ref Signature; parsename: fn(s: ref Sexprs->Sexp): ref Name; parsekey: fn(s: ref Sexprs->Sexp): ref Key; parsehash: fn(s: ref Sexprs->Sexp): ref Hash; parsecompound: fn(s: ref Sexprs->Sexp): ref Name; parsevalid: fn(s: ref Sexprs->Sexp): ref Valid; # signature checking checksig: fn(c: ref Cert, sig: ref Signature): string; sig2icert: fn(sig: ref Signature, signer: string, exp: int): ref Keyring->Certificate; # signature making signcert: fn(c: ref Cert, sigalg: string, key: ref Key): (ref Signature, string); signbytes: fn(a: array of byte, sigalg: string, key: ref Key): (ref Signature, string); # tags maketag: fn(e: ref Sexprs->Sexp): ref Sexprs->Sexp; tagintersect: fn(t1: ref Sexprs->Sexp, t2: ref Sexprs->Sexp): ref Sexprs->Sexp; tagimplies: fn(t1: ref Sexprs->Sexp, t2: ref Sexprs->Sexp): int; # hash canonical s-expression hashbytes: fn(a: array of byte, alg: string): array of byte; hashexp: fn(e: ref Sexprs->Sexp, alg: string): array of byte; # convert between date and time strings and Inferno form date2epoch: fn(s: string): int; # YYYY-MM-DD_HH:MM:SS epoch2date: fn(t: int): string; time2secs: fn(s: string): int; # HH:MM:SS secs2time: fn(t: int): string; # misc sigalgs: fn(algs: string): (string, string, string); # debugging dump: fn(s: string, a: array of byte); }; Proofs: module { Proof: adt { n: int; parse: fn(s: string): ref Proof; sexp: fn(p: self ref Proof): ref Sexprs->Sexp; text: fn(p: self ref Proof): string; }; init: fn(): string; }; Verifier: module { PATH: con "/dis/lib/spki/verifier.dis"; Speaksfor: adt { subject: ref SPKI->Subject; name: ref SPKI->Name; regarding: ref Sexprs->Sexp; valid: ref SPKI->Valid; }; init: fn(); verify: fn(seq: list of ref SPKI->Seqel): (ref Speaksfor, list of ref SPKI->Seqel, string); };