epoint-client
[epoint] / cmd / epoint-client / epoint-client.go
index da29a2c..518346c 100644 (file)
@@ -1,4 +1,188 @@
 package main
 
+import (
+       "crypto/openpgp"
+       "crypto/openpgp/armor"
+       "crypto/rand"
+       "epoint/document"
+       "epoint/key"
+       "fmt"
+       "io"
+       "log"
+       "net/http"
+       "net/url"
+       "os"
+       "strconv"
+)
+
+const usage = `usage: ./epoint-client [k|d|s|v] [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]
+v - verify a document (prints body of the document if ok)
+`
+
+func rnd(n int) (r []byte, err error) {
+       r = make([]byte, n)
+       _, err = io.ReadFull(rand.Reader, r)
+       return
+}
+
+func k(r []byte, issuer, denom string) (err error) {
+       var e *openpgp.Entity
+
+       if issuer == "" {
+               e, err = key.Issuer(r, denom)
+       } else {
+               e, err = key.Holder(r, issuer, denom)
+       }
+       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)
+               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.Write([]byte{'\n'})
+       if err != nil {
+               return
+       }
+       err = w.Close()
+       return
+}
+
+func d(r []byte, target, value string) (err error) {
+       v, err := strconv.Atoi64(value)
+       if err != nil {
+               return
+       }
+       e, err := key.Holder(r, "", "")
+       if err != nil {
+               return
+       }
+       draft := new(document.Draft)
+       draft.Drawer = key.Id(e)
+       draft.Beneficiary = target
+       draft.Amount = v
+       draft.Denomination = "" // TODO
+       draft.Issuer = ""       // TODO
+       draft.AuthorizedBy = "" // TODO
+       nonce, err := rnd(10)
+       if err != nil {
+               return
+       }
+       draft.Nonce = fmt.Sprintf("%X", nonce)
+       s, _, err := document.Format(draft, e)
+       if err != nil {
+               return
+       }
+       _, err = os.Stdout.Write(s)
+       return
+}
+
+func s(d []byte, cmd, server string) (err error) {
+       m := map[string]string{
+               "k": "key",
+               "d": "draft",
+               "c": "debit",
+       }
+       k, ok := m[cmd]
+       if !ok {
+               err = fmt.Errorf("unknown submit command: %s", cmd)
+               return
+       }
+       resp, err := http.PostForm(server, url.Values{k: {string(d)}})
+       if err != nil {
+               return
+       }
+       fmt.Printf("%v", resp)
+       return
+}
+
+func v(d []byte) (err error) {
+       _, s, err := document.Parse(d)
+       if err != nil {
+               return
+       }
+       _, err = os.Stdout.Write(s.Body)
+       return
+}
+
+func read() []byte {
+       b := make([]byte, 10000)
+       n, err := io.ReadFull(os.Stdin, b)
+       if err != io.ErrUnexpectedEOF {
+               if err == nil {
+                       log.Fatal("too much input")
+               }
+               log.Fatal(err)
+       }
+       return b[:n]
+}
+
 func main() {
+       if len(os.Args) < 2 {
+               log.Fatal(usage)
+       }
+
+       var err error
+       switch os.Args[1] {
+       case "k":
+               issuer := ""
+               denom := ""
+               if len(os.Args) == 4 {
+                       issuer = os.Args[2]
+                       denom = os.Args[3]
+               } else if len(os.Args) == 3 {
+                       denom = os.Args[2]
+               } else {
+                       log.Fatal(usage)
+               }
+               err = k(read(), issuer, denom)
+       case "d":
+               if len(os.Args) != 4 {
+                       log.Fatal(usage)
+               }
+               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]
+                       server = os.Args[3]
+               } else if len(os.Args) == 3 {
+                       cmd = os.Args[2]
+               } else {
+                       log.Fatal(usage)
+               }
+               err = s(read(), cmd, server+"/submit")
+       case "v":
+               if len(os.Args) != 2 {
+                       log.Fatal(usage)
+               }
+               err = v(read())
+       }
+       if err != nil {
+               log.Fatal(err)
+       }
 }