#include #include #include #include #include #include void usage(void) { fprint(2, "usage: dsasign [-i id] [-v] key narg, rpc->arg); exits(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, *text; uchar digest[SHA1dlen], sig[1024]; int n; Fmt fmt; 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] == ' ') goto end; if(p[0] == '+') p++; fmtprint(&fmt, "%s\n", p); } sysfatal("did not find end of message"); end: if(dec16(sig, sizeof sig, p+1+nid+1, n-(1+nid+1)) != 20+20) sysfatal("malformed signture"); text = fmtstrflush(&fmt); sha1((uchar*)text, strlen(text), digest, nil); 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)); exits(""); } static 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; }