add NotFoundError to store
[epoint] / logic / logic.go
index a9fd15b..602f458 100644 (file)
@@ -6,6 +6,7 @@ import (
        "bytes"
        "crypto/openpgp"
        "epoint/document"
+       "epoint/dsakey"
        "epoint/store"
        "fmt"
        "time"
@@ -16,6 +17,29 @@ const IntLimit = 1e15
 
 var db *store.Conn
 
+func StoreSk(sk *openpgp.Entity) (err error) {
+       // TODO: initkey should save serverkey in db
+       b := new(bytes.Buffer)
+       err = sk.Serialize(b)
+       if err != nil {
+               return
+       }
+       return db.Set("key", fmt.Sprintf("%X", sk.PrimaryKey.Fingerprint), b.Bytes())
+}
+
+func GetKeys(fpr string) (es openpgp.EntityList, err error) {
+       b, err := db.Get("key", fpr)
+       if err != nil {
+               return
+       }
+       es, err = openpgp.ReadKeyRing(bytes.NewBuffer(b))
+       if err != nil {
+               // internal error: pubkey cannot be parsed
+               return
+       }
+       return
+}
+
 func AddKeys(d []byte) (err error) {
        entities, err := openpgp.ReadArmoredKeyRing(bytes.NewBuffer(d))
        if err != nil {
@@ -28,21 +52,39 @@ func AddKeys(d []byte) (err error) {
        }
        for _, e := range entities {
                // TODO: various checks..
+               isIssuer, issuer, denom, err1 := dsakey.CheckEntity(e)
+               err = err1
+               if err != nil {
+                       // TODO..
+                       continue
+               }
+               if !isIssuer {
+                       es, err := GetKeys(issuer)
+                       if err != nil {
+                               // TODO..
+                               continue
+                       }
+                       ok, _, den, err := dsakey.CheckEntity(es[0])
+                       if !ok || err != nil || den != denom {
+                               // TODO..
+                               continue
+                       }
+               }
                b := new(bytes.Buffer)
                err = e.Serialize(b)
                if err != nil {
                        return
                }
-               fpr := fmt.Sprintf("%040X", e.PrimaryKey.Fingerprint)
+               fpr := fmt.Sprintf("%X", e.PrimaryKey.Fingerprint)
                err = db.Set("key", fpr, b.Bytes())
                if err != nil {
                        return
                }
-               err = db.Append("fprlist/64", fpr[len(fpr)-16:], []byte(fpr))
+               err = db.Append("keysby/64", fpr[len(fpr)-16:], []byte(fpr))
                if err != nil {
                        return
                }
-               err = db.Append("fprlist/32", fpr[len(fpr)-8:], []byte(fpr))
+               err = db.Append("keysby/32", fpr[len(fpr)-8:], []byte(fpr))
                if err != nil {
                        return
                }
@@ -51,7 +93,7 @@ func AddKeys(d []byte) (err error) {
 }
 
 func CertByDraft(draftid string) (d []byte, err error) {
-       certid, err := db.Get("certid/debit", draftid)
+       certid, err := db.Get("certby/draft", draftid)
        if err != nil {
                // TODO: we have the draft but the cert is not ready
                return
@@ -65,7 +107,7 @@ func CertByDraft(draftid string) (d []byte, err error) {
 }
 
 func CertByDebitCert(debitid string) (d []byte, err error) {
-       creditid, err := db.Get("certid/credit", debitid)
+       creditid, err := db.Get("certby/debit", debitid)
        if err != nil {
                // TODO: we have the debit cert but the credit cert is not ready
                return
@@ -90,7 +132,7 @@ func ParseDraft(d []byte) (draft *document.Draft, draftid string, err error) {
                return
        }
        draftid = document.Id(signed)
-/*
+
        k, err := db.Get("key", draft.Drawer)
        if err != nil {
                return
@@ -100,16 +142,35 @@ func ParseDraft(d []byte) (draft *document.Draft, draftid string, err error) {
                // internal error: pubkey cannot be parsed
                return
        }
-       cleaned, err = document.Verify(signed, kr)
+       err = document.Verify(signed, kr)
+       if err != nil {
+               return
+       }
+       _, issuer, denom, err := dsakey.CheckEntity(kr[0])
+       if err != nil {
+               return
+       }
+       k, err = db.Get("key", draft.Beneficiary)
        if err != nil {
                return
        }
-       // TODO: verify issuer
-       _, err = db.Get("key", draft.Beneficiary)
+       kr, err = openpgp.ReadKeyRing(bytes.NewBuffer(k))
+       if err != nil {
+               // internal error: pubkey cannot be parsed
+               return
+       }
+       _, issuer2, denom2, err := dsakey.CheckEntity(kr[0])
        if err != nil {
                return
        }
-*/
+       if draft.Issuer != issuer ||
+               draft.Issuer != issuer2 ||
+               draft.Denomination != denom ||
+               draft.Denomination != denom2 {
+               err = fmt.Errorf("Issuer or denomination mismatch")
+               return
+       }
+
        // TODO: do various format checks (AuthorizedBy check etc)
        if draft.Amount <= 0 || draft.Amount >= IntLimit {
                err = fmt.Errorf("draft amount is invalid: %d", draft.Amount)
@@ -128,23 +189,23 @@ func ParseDebitCert(d []byte) (cert *document.DebitCert, certid string, err erro
                err = fmt.Errorf("ParseDebitCert: expected a debit docuent")
                return
        }
-/*
-       // TODO: keep our key at hand
+
        k, err := db.Get("key", cert.AuthorizedBy)
        if err != nil {
                return
        }
+       // TODO: keep our key at hand
        kr, err := openpgp.ReadKeyRing(bytes.NewBuffer(k))
        if err != nil {
                // internal error: pubkey cannot be parsed
                return
        }
        // must clean up to make sure the hash is ok
-       cleaned, err = document.Verify(signed, kr)
+       err = document.Verify(signed, kr)
        if err != nil {
                return
        }
-*/
+
        certid = document.Id(signed)
        return
 }
@@ -160,7 +221,7 @@ func NewDebitCert(draftid string, draft *document.Draft) (*document.DebitCert, e
        cert.Draft = draftid
        cert.Beneficiary = draft.Beneficiary
 
-       oid, err := db.Get("certid/last", draft.Drawer)
+       oid, err := db.Get("certby/key", draft.Drawer)
        oldcertid := string(oid)
        if err != nil {
                // first cert: drawer is issuer
@@ -183,6 +244,10 @@ func NewDebitCert(draftid string, draft *document.Draft) (*document.DebitCert, e
                }
                // TODO: this is a hack
                oldcert, err := document.ToCert(iv)
+               if err != nil {
+                       // internal error
+                       return nil, err
+               }
                // TODO: sanity checks? oldcert.Holder == draft.Drawer
                cert.Serial = oldcert.Serial + 1
                cert.Balance = oldcert.Balance + cert.Difference
@@ -194,7 +259,7 @@ func NewDebitCert(draftid string, draft *document.Draft) (*document.DebitCert, e
                }
                cert.LastDebitSerial = oldcert.LastDebitSerial
                cert.LastCreditSerial = oldcert.LastCreditSerial
-               if oldcert.IsDebit {
+               if _,ok := iv.(*document.DebitCert); ok {
                        cert.LastDebitSerial = oldcert.Serial
                } else {
                        cert.LastCreditSerial = oldcert.Serial
@@ -218,7 +283,7 @@ func NewCreditCert(draftid string, draft *document.Draft, dcertid string, dcert
        cert.Drawer = dcert.Holder
        cert.DebitCert = dcertid
 
-       oid, err := db.Get("certid/last", dcert.Beneficiary)
+       oid, err := db.Get("certby/key", dcert.Beneficiary)
        oldcertid := string(oid)
        if err != nil {
                // this is the first cert
@@ -250,7 +315,7 @@ func NewCreditCert(draftid string, draft *document.Draft, dcertid string, dcert
                }
                cert.LastDebitSerial = oldcert.LastDebitSerial
                cert.LastCreditSerial = oldcert.LastCreditSerial
-               if oldcert.IsDebit {
+               if _,ok := iv.(*document.DebitCert); ok {
                        cert.LastDebitSerial = oldcert.Serial
                } else {
                        cert.LastCreditSerial = oldcert.Serial
@@ -260,7 +325,6 @@ func NewCreditCert(draftid string, draft *document.Draft, dcertid string, dcert
        return cert, nil
 }
 
-// TODO: draft ref
 func EvalDraft(d []byte, sk *openpgp.Entity) (r []byte, err error) {
        draft, draftid, err := ParseDraft(d)
        if err != nil {
@@ -269,6 +333,7 @@ func EvalDraft(d []byte, sk *openpgp.Entity) (r []byte, err error) {
        _, err = db.Get("draft", draftid)
        if err == nil {
                // found
+               // TODO: certby/draft might not be ready even if draft is there
                return CertByDraft(draftid)
        }
        // if draft is ok we save it
@@ -277,6 +342,18 @@ func EvalDraft(d []byte, sk *openpgp.Entity) (r []byte, err error) {
                // internal error
                return
        }
+       // TODO: db.Insert: fails if key exists
+       s := fmt.Sprintf("%s.%s", draft.Drawer, draft.Nonce)
+       _, err = db.Get("draftby/key.nonce", s)
+       if err == nil {
+               err = fmt.Errorf("draft nonce is not unique")
+               return
+       }
+       err = db.Set("draftby/key.nonce", s, d)
+       if err != nil {
+               // internal error
+               return
+       }
 
        // debit cert
        cert, err := NewDebitCert(draftid, draft)
@@ -290,18 +367,18 @@ func EvalDraft(d []byte, sk *openpgp.Entity) (r []byte, err error) {
                // internal error
                return
        }
-       err = db.Set("certid/debit", draftid, []byte(certid))
+       err = db.Set("certby/draft", draftid, []byte(certid))
        if err != nil {
                // internal error
                return
        }
-       err = db.Set("certid/last", cert.Holder, []byte(certid))
+       err = db.Set("certby/key", cert.Holder, []byte(certid))
        if err != nil {
                // internal error
                return
        }
        // TODO: append?
-       err = db.Set("certid/all", fmt.Sprintf("%s.%09d", cert.Holder, cert.Serial), []byte(certid))
+       err = db.Set("certby/key.serial", fmt.Sprintf("%s.%09d", cert.Holder, cert.Serial), []byte(certid))
        if err != nil {
                // internal error
                return
@@ -356,18 +433,18 @@ func EvalDebitCert(d []byte, sk *openpgp.Entity) (r []byte, err error) {
                // internal error
                return
        }
-       err = db.Set("certid/credit", dcertid, []byte(certid))
+       err = db.Set("certby/debit", dcertid, []byte(certid))
        if err != nil {
                // internal error
                return
        }
-       err = db.Set("certid/last", cert.Holder, []byte(certid))
+       err = db.Set("certby/key", cert.Holder, []byte(certid))
        if err != nil {
                // internal error
                return
        }
        // TODO: append?
-       err = db.Set("certid/all", fmt.Sprintf("%s.%09d", cert.Holder, cert.Serial), []byte(certid))
+       err = db.Set("certby/key.serial", fmt.Sprintf("%s.%09d", cert.Holder, cert.Serial), []byte(certid))
        if err != nil {
                // internal error
                return
@@ -375,8 +452,8 @@ func EvalDebitCert(d []byte, sk *openpgp.Entity) (r []byte, err error) {
        return
 }
 
-func Init() (err error) {
-       db, err = store.Open("teststore")
+func Init(rootdir string) (err error) {
+       db, err = store.Open(rootdir)
        if err != nil {
                return
        }
@@ -392,27 +469,31 @@ func Init() (err error) {
        if err != nil {
                return
        }
-       err = db.Ensure("certid/credit")
+       err = db.Ensure("certby/draft")
+       if err != nil {
+               return
+       }
+       err = db.Ensure("certby/debit")
        if err != nil {
                return
        }
-       err = db.Ensure("certid/debit")
+       err = db.Ensure("certby/key")
        if err != nil {
                return
        }
-       err = db.Ensure("certid/last")
+       err = db.Ensure("certby/key.serial")
        if err != nil {
                return
        }
-       err = db.Ensure("certid/all")
+       err = db.Ensure("draftby/key.nonce")
        if err != nil {
                return
        }
-       err = db.Ensure("fprlist/64")
+       err = db.Ensure("keysby/64")
        if err != nil {
                return
        }
-       err = db.Ensure("fprlist/32")
+       err = db.Ensure("keysby/32")
        if err != nil {
                return
        }