summaryrefslogtreecommitdiff
path: root/appl/cmd/auth/signer.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/cmd/auth/signer.b')
-rw-r--r--appl/cmd/auth/signer.b132
1 files changed, 132 insertions, 0 deletions
diff --git a/appl/cmd/auth/signer.b b/appl/cmd/auth/signer.b
new file mode 100644
index 00000000..b3f4669d
--- /dev/null
+++ b/appl/cmd/auth/signer.b
@@ -0,0 +1,132 @@
+implement Signer;
+
+include "sys.m";
+ sys: Sys;
+
+include "draw.m";
+
+include "keyring.m";
+ kr: Keyring;
+ IPint: import kr;
+
+include "security.m";
+ random: Random;
+
+Signer: module
+{
+ init: fn(ctxt: ref Draw->Context, argv: list of string);
+};
+
+# size in bits of modulus for public keys
+PKmodlen: con 512;
+
+# size in bits of modulus for diffie hellman
+DHmodlen: con 512;
+
+stderr, stdin, stdout: ref Sys->FD;
+
+init(nil: ref Draw->Context, nil: list of string)
+{
+ sys = load Sys Sys->PATH;
+ random = load Random Random->PATH;
+ kr = load Keyring Keyring->PATH;
+
+ stdin = sys->fildes(0);
+ stdout = sys->fildes(1);
+ stderr = sys->fildes(2);
+
+ sys->pctl(Sys->FORKNS, nil);
+ if(sys->chdir("/keydb") < 0){
+ sys->fprint(stderr, "signer: no key database\n");
+ raise "fail:no keydb";
+ }
+
+ err := sign();
+ if(err != nil){
+ sys->fprint(stderr, "signer: %s\n", err);
+ raise "fail:error";
+ }
+}
+
+sign(): string
+{
+ info := signerkey("signerkey");
+ if(info == nil)
+ return "can't read key";
+
+ # send public part to client
+ mypkbuf := array of byte kr->pktostr(kr->sktopk(info.mysk));
+ kr->sendmsg(stdout, mypkbuf, len mypkbuf);
+ alphabuf := array of byte info.alpha.iptob64();
+ kr->sendmsg(stdout, alphabuf, len alphabuf);
+ pbuf := array of byte info.p.iptob64();
+ kr->sendmsg(stdout, pbuf, len pbuf);
+
+ # get client's public key
+ hisPKbuf := kr->getmsg(stdin);
+ if(hisPKbuf == nil)
+ return "caller hung up";
+ hisPK := kr->strtopk(string hisPKbuf);
+ if(hisPK == nil)
+ return "illegal caller PK";
+
+ # hash, sign, and blind
+ state := kr->sha1(hisPKbuf, len hisPKbuf, nil, nil);
+ cert := kr->sign(info.mysk, 0, state, "sha1");
+
+ # sanity clause
+ state = kr->sha1(hisPKbuf, len hisPKbuf, nil, nil);
+ if(kr->verify(info.mypk, cert, state) == 0)
+ return "bad signer certificate";
+
+ certbuf := array of byte kr->certtostr(cert);
+ blind := random->randombuf(random->ReallyRandom, len certbuf);
+ for(i := 0; i < len blind; i++)
+ certbuf[i] = certbuf[i] ^ blind[i];
+
+ # sum PKs and blinded certificate
+ state = kr->md5(mypkbuf, len mypkbuf, nil, nil);
+ kr->md5(hisPKbuf, len hisPKbuf, nil, state);
+ digest := array[Keyring->MD5dlen] of byte;
+ kr->md5(certbuf, len certbuf, digest, state);
+
+ # save sum and blinded cert in a file
+ file := "signed/"+hisPK.owner;
+ fd := sys->create(file, Sys->OWRITE, 8r600);
+ if(fd == nil)
+ return "can't create "+file+sys->sprint(": %r");
+ if(kr->sendmsg(fd, blind, len blind) < 0 ||
+ kr->sendmsg(fd, digest, len digest) < 0){
+ sys->remove(file);
+ return "can't write "+file+sys->sprint(": %r");
+ }
+
+ # send blinded cert to client
+ kr->sendmsg(stdout, certbuf, len certbuf);
+
+ return nil;
+}
+
+signerkey(filename: string): ref Keyring->Authinfo
+{
+ info := kr->readauthinfo(filename);
+ if(info != nil)
+ return info;
+
+ # generate a local key
+ info = ref Keyring->Authinfo;
+ info.mysk = kr->genSK("elgamal", "*", PKmodlen);
+ info.mypk = kr->sktopk(info.mysk);
+ info.spk = kr->sktopk(info.mysk);
+ myPKbuf := array of byte kr->pktostr(info.mypk);
+ state := kr->sha1(myPKbuf, len myPKbuf, nil, nil);
+ info.cert = kr->sign(info.mysk, 0, state, "sha1");
+ (info.alpha, info.p) = kr->dhparams(DHmodlen);
+
+ if(kr->writeauthinfo(filename, info) < 0){
+ sys->fprint(stderr, "can't write signerkey file: %r\n");
+ return nil;
+ }
+
+ return info;
+}