diff options
author | Russ Cox <rsc@swtch.com> | 2011-10-05 16:20:59 -0400 |
---|---|---|
committer | Russ Cox <rsc@swtch.com> | 2011-10-05 16:20:59 -0400 |
commit | 0e43f5c6d330afe996e157205e78618001d1d038 (patch) | |
tree | 45c49b5d06839d53ffed60d0fbe3a29031eab135 /src/cmd/auth/dsasign.c | |
parent | 281ca361d340f6afb153bfa2bfbdcf61116a31bf (diff) | |
download | plan9port-0e43f5c6d330afe996e157205e78618001d1d038.tar.gz plan9port-0e43f5c6d330afe996e157205e78618001d1d038.tar.bz2 plan9port-0e43f5c6d330afe996e157205e78618001d1d038.zip |
dsasign: new command
Diffstat (limited to 'src/cmd/auth/dsasign.c')
-rw-r--r-- | src/cmd/auth/dsasign.c | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/src/cmd/auth/dsasign.c b/src/cmd/auth/dsasign.c new file mode 100644 index 00000000..1387dab6 --- /dev/null +++ b/src/cmd/auth/dsasign.c @@ -0,0 +1,180 @@ +#include <u.h> +#include <libc.h> +#include <mp.h> +#include <libsec.h> +#include <auth.h> +#include <thread.h> +#include <9pclient.h> +#include <bio.h> + +void +usage(void) +{ + fprint(2, "usage: 9 dsasign [-i id] [-v] key <data\n"); + threadexitsall("usage"); +} + +static void doVerify(void); +static char *getline(int*); + +char *id; +Biobuf b; +int nid; +char *key; + +void +threadmain(int argc, char **argv) +{ + int n, verify; + char *text, *p; + uchar digest[SHA1dlen]; + AuthRpc *rpc; + Fmt fmt; + + fmtinstall('[', encodefmt); + fmtinstall('H', encodefmt); + + verify = 0; + id = ""; + ARGBEGIN{ + case 'i': + id = EARGF(usage()); + break; + case 'v': + verify = 1; + break; + default: + usage(); + }ARGEND + + if(argc != 1) + usage(); + key = argv[0]; + nid = strlen(id); + + Binit(&b, 0, OREAD); + if(verify) { + doVerify(); + threadexitsall(nil); + } + + if((rpc = auth_allocrpc()) == nil){ + fprint(2, "dsasign: auth_allocrpc: %r\n"); + threadexits("rpc"); + } + key = smprint("proto=dsa role=sign %s", key); + if(auth_rpc(rpc, "start", key, strlen(key)) != ARok){ + fprint(2, "dsasign: auth 'start' failed: %r\n"); + auth_freerpc(rpc); + threadexits("rpc"); + } + + print("+%s\n", id); + + Binit(&b, 0, OREAD); + fmtstrinit(&fmt); + while((p = getline(&n)) != nil) { + if(p[0] == '-' || p[0] == '+') + print("+"); + print("%s\n", p); + fmtprint(&fmt, "%s\n", p); + } + text = fmtstrflush(&fmt); + sha1((uchar*)text, strlen(text), digest, nil); + + if(auth_rpc(rpc, "write", digest, SHA1dlen) != ARok) + sysfatal("auth write in sign failed: %r"); + if(auth_rpc(rpc, "read", nil, 0) != ARok) + sysfatal("auth read in sign failed: %r"); + + print("-%s %.*H\n", id, rpc->narg, rpc->arg); + threadexits(nil); +} + +static mpint* +keytomp(Attr *a, char *name) +{ + char *p; + mpint *m; + + p = _strfindattr(a, name); + if(p == nil) + sysfatal("missing key attribute %s", name); + m = strtomp(p, nil, 16, nil); + if(m == nil) + sysfatal("malformed key attribute %s=%s", name, p); + return m; +} + +static void +doVerify(void) +{ + char *p; + int n, nsig; + Fmt fmt; + uchar digest[SHA1dlen], sig[1024]; + char *text; + Attr *a; + DSAsig dsig; + DSApub dkey; + + a = _parseattr(key); + if(a == nil) + sysfatal("invalid key"); + dkey.alpha = keytomp(a, "alpha"); + dkey.key = keytomp(a, "key"); + dkey.p = keytomp(a, "p"); + dkey.q = keytomp(a, "q"); + if(!probably_prime(dkey.p, 20) && !probably_prime(dkey.q, 20)) + sysfatal("p or q not prime"); + + while((p = getline(&n)) != nil) + if(p[0] == '+' && strcmp(p+1, id) == 0) + goto start; + sysfatal("no message found"); + +start: + fmtstrinit(&fmt); + while((p = getline(&n)) != nil) { + if(n >= 1+nid+1+16 && p[0] == '-' && strncmp(p+1, id, nid) == 0 && p[1+nid] == ' ') { + if((nsig = dec16(sig, sizeof sig, p+1+nid+1, n-(1+nid+1))) != 20+20) + sysfatal("malformed signture"); + goto end; + } + if(p[0] == '+') + p++; + fmtprint(&fmt, "%s\n", p); + } + sysfatal("did not find end of message"); + +end: + text = fmtstrflush(&fmt); + sha1((uchar*)text, strlen(text), digest, nil); + + if(nsig != 40) + sysfatal("malformed signature"); + dsig.r = betomp(sig, 20, nil); + dsig.s = betomp(sig+20, 20, nil); + + if(dsaverify(&dkey, &dsig, betomp(digest, sizeof digest, nil)) < 0) + sysfatal("signature failed to verify: %r"); + + write(1, text, strlen(text)); + threadexitsall(0); +} + +char* +getline(int *np) +{ + char *p; + int n; + + if((p = Brdline(&b, '\n')) == nil) + return nil; + n = Blinelen(&b); + while(n > 0 && (p[n-1] == '\n' || p[n-1] == ' ' || p[n-1] == '\t')) + n--; + p[n] = '\0'; + *np = n; + return p; +} |