1implement Signer; 2 3include "sys.m"; 4 sys: Sys; 5 6include "draw.m"; 7 8include "keyring.m"; 9 kr: Keyring; 10 IPint: import kr; 11 12include "security.m"; 13 random: Random; 14 15Signer: module 16{ 17 init: fn(ctxt: ref Draw->Context, argv: list of string); 18}; 19 20# size in bits of modulus for public keys 21PKmodlen: con 512; 22 23# size in bits of modulus for diffie hellman 24DHmodlen: con 512; 25 26stderr, stdin, stdout: ref Sys->FD; 27 28init(nil: ref Draw->Context, nil: list of string) 29{ 30 sys = load Sys Sys->PATH; 31 random = load Random Random->PATH; 32 kr = load Keyring Keyring->PATH; 33 34 stdin = sys->fildes(0); 35 stdout = sys->fildes(1); 36 stderr = sys->fildes(2); 37 38 sys->pctl(Sys->FORKNS, nil); 39 if(sys->chdir("/keydb") < 0){ 40 sys->fprint(stderr, "signer: no key database\n"); 41 raise "fail:no keydb"; 42 } 43 44 err := sign(); 45 if(err != nil){ 46 sys->fprint(stderr, "signer: %s\n", err); 47 raise "fail:error"; 48 } 49} 50 51sign(): string 52{ 53 info := signerkey("signerkey"); 54 if(info == nil) 55 return "can't read key"; 56 57 # send public part to client 58 mypkbuf := array of byte kr->pktostr(kr->sktopk(info.mysk)); 59 kr->sendmsg(stdout, mypkbuf, len mypkbuf); 60 alphabuf := array of byte info.alpha.iptob64(); 61 kr->sendmsg(stdout, alphabuf, len alphabuf); 62 pbuf := array of byte info.p.iptob64(); 63 kr->sendmsg(stdout, pbuf, len pbuf); 64 65 # get client's public key 66 hisPKbuf := kr->getmsg(stdin); 67 if(hisPKbuf == nil) 68 return "caller hung up"; 69 hisPK := kr->strtopk(string hisPKbuf); 70 if(hisPK == nil) 71 return "illegal caller PK"; 72 73 # hash, sign, and blind 74 state := kr->sha1(hisPKbuf, len hisPKbuf, nil, nil); 75 cert := kr->sign(info.mysk, 0, state, "sha1"); 76 77 # sanity clause 78 state = kr->sha1(hisPKbuf, len hisPKbuf, nil, nil); 79 if(kr->verify(info.mypk, cert, state) == 0) 80 return "bad signer certificate"; 81 82 certbuf := array of byte kr->certtostr(cert); 83 blind := random->randombuf(random->ReallyRandom, len certbuf); 84 for(i := 0; i < len blind; i++) 85 certbuf[i] = certbuf[i] ^ blind[i]; 86 87 # sum PKs and blinded certificate 88 state = kr->md5(mypkbuf, len mypkbuf, nil, nil); 89 kr->md5(hisPKbuf, len hisPKbuf, nil, state); 90 digest := array[Keyring->MD5dlen] of byte; 91 kr->md5(certbuf, len certbuf, digest, state); 92 93 # save sum and blinded cert in a file 94 file := "signed/"+hisPK.owner; 95 fd := sys->create(file, Sys->OWRITE, 8r600); 96 if(fd == nil) 97 return "can't create "+file+sys->sprint(": %r"); 98 if(kr->sendmsg(fd, blind, len blind) < 0 || 99 kr->sendmsg(fd, digest, len digest) < 0){ 100 sys->remove(file); 101 return "can't write "+file+sys->sprint(": %r"); 102 } 103 104 # send blinded cert to client 105 kr->sendmsg(stdout, certbuf, len certbuf); 106 107 return nil; 108} 109 110signerkey(filename: string): ref Keyring->Authinfo 111{ 112 info := kr->readauthinfo(filename); 113 if(info != nil) 114 return info; 115 116 # generate a local key 117 info = ref Keyring->Authinfo; 118 info.mysk = kr->genSK("elgamal", "*", PKmodlen); 119 info.mypk = kr->sktopk(info.mysk); 120 info.spk = kr->sktopk(info.mysk); 121 myPKbuf := array of byte kr->pktostr(info.mypk); 122 state := kr->sha1(myPKbuf, len myPKbuf, nil, nil); 123 info.cert = kr->sign(info.mysk, 0, state, "sha1"); 124 (info.alpha, info.p) = kr->dhparams(DHmodlen); 125 126 if(kr->writeauthinfo(filename, info) < 0){ 127 sys->fprint(stderr, "can't write signerkey file: %r\n"); 128 return nil; 129 } 130 131 return info; 132} 133