From: nsz Date: Fri, 16 Dec 2011 06:48:33 +0000 (+0100) Subject: +armorkey, update epoint-client X-Git-Url: http://nsz.repo.hu/git/?p=epoint;a=commitdiff_plain;h=a86164c8ba48de5cb1a95acc140e811d1c4b1241 +armorkey, update epoint-client --- diff --git a/cmd/armorkey/Makefile b/cmd/armorkey/Makefile new file mode 100644 index 0000000..8a91db3 --- /dev/null +++ b/cmd/armorkey/Makefile @@ -0,0 +1,7 @@ +include $(GOROOT)/src/Make.inc + +TARG=armorkey +GOFILES=\ + armorkey.go + +include $(GOROOT)/src/Make.cmd diff --git a/cmd/armorkey/armorkey.go b/cmd/armorkey/armorkey.go new file mode 100644 index 0000000..628f06a --- /dev/null +++ b/cmd/armorkey/armorkey.go @@ -0,0 +1,81 @@ +package main + +import ( + "bufio" + "crypto/openpgp" + "crypto/openpgp/armor" + "flag" + "io" + "log" + "os" +) + +var dearmor = flag.Bool("d", false, "dearmor binary key") +var publiconly = flag.Bool("p", false, "ouput public part only, even if input is a private key") + +func serialize(w io.Writer, e *openpgp.Entity, publiconly bool) (err error) { + if publiconly { + err = e.Serialize(w) + } else { + err = e.SerializePrivate(w) + } + return +} + +func code(e *openpgp.Entity, arm bool) (err error) { + pub := e.PrivateKey == nil || *publiconly + header := openpgp.PublicKeyType + if !pub { + header = openpgp.PrivateKeyType + } + out := bufio.NewWriter(os.Stdout) + if arm { + w, err1 := armor.Encode(out, header, nil) + err = err1 + if err != nil { + return + } + err = serialize(w, e, pub) + if err != nil { + return + } + err = w.Close() + if err != nil { + return + } + _, err = out.Write([]byte{'\n'}) + if err != nil { + return + } + } else { + err = serialize(out, e, pub) + if err != nil { + return + } + } + err = out.Flush() + return +} + +func main() { + flag.Parse() + var elist openpgp.EntityList + var err error + in := bufio.NewReader(os.Stdin) + if *dearmor { + elist, err = openpgp.ReadArmoredKeyRing(in) + } else { + elist, err = openpgp.ReadKeyRing(in) + } + if err != nil { + log.Fatal(err) + } + if len(elist) != 1 { + log.Fatal("expected a single key") + } + err = code(elist[0], !*dearmor) + if err != nil { + log.Fatal(err) + } + return +} diff --git a/cmd/epoint-client/epoint-client.go b/cmd/epoint-client/epoint-client.go index 8ffc615..4281519 100644 --- a/cmd/epoint-client/epoint-client.go +++ b/cmd/epoint-client/epoint-client.go @@ -7,6 +7,7 @@ import ( "crypto/rand" "epoint/document" "epoint/key" + "epoint/store" "fmt" "io" "log" @@ -16,13 +17,18 @@ import ( "strconv" ) -const usage = `usage: ./epoint-client [k|d|s|v] [args..] < [seed|document] +// TODO: store documents, query store (keys), easy submit + +var db *store.Conn + +const usage = `usage: ./epoint-client [k|d|s|v|c] [args..] < [seed|document] server is http://localhost:8080 by default k - make key, use seed for generation, args: [issuer] denomination -d - make draft, use seed as signing key, args: targetid value -s - submit a document, args: k[ey]|d[raft]|c[ert] [server] +d - make draft, use seed for signing key, args: targetid value +s - submit a (key|draft|cert) document, args: k|d|c [server] v - verify a document (prints body of the document if ok) +c - connect to server and get server key, args: [server] ` func rnd(n int) (r []byte, err error) { @@ -42,52 +48,96 @@ func k(r []byte, issuer, denom string) (err error) { if err != nil { return } - w, err := armor.Encode(os.Stdout, openpgp.PublicKeyType, nil) - if err != nil { - return - } - // TODO: maybe Serialize should do this internally - for _, ident := range e.Identities { - err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey) + log.Printf("generated key %s", key.Id(e)) + d, err := db.Get("key", key.Id(e)) + if err == nil { + // TODO: issuer, denom check (remove keys from store if they are not sent to server?) + log.Printf("key %s was found in store", key.Id(e)) + } else { + out := new(bytes.Buffer) + w, err1 := armor.Encode(out, openpgp.PublicKeyType, nil) + err = err1 if err != nil { return } - } - for _, subkey := range e.Subkeys { - err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey) + // TODO: maybe Serialize should do this internally + for _, ident := range e.Identities { + err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey) + if err != nil { + return + } + } + for _, subkey := range e.Subkeys { + err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey) + if err != nil { + return + } + } + err = e.Serialize(w) + if err != nil { + return + } + err = w.Close() + if err != nil { + return + } + _, err = out.Write([]byte{'\n'}) + if err != nil { + return + } + d = out.Bytes() + err = db.Insert("key", key.Id(e), d) if err != nil { return } } + _, err = os.Stdout.Write(d) + return +} - err = e.Serialize(w) +func d(r []byte, target, value string) (err error) { + v, err := strconv.Atoi64(value) if err != nil { return } - err = w.Close() + e, err := key.Holder(r, "", "") if err != nil { return } - _, err = os.Stdout.Write([]byte{'\n'}) - return -} - -func d(r []byte, target, value string) (err error) { - v, err := strconv.Atoi64(value) + log.Printf("drawer: %s", key.Id(e)) + if key.Id(e) == target { + err = fmt.Errorf("Drawer and beneficiary are the same") + return + } + b, err := db.Get("key", key.Id(e)) if err != nil { return } - e, err := key.Holder(r, "", "") + e1, err := key.Parse(b) + if err != nil { + return + } + _, issuer, denom, err := key.Check(e1) + if err != nil { + return + } + // TODO: store server id as well? + b, err = db.Get("", "serverkey") if err != nil { return } + sk, err := key.Parse(b) + if err != nil { + return + } + // TODO: check beneficiary (check value?) draft := new(document.Draft) draft.Drawer = key.Id(e) draft.Beneficiary = target draft.Amount = v - draft.Denomination = "" // TODO - draft.Issuer = "" // TODO - draft.AuthorizedBy = "" // TODO + draft.Denomination = denom + draft.Issuer = issuer + draft.AuthorizedBy = key.Id(sk) nonce, err := rnd(10) if err != nil { return @@ -112,13 +162,14 @@ func s(d []byte, cmd, server string) (err error) { err = fmt.Errorf("unknown submit command: %s", cmd) return } - resp, err := http.PostForm(server, url.Values{k: {string(d)}}) + resp, err := http.PostForm(server+"/submit", url.Values{k: {string(d)}}) if err != nil { return } if resp.StatusCode != 200 { log.Printf("request failed: %s\n", resp.Status) } + // TODO: store result _, err = io.Copy(os.Stdout, resp.Body) if err != nil { return @@ -161,16 +212,97 @@ func v(d []byte) (err error) { return } -func read() []byte { +func c(server string) (err error) { + resp, err := http.Get(server + "/serverkey") + if err != nil { + return + } + if resp.StatusCode != 200 { + log.Printf("request failed: %s\n", resp.Status) + } + b, err := readall(resp.Body) + if err != nil { + return + } + err = resp.Body.Close() + if err != nil { + return + } + e, err := key.Parse(b) + if err != nil { + return + } + log.Printf("got server key %s", key.Id(e)) + err = db.Set("", "serverkey", b) + return +} + +// TODO: commmon code with server +func initstore(dir string) (db *store.Conn, err error) { + log.Printf("using root dir %s", dir) + db, err = store.Open(dir) + if err != nil { + return + } + err = db.Ensure("key") + if err != nil { + return + } + err = db.Ensure("cert") + if err != nil { + return + } + err = db.Ensure("draft") + if err != nil { + return + } + err = db.Ensure("certby/draft") + if err != nil { + return + } + err = db.Ensure("certby/debit") + if err != nil { + return + } + err = db.Ensure("certby/key") + if err != nil { + return + } + err = db.Ensure("certby/key.serial") + if err != nil { + return + } + return +} + +func storedir() string { + dir := os.Getenv("HOME") + if dir == "" { + dir = "/var/cache/epoint" + } else { + dir += "/.epoint-client" + } + return dir +} + +func readall(r io.Reader) ([]byte, error) { b := make([]byte, 10000) - n, err := io.ReadFull(os.Stdin, b) + n, err := io.ReadFull(r, b) if err != io.ErrUnexpectedEOF { if err == nil { - log.Fatal("too much input") + err = fmt.Errorf("too much input") } + return nil, err + } + return b[:n], nil +} + +func read() []byte { + b, err := readall(os.Stdin) + if err != nil { log.Fatal(err) } - return b[:n] + return b } func main() { @@ -179,6 +311,8 @@ func main() { } var err error + db, err = initstore(storedir()) + server := "http://localhost:8080" switch os.Args[1] { case "k": issuer := "" @@ -198,7 +332,6 @@ func main() { } err = d(read(), os.Args[2], os.Args[3]) case "s": - server := "http://localhost:8080" cmd := "" if len(os.Args) == 4 { cmd = os.Args[2] @@ -208,12 +341,21 @@ func main() { } else { log.Fatal(usage) } - err = s(read(), cmd, server+"/submit") + err = s(read(), cmd, server) case "v": if len(os.Args) != 2 { log.Fatal(usage) } err = v(read()) + case "c": + if len(os.Args) == 3 { + server = os.Args[2] + } else if len(os.Args) != 2 { + log.Fatal(usage) + } + err = c(server) + default: + log.Fatal(usage) } if err != nil { log.Fatal(err) diff --git a/pkg/Makefile b/pkg/Makefile index 896c219..5681a0a 100644 --- a/pkg/Makefile +++ b/pkg/Makefile @@ -7,6 +7,7 @@ DIRS=\ key\ server\ store\ + ../cmd/armorkey\ ../cmd/genkey\ ../cmd/epoint-client\ ../cmd/epoint-server\