WaveVerifier: module
{
PATH: con "/dis/waveverifier.dis";
Wave: adt {
payload: array of byte;
score: string;
sig: array of byte;
pubkey: string;
hash: fn(w: self ref Wave): string;
verify: fn(w: self ref Wave): int;
};
init: fn(ctxt: ref Draw->Context, argv: list of string);
};
implement WaveVerifier;
include "sys.m";
sys: Sys;
include "draw.m";
include "keyring.m";
kr: Keyring;
include "styx.m";
styx: Styx;
include "styxservers.m";
styxservers: Styxservers;
Styxserver, Navigator, Navop: import styxservers;
include "waveverifier.m";
Qroot, Qpayload, Qsig, Qstatus: con iota;
dirtab := array of {
(Qroot, ".", Sys->QTDIR, 8r555),
(Qpayload, "payload", Sys->QTFILE, 8r666),
(Qsig, "signature", Sys->QTFILE, 8r666),
(Qstatus, "status", Sys->QTFILE, 8r444),
};
init(nil: ref Draw->Context, args: list of string)
{
sys = load Sys Sys->PATH;
kr = load Keyring Keyring->PATH;
styx = load Styx Styx->PATH;
styxservers = load Styxservers Styxservers->PATH;
styxservers->init(styx);
nav := Navigator.new(styxservers->dirgen(dirtab));
(msgchan, srv) := Styxserver.new(sys->fildes(0), nav, Qroot);
wave := ref Wave(nil, "", nil, "forge-auth-key-public");
spawn servloop(srv, msgchan, wave);
}
servloop(srv: ref Styxserver, msgchan: chan of ref Styx->Tmsg, wave: ref Wave)
{
for(;;) {
msg := <-msgchan;
if(msg == nil) break;
pick m := msg {
Read =>
case srv.getfid(m.fid).path {
Qstatus =>
status_str := "Unverified";
if(wave.payload != nil && wave.sig != nil) {
wave.score = wave.hash();
is_valid := wave.verify();
if(is_valid)
status_str = "Verified_Score: " + wave.score;
else
status_str = "ERR: Failed Signature";
}
srv.reply(styxservers->readstr(m, status_str));
* => srv.default(m);
}
Write =>
case srv.getfid(m.fid).path {
Qpayload =>
wave.payload = m.data;
srv.reply(ref Styx->Rmsg.Write(m.tag, len m.data));
Qsig =>
wave.sig = m.data;
srv.reply(ref Styx->Rmsg.Write(m.tag, len m.data));
* => srv.default(m);
}
* => srv.default(msg);
}
}
}
Wave.hash(w: self ref Wave): string
{
digest := kr->sha1(w.payload, len w.payload, nil, nil);
hex := "";
for(i := 0; i < len digest; i++)
hex += sys->sprint("%02x", int digest[i]);
return hex;
}
Wave.verify(w: self ref Wave): int
{
pk := kr->strtopk(w.pubkey);
if(pk == nil) return 0;
sig := kr->strtosig(string w.sig);
if(sig == nil) return 0;
state := kr->verify(pk, sig, w.payload, len w.payload);
if(state == "valid") return 1;
return 0;
}