20 func StoreSk(sk *openpgp.Entity) (err error) {
21 // TODO: initkey should save serverkey in db
22 b := new(bytes.Buffer)
27 return db.Set("key", key.Id(sk), b.Bytes())
30 func GetKeys(fpr string) (es openpgp.EntityList, err error) {
31 b, err := db.Get("key", fpr)
35 es, err = openpgp.ReadKeyRing(bytes.NewBuffer(b))
37 // internal error: pubkey cannot be parsed
43 func AddKeys(d []byte) (err error) {
44 entities, err := openpgp.ReadArmoredKeyRing(bytes.NewBuffer(d))
48 // TODO: allow multiple key uploads at once?
49 if len(entities) > 100 {
50 err = fmt.Errorf("expected at most 100 keys; got %d", len(entities))
53 for _, e := range entities {
54 // TODO: various checks..
55 // TODO: collect errors instead of aborting addkeys
56 isIssuer, issuer, denom, err1 := key.Check(e)
62 es, err1 := GetKeys(issuer)
67 ok, _, den, err1 := key.Check(es[0])
73 if !ok || den != denom {
74 err = fmt.Errorf("Issuer key check failed")
78 b := new(bytes.Buffer)
84 err = db.Insert("key", fpr, b.Bytes())
88 err = db.Append("keysby/64", fpr[len(fpr)-16:], []byte(fpr))
92 err = db.Append("keysby/32", fpr[len(fpr)-8:], []byte(fpr))
100 func CertByDraft(draftid string) (d []byte, err error) {
101 certid, err := db.Get("certby/draft", draftid)
103 // TODO: we have the draft but the cert is not ready
106 d, err = db.Get("cert", string(certid))
108 // shouldn't happen, cert is not available
114 func CertByDebitCert(debitid string) (d []byte, err error) {
115 creditid, err := db.Get("certby/debit", debitid)
117 // TODO: we have the debit cert but the credit cert is not ready
120 d, err = db.Get("cert", string(creditid))
122 // shouldn't happen, cert is not available
128 // parse clear signed draft and verify it
129 func ParseDraft(d []byte) (draft *document.Draft, draftid string, err error) {
130 iv, signed, err := document.Parse(d)
134 draft, ok := iv.(*document.Draft)
136 err = fmt.Errorf("ParseDraft: expected a draft document")
139 draftid = document.Id(signed)
141 k, err := db.Get("key", draft.Drawer)
145 kr, err := openpgp.ReadKeyRing(bytes.NewBuffer(k))
147 // internal error: pubkey cannot be parsed
150 err = document.Verify(signed, kr)
154 _, issuer, denom, err := key.Check(kr[0])
158 k, err = db.Get("key", draft.Beneficiary)
162 kr, err = openpgp.ReadKeyRing(bytes.NewBuffer(k))
164 // internal error: pubkey cannot be parsed
167 _, issuer2, denom2, err := key.Check(kr[0])
171 if draft.Issuer != issuer ||
172 draft.Issuer != issuer2 ||
173 draft.Denomination != denom ||
174 draft.Denomination != denom2 {
175 err = fmt.Errorf("Issuer or denomination mismatch")
179 // TODO: do various format checks (AuthorizedBy check etc)
180 if draft.Amount <= 0 || draft.Amount >= IntLimit {
181 err = fmt.Errorf("draft amount is invalid: %d", draft.Amount)
187 func ParseDebitCert(d []byte) (cert *document.DebitCert, certid string, err error) {
188 iv, signed, err := document.Parse(d)
192 cert, ok := iv.(*document.DebitCert)
194 err = fmt.Errorf("ParseDebitCert: expected a debit docuent")
198 k, err := db.Get("key", cert.AuthorizedBy)
202 // TODO: keep our key at hand
203 kr, err := openpgp.ReadKeyRing(bytes.NewBuffer(k))
205 // internal error: pubkey cannot be parsed
208 // must clean up to make sure the hash is ok
209 err = document.Verify(signed, kr)
214 certid = document.Id(signed)
218 func NewDebitCert(draftid string, draft *document.Draft) (*document.DebitCert, error) {
219 cert := new(document.DebitCert)
220 cert.Holder = draft.Drawer
221 cert.Date = time.Now().Unix()
222 cert.Denomination = "epoint"
223 cert.Issuer = draft.Issuer
224 cert.AuthorizedBy = draft.AuthorizedBy
225 cert.Difference = -draft.Amount
227 cert.Beneficiary = draft.Beneficiary
229 oid, err := db.Get("certby/key", draft.Drawer)
230 oldcertid := string(oid)
232 // first cert: drawer is issuer
233 if draft.Drawer != draft.Issuer {
234 return nil, fmt.Errorf("drawer must be the issuer when drawing an empty account (%s != %s)", draft.Drawer, draft.Issuer)
237 cert.Balance = cert.Difference
238 cert.LastDebitSerial = 0
239 cert.LastCreditSerial = 0
241 d, err := db.Get("cert", oldcertid)
245 iv, _, err := document.Parse(d)
250 // TODO: this is a hack
251 oldcert, err := document.ToCert(iv)
256 // TODO: sanity checks? oldcert.Holder == draft.Drawer
257 cert.Serial = oldcert.Serial + 1
258 cert.Balance = oldcert.Balance + cert.Difference
259 if cert.Balance <= -IntLimit {
260 return nil, fmt.Errorf("balance limit exceeded: %d", cert.Balance)
262 if oldcert.Balance > 0 && cert.Balance < 0 {
263 return nil, fmt.Errorf("insufficient funds: %d", oldcert.Balance)
265 cert.LastDebitSerial = oldcert.LastDebitSerial
266 cert.LastCreditSerial = oldcert.LastCreditSerial
267 if _, ok := iv.(*document.DebitCert); ok {
268 cert.LastDebitSerial = oldcert.Serial
270 cert.LastCreditSerial = oldcert.Serial
272 cert.LastCert = &oldcertid
277 func NewCreditCert(draftid string, draft *document.Draft, dcertid string, dcert *document.DebitCert) (*document.CreditCert, error) {
278 cert := new(document.CreditCert)
279 // TODO: get from old cert instead?
280 cert.Holder = dcert.Beneficiary
281 cert.Date = time.Now().Unix()
282 // TODO: get these from the cert holder pubkey
283 cert.Denomination = "epoint"
284 cert.Issuer = draft.Issuer
285 cert.AuthorizedBy = dcert.AuthorizedBy // TODO: draft vs dcert vs serverside decision
286 cert.Difference = -dcert.Difference
288 cert.Drawer = dcert.Holder
289 cert.DebitCert = dcertid
291 oid, err := db.Get("certby/key", dcert.Beneficiary)
292 oldcertid := string(oid)
294 // this is the first cert
296 cert.Balance = cert.Difference
297 cert.LastDebitSerial = 0
298 cert.LastCreditSerial = 0
300 d, err := db.Get("cert", oldcertid)
305 iv, _, err := document.Parse(d)
310 // TODO: this is a hack
311 oldcert, err := document.ToCert(iv)
316 cert.Serial = oldcert.Serial + 1
317 cert.Balance = oldcert.Balance + cert.Difference
318 if cert.Balance >= IntLimit {
319 return nil, fmt.Errorf("balance limit exceeded: %d", cert.Balance)
321 cert.LastDebitSerial = oldcert.LastDebitSerial
322 cert.LastCreditSerial = oldcert.LastCreditSerial
323 if _, ok := iv.(*document.DebitCert); ok {
324 cert.LastDebitSerial = oldcert.Serial
326 cert.LastCreditSerial = oldcert.Serial
328 cert.LastCert = &oldcertid
333 func EvalDraft(d []byte, sk *openpgp.Entity) (r []byte, err error) {
334 draft, draftid, err := ParseDraft(d)
338 _, err = db.Get("draft", draftid)
341 // TODO: certby/draft might not be ready even if draft is there
342 return CertByDraft(draftid)
344 // if draft is ok we save it
345 err = db.Set("draft", draftid, d)
350 // TODO: db.Insert: fails if key exists
351 s := fmt.Sprintf("%s.%s", draft.Drawer, draft.Nonce)
352 _, err = db.Get("draftby/key.nonce", s)
354 err = fmt.Errorf("draft nonce is not unique")
357 err = db.Set("draftby/key.nonce", s, d)
364 cert, err := NewDebitCert(draftid, draft)
368 r, signed, err := document.Format(cert, sk)
369 certid := document.Id(signed)
370 err = db.Set("cert", certid, r)
375 err = db.Set("certby/draft", draftid, []byte(certid))
380 err = db.Set("certby/key", cert.Holder, []byte(certid))
386 err = db.Set("certby/key.serial", fmt.Sprintf("%s.%09d", cert.Holder, cert.Serial), []byte(certid))
394 func EvalDebitCert(d []byte, sk *openpgp.Entity) (r []byte, err error) {
395 dcert, dcertid, err := ParseDebitCert(d)
399 r, err = CertByDebitCert(dcertid)
404 // TODO: we only need the draft to know the issuer (+beneficiary)
405 // it should be in the pubkey
406 d, err = db.Get("draft", dcert.Draft)
411 iv, _, err := document.Parse(d)
416 draft, ok := iv.(*document.Draft)
419 err = fmt.Errorf("EvalDebitCert: expected draft from internal db")
424 // TODO: check pubkey etc
425 cert, err := NewCreditCert(dcert.Draft, draft, dcertid, dcert)
430 r, signed, err := document.Format(cert, sk)
435 certid := document.Id(signed)
436 err = db.Set("cert", certid, r)
441 err = db.Set("certby/debit", dcertid, []byte(certid))
446 err = db.Set("certby/key", cert.Holder, []byte(certid))
452 err = db.Set("certby/key.serial", fmt.Sprintf("%s.%09d", cert.Holder, cert.Serial), []byte(certid))
460 func Init(rootdir string) (err error) {
461 db, err = store.Open(rootdir)
465 err = db.Ensure("key")
469 err = db.Ensure("cert")
473 err = db.Ensure("draft")
477 err = db.Ensure("certby/draft")
481 err = db.Ensure("certby/debit")
485 err = db.Ensure("certby/key")
489 err = db.Ensure("certby/key.serial")
493 err = db.Ensure("draftby/key.nonce")
497 err = db.Ensure("keysby/64")
501 err = db.Ensure("keysby/32")