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)
247 // TODO: sanity checks? oldcert.Holder == draft.Drawer
248 cert.Serial = oldcert.Serial + 1
249 cert.Balance = oldcert.Balance + cert.Difference
250 if cert.Balance <= -IntLimit {
251 return nil, fmt.Errorf("balance limit exceeded: %d", cert.Balance)
253 if oldcert.Balance > 0 && cert.Balance < 0 {
254 return nil, fmt.Errorf("insufficient funds: %d", oldcert.Balance)
256 cert.LastDebitSerial = oldcert.LastDebitSerial
257 cert.LastCreditSerial = oldcert.LastCreditSerial
259 cert.LastDebitSerial = oldcert.Serial
261 cert.LastCreditSerial = oldcert.Serial
263 cert.LastCert = &oldcertid
268 func NewCreditCert(draftid string, draft *document.Draft, dcertid string, dcert *document.DebitCert) (*document.CreditCert, error) {
269 cert := new(document.CreditCert)
270 // TODO: get from old cert instead?
271 cert.Holder = dcert.Beneficiary
272 cert.Date = time.Seconds()
273 // TODO: get these from the cert holder pubkey
274 cert.Denomination = "epoint"
275 cert.Issuer = draft.Issuer
276 cert.AuthorizedBy = dcert.AuthorizedBy // TODO: draft vs dcert vs serverside decision
277 cert.Difference = -dcert.Difference
279 cert.Drawer = dcert.Holder
280 cert.DebitCert = dcertid
282 oid, err := db.Get("certby/key", dcert.Beneficiary)
283 oldcertid := string(oid)
285 // this is the first cert
287 cert.Balance = cert.Difference
288 cert.LastDebitSerial = 0
289 cert.LastCreditSerial = 0
291 d, err := db.Get("cert", oldcertid)
296 iv, _, err := document.Parse(d)
301 // TODO: this is a hack
302 oldcert, err := document.ToCert(iv)
307 cert.Serial = oldcert.Serial + 1
308 cert.Balance = oldcert.Balance + cert.Difference
309 if cert.Balance >= IntLimit {
310 return nil, fmt.Errorf("balance limit exceeded: %d", cert.Balance)
312 cert.LastDebitSerial = oldcert.LastDebitSerial
313 cert.LastCreditSerial = oldcert.LastCreditSerial
315 cert.LastDebitSerial = oldcert.Serial
317 cert.LastCreditSerial = oldcert.Serial
319 cert.LastCert = &oldcertid
324 func EvalDraft(d []byte, sk *openpgp.Entity) (r []byte, err error) {
325 draft, draftid, err := ParseDraft(d)
329 _, err = db.Get("draft", draftid)
332 // TODO: certby/draft might not be ready even if draft is there
333 return CertByDraft(draftid)
335 // if draft is ok we save it
336 err = db.Set("draft", draftid, d)
341 // TODO: db.Insert: fails if key exists
342 s := fmt.Sprintf("%s.%s", draft.Drawer, draft.Nonce)
343 _, err = db.Get("draftby/key.nonce", s)
345 err = fmt.Errorf("draft nonce is not unique")
348 err = db.Set("draftby/key.nonce", s, d)
355 cert, err := NewDebitCert(draftid, draft)
359 r, signed, err := document.Format(cert, sk)
360 certid := document.Id(signed)
361 err = db.Set("cert", certid, r)
366 err = db.Set("certby/draft", draftid, []byte(certid))
371 err = db.Set("certby/key", cert.Holder, []byte(certid))
377 err = db.Set("certby/key.serial", fmt.Sprintf("%s.%09d", cert.Holder, cert.Serial), []byte(certid))
385 func EvalDebitCert(d []byte, sk *openpgp.Entity) (r []byte, err error) {
386 dcert, dcertid, err := ParseDebitCert(d)
390 r, err = CertByDebitCert(dcertid)
395 // TODO: we only need the draft to know the issuer (+beneficiary)
396 // it should be in the pubkey
397 d, err = db.Get("draft", dcert.Draft)
402 iv, _, err := document.Parse(d)
407 draft, ok := iv.(*document.Draft)
410 err = fmt.Errorf("EvalDebitCert: expected draft from internal db")
415 // TODO: check pubkey etc
416 cert, err := NewCreditCert(dcert.Draft, draft, dcertid, dcert)
421 r, signed, err := document.Format(cert, sk)
426 certid := document.Id(signed)
427 err = db.Set("cert", certid, r)
432 err = db.Set("certby/debit", dcertid, []byte(certid))
437 err = db.Set("certby/key", cert.Holder, []byte(certid))
443 err = db.Set("certby/key.serial", fmt.Sprintf("%s.%09d", cert.Holder, cert.Serial), []byte(certid))
451 func Init(rootdir string) (err error) {
452 db, err = store.Open(rootdir)
456 err = db.Ensure("key")
460 err = db.Ensure("cert")
464 err = db.Ensure("draft")
468 err = db.Ensure("certby/draft")
472 err = db.Ensure("certby/debit")
476 err = db.Ensure("certby/key")
480 err = db.Ensure("certby/key.serial")
484 err = db.Ensure("draftby/key.nonce")
488 err = db.Ensure("keysby/64")
492 err = db.Ensure("keysby/32")