tdsasign: new command - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 0e43f5c6d330afe996e157205e78618001d1d038
 (DIR) parent 281ca361d340f6afb153bfa2bfbdcf61116a31bf
 (HTM) Author: Russ Cox <rsc@swtch.com>
       Date:   Wed,  5 Oct 2011 16:20:59 -0400
       
       dsasign: new command
       
       Diffstat:
         A src/cmd/auth/dsasign.c              |     180 +++++++++++++++++++++++++++++++
         M src/cmd/auth/mkfile                 |       1 +
       
       2 files changed, 181 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/src/cmd/auth/dsasign.c b/src/cmd/auth/dsasign.c
       t@@ -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;
       +}
 (DIR) diff --git a/src/cmd/auth/mkfile b/src/cmd/auth/mkfile
       t@@ -6,6 +6,7 @@ TARG=\
                asn12dsa\
                asn12rsa\
                dsagen\
       +        dsasign\
                dsa2pub\
                dsa2ssh\
                passwd\