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", fmt.Sprintf("%X", sk.PrimaryKey.Fingerprint), 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 isIssuer, issuer, denom, err1 := dsakey.CheckEntity(e)
62 es, err := GetKeys(issuer)
67 ok, _, den, err := dsakey.CheckEntity(es[0])
68 if !ok || err != nil || den != denom {
73 b := new(bytes.Buffer)
78 fpr := fmt.Sprintf("%X", e.PrimaryKey.Fingerprint)
79 err = db.Set("key", fpr, b.Bytes())
83 err = db.Append("keysby/64", fpr[len(fpr)-16:], []byte(fpr))
87 err = db.Append("keysby/32", fpr[len(fpr)-8:], []byte(fpr))
95 func CertByDraft(draftid string) (d []byte, err error) {
96 certid, err := db.Get("certby/draft", draftid)
98 // TODO: we have the draft but the cert is not ready
101 d, err = db.Get("cert", string(certid))
103 // shouldn't happen, cert is not available
109 func CertByDebitCert(debitid string) (d []byte, err error) {
110 creditid, err := db.Get("certby/debit", debitid)
112 // TODO: we have the debit cert but the credit cert is not ready
115 d, err = db.Get("cert", string(creditid))
117 // shouldn't happen, cert is not available
123 // parse clear signed draft and verify it
124 func ParseDraft(d []byte) (draft *document.Draft, draftid string, err error) {
125 iv, signed, err := document.Parse(d)
129 draft, ok := iv.(*document.Draft)
131 err = fmt.Errorf("ParseDraft: expected a draft docuent")
134 draftid = document.Id(signed)
136 k, err := db.Get("key", draft.Drawer)
140 kr, err := openpgp.ReadKeyRing(bytes.NewBuffer(k))
142 // internal error: pubkey cannot be parsed
145 err = document.Verify(signed, kr)
149 _, issuer, denom, err := dsakey.CheckEntity(kr[0])
153 k, err = db.Get("key", draft.Beneficiary)
157 kr, err = openpgp.ReadKeyRing(bytes.NewBuffer(k))
159 // internal error: pubkey cannot be parsed
162 _, issuer2, denom2, err := dsakey.CheckEntity(kr[0])
166 if draft.Issuer != issuer ||
167 draft.Issuer != issuer2 ||
168 draft.Denomination != denom ||
169 draft.Denomination != denom2 {
170 err = fmt.Errorf("Issuer or denomination mismatch")
174 // TODO: do various format checks (AuthorizedBy check etc)
175 if draft.Amount <= 0 || draft.Amount >= IntLimit {
176 err = fmt.Errorf("draft amount is invalid: %d", draft.Amount)
182 func ParseDebitCert(d []byte) (cert *document.DebitCert, certid string, err error) {
183 iv, signed, err := document.Parse(d)
187 cert, ok := iv.(*document.DebitCert)
189 err = fmt.Errorf("ParseDebitCert: expected a debit docuent")
193 k, err := db.Get("key", cert.AuthorizedBy)
197 // TODO: keep our key at hand
198 kr, err := openpgp.ReadKeyRing(bytes.NewBuffer(k))
200 // internal error: pubkey cannot be parsed
203 // must clean up to make sure the hash is ok
204 err = document.Verify(signed, kr)
209 certid = document.Id(signed)
213 func NewDebitCert(draftid string, draft *document.Draft) (*document.DebitCert, error) {
214 cert := new(document.DebitCert)
215 cert.Holder = draft.Drawer
216 cert.Date = time.Seconds()
217 cert.Denomination = "epoint"
218 cert.Issuer = draft.Issuer
219 cert.AuthorizedBy = draft.AuthorizedBy
220 cert.Difference = -draft.Amount
222 cert.Beneficiary = draft.Beneficiary
224 oid, err := db.Get("certby/key", draft.Drawer)
225 oldcertid := string(oid)
227 // first cert: drawer is issuer
228 if draft.Drawer != draft.Issuer {
229 return nil, fmt.Errorf("drawer must be the issuer when drawing an empty account")
232 cert.Balance = cert.Difference
233 cert.LastDebitSerial = 0
234 cert.LastCreditSerial = 0
236 d, err := db.Get("cert", oldcertid)
240 iv, _, err := document.Parse(d)
245 // TODO: this is a hack
246 oldcert, err := document.ToCert(iv)
251 // TODO: sanity checks? oldcert.Holder == draft.Drawer
252 cert.Serial = oldcert.Serial + 1
253 cert.Balance = oldcert.Balance + cert.Difference
254 if cert.Balance <= -IntLimit {
255 return nil, fmt.Errorf("balance limit exceeded: %d", cert.Balance)
257 if oldcert.Balance > 0 && cert.Balance < 0 {
258 return nil, fmt.Errorf("insufficient funds: %d", oldcert.Balance)
260 cert.LastDebitSerial = oldcert.LastDebitSerial
261 cert.LastCreditSerial = oldcert.LastCreditSerial
262 if _,ok := iv.(*document.DebitCert); ok {
263 cert.LastDebitSerial = oldcert.Serial
265 cert.LastCreditSerial = oldcert.Serial
267 cert.LastCert = &oldcertid
272 func NewCreditCert(draftid string, draft *document.Draft, dcertid string, dcert *document.DebitCert) (*document.CreditCert, error) {
273 cert := new(document.CreditCert)
274 // TODO: get from old cert instead?
275 cert.Holder = dcert.Beneficiary
276 cert.Date = time.Seconds()
277 // TODO: get these from the cert holder pubkey
278 cert.Denomination = "epoint"
279 cert.Issuer = draft.Issuer
280 cert.AuthorizedBy = dcert.AuthorizedBy // TODO: draft vs dcert vs serverside decision
281 cert.Difference = -dcert.Difference
283 cert.Drawer = dcert.Holder
284 cert.DebitCert = dcertid
286 oid, err := db.Get("certby/key", dcert.Beneficiary)
287 oldcertid := string(oid)
289 // this is the first cert
291 cert.Balance = cert.Difference
292 cert.LastDebitSerial = 0
293 cert.LastCreditSerial = 0
295 d, err := db.Get("cert", oldcertid)
300 iv, _, err := document.Parse(d)
305 // TODO: this is a hack
306 oldcert, err := document.ToCert(iv)
311 cert.Serial = oldcert.Serial + 1
312 cert.Balance = oldcert.Balance + cert.Difference
313 if cert.Balance >= IntLimit {
314 return nil, fmt.Errorf("balance limit exceeded: %d", cert.Balance)
316 cert.LastDebitSerial = oldcert.LastDebitSerial
317 cert.LastCreditSerial = oldcert.LastCreditSerial
318 if _,ok := iv.(*document.DebitCert); ok {
319 cert.LastDebitSerial = oldcert.Serial
321 cert.LastCreditSerial = oldcert.Serial
323 cert.LastCert = &oldcertid
328 func EvalDraft(d []byte, sk *openpgp.Entity) (r []byte, err error) {
329 draft, draftid, err := ParseDraft(d)
333 _, err = db.Get("draft", draftid)
336 // TODO: certby/draft might not be ready even if draft is there
337 return CertByDraft(draftid)
339 // if draft is ok we save it
340 err = db.Set("draft", draftid, d)
345 // TODO: db.Insert: fails if key exists
346 s := fmt.Sprintf("%s.%s", draft.Drawer, draft.Nonce)
347 _, err = db.Get("draftby/key.nonce", s)
349 err = fmt.Errorf("draft nonce is not unique")
352 err = db.Set("draftby/key.nonce", s, d)
359 cert, err := NewDebitCert(draftid, draft)
363 r, signed, err := document.Format(cert, sk)
364 certid := document.Id(signed)
365 err = db.Set("cert", certid, r)
370 err = db.Set("certby/draft", draftid, []byte(certid))
375 err = db.Set("certby/key", cert.Holder, []byte(certid))
381 err = db.Set("certby/key.serial", fmt.Sprintf("%s.%09d", cert.Holder, cert.Serial), []byte(certid))
389 func EvalDebitCert(d []byte, sk *openpgp.Entity) (r []byte, err error) {
390 dcert, dcertid, err := ParseDebitCert(d)
394 r, err = CertByDebitCert(dcertid)
399 // TODO: we only need the draft to know the issuer (+beneficiary)
400 // it should be in the pubkey
401 d, err = db.Get("draft", dcert.Draft)
406 iv, _, err := document.Parse(d)
411 draft, ok := iv.(*document.Draft)
414 err = fmt.Errorf("EvalDebitCert: expected draft from internal db")
419 // TODO: check pubkey etc
420 cert, err := NewCreditCert(dcert.Draft, draft, dcertid, dcert)
425 r, signed, err := document.Format(cert, sk)
430 certid := document.Id(signed)
431 err = db.Set("cert", certid, r)
436 err = db.Set("certby/debit", dcertid, []byte(certid))
441 err = db.Set("certby/key", cert.Holder, []byte(certid))
447 err = db.Set("certby/key.serial", fmt.Sprintf("%s.%09d", cert.Holder, cert.Serial), []byte(certid))
455 func Init(rootdir string) (err error) {
456 db, err = store.Open(rootdir)
460 err = db.Ensure("key")
464 err = db.Ensure("cert")
468 err = db.Ensure("draft")
472 err = db.Ensure("certby/draft")
476 err = db.Ensure("certby/debit")
480 err = db.Ensure("certby/key")
484 err = db.Ensure("certby/key.serial")
488 err = db.Ensure("draftby/key.nonce")
492 err = db.Ensure("keysby/64")
496 err = db.Ensure("keysby/32")