1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
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;
}
|