-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathopencoin-v3.txt
637 lines (493 loc) · 21.8 KB
/
opencoin-v3.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
OpenCoin Project http://opencoin.org/ Category: Draft
OPENCOIN V3 PROTOCOL DRAFT 0.1a
Status of this Memo
===================
This draft is work in heavy progress. Do not consider it's content
stable in any sense as long as this note is present. Get in touch with
opencoin.org [1] and fetch a recent copy [TBD].
Copyright Notice
Copyright (2012) N. Toedtmann, J. H. Baach, J. K. Muennich, J. Suhr.
Abstract
========
This document describes the OpenCoin protocol which seeks to implement
David Chaum's concept of digital cash [3].
Table of Contents
1. Introduction
===============
1.1 Entities
------------
Opencoin consists of the following entities:
* _Currency_ is defined by an issuer and it can be used for various
use cases (e.g. digital cash, balloting, vouchers)
* _Issuer_ defines a currency and provides the following
services/data:
* _Certificate Authority (CA)_: masterkey, CDD ("currency description
document")
* _Mint_ is a service which signs blinded payload hashes and creates
blinded signatures
* _Double Spending Data Base (DSDB)_ stores the serials (and
potentially signatures) of all renewed coins in order to
prevent its double spending. WHO IS QUERING THE DSDB? THE
MINT, SERVICE OR AUTHORIZER?
* Issuer services are:
* _Information_ provides information of the issuer and
currency (e.g. CDDs, mint key certificates, certificate
revocation list (CRL))
* _Validate_ is used by clients to request coins without
having coins already. Usually the validate service may ask
the Authorizer whether to approve or reject particular
requests. This service is usually used to convert value of
another payment system to opencoin.
* _Renew_ is used by clients to renew existing coins. The
client needs to provide valid coins and blinds of the same
total value. The Renew service validates against the DSDB
and in the valid case mints the provided blinds. Usually
clients who received coins during a transaction are
supposed to call this service to ensure the received coins
are valid (and not spend before).
* _Invalidate_ converts valid coins into a different payment
system.
* _Authorizer_ verifies validation requests and responds to the
mint with an authorization or rejection. This component may
interface with other payment/account systems in order to
convert value from another payment system to the particular
currency.
* _Client_ is the application of a user which interacts with the
other entities. It manages the wallet.
* _Tokens_ are payloads, blinds, and coins. Their lifecycle is:
* Client: creates yet unsigned payload ("blank")
* Client: ==[padded hash]==> payload hash
* Client: ==[blind]==> blinded payload hash ("blind")
* Mint: ==[sign]==> signature of blinded payload hash
a.k.a blind signature of payload hash
a.k.a ("blind signature")
* Client: ==[unblind]==> signature of payload hash
* Client: ==[combine with unsigned payload]==> signed payload
a.k.a. "coin"
* _Payload_ is prepared by the client (and while it doesn't have a
signature it's called "blank")
* Blind is the blinded padded hash of a payload. It is send from
the client to the mint.
* Coin consists of a payload and the mint's signature of the
particular payload.
* Wallet is a file which contains tokens (e.g. coins) and is managed
by the client.
2. The OpenCoin protocol
========================
2.1 Containers
--------------
2.1.1 Generic format:
struct <name> = {
type: '<type name>',
<type-dependent field> [, <type-dependent field>[...]]
}
2.1.2 General Conditions
Limits:
The following limits are defined to allow clients handling data more easily.
* Maximum list length = 2^16 entries. Lists are not sorted unless
mentioned explicitly. It is used for denominations and service URLs for instance.
* signed (?) integers (weights, denomination, display factor) =
4 bytes (32 bit)
* String length = 2^16 bytes
* Date: UTC
Encodings:
* date: ISO8601, extended format, always UTC,
e.g. 2009-01-01T12:00:00Z
* URL
* Integer?
* crypto_random_number: 128 bit, high entropy random number
Container signing:
* signature = sign(padded_hash(bencode_serialized(container)))
signed_container = {type:<type>,
<attribute_name>:container,
'signature':signature}
Rules:
* UTF-8 encoding. Tokens and gwop are additionally base64 encoded
(RFC 4648).
* exact all fields are required but some may be empty if mentioned
in the spec. All field names are unique [[we don't want double
fields, or unlimited additional fields. People who want to "abuse"
the CDD should use additional info field]]
2.1.2 The currency description document (CDD)
For simplicity reasons, the terminology defines a CDD as containing a
signature/certificate.
struct: CDD
* struct: signed data
* type = 'cdd'
* protocol version = URL:http://opencoin.org/OpenCoinProtocol/1.0
[[An URL to the protocol standard being used for the coin.]]
* cdd location = URL: http://opencent.net/OpenCent )
[[This is not an identifier. This URL is required to be
embedded in payloads. DOES IT NEED TO BE UNIQUE FOR EACH CDD
AND VERSION?]]
* cdd serial number = positive integer, incremental [[Purpose is
to distinguish different versions of a CDD]]
* cdd signing date = date
* cdd expiry date = date or None [[we want to allow a controlled
rollover, temporary systems. This is the expiry date of the
CDD.]]
* currency name = string: [[e.g. Open Cent]]
* currency divisor = positive integer
[[value/display divisor == display value in unit display name;
For instance a divisor of 100 to express cent values for Euro
or Dollar ]]
* info service = weighted_list_of_URLs
* CDDs
* mint key certificates
* certificate revocation list (CRL)
* icons and other funky shiny stuff
* [[Weighted to also allows round-robin, but also proper preference]]
* validation service = weighted_list_of_URLs:
[(10, https://validate.opencent.net:8002),
(1, xmpp://1.2.3.4/opencoin) ]
* renewal service = weighted_list_of_URLs
* invalidation service = weighted_list_of_URLs
* denominations = list_of_integers: 1, 2, 5, 10, 20, 50, 100,
200, 500, 1000 [[negative denominations may be allowed but
clients may not be able to handle it and reject currency]]
* issuer cipher suite = string: HASH-SIGN-BLINDING
* example: SHA512-RSA-CHAUM83
* issuer public master key = JSON dict construct, depending on
used crypto algorithm. 7bit_serialize(sign-key: pM))
* [[it seems that the only valid identifier of the currency is
the master key. A shorter hash of this key may be displayed to
allow its manual verification by users. This key MUST be
changed if hash or signing algorithm changes.]]
* additional info = string or None [[there might be additions]]
* 7bit_serialize(sign(sM,hash(serialize(signed data))))
A complete CDD serialized into json may look like this:
{'type' : 'cdd',
'protocol_version' : 'http://opencoin.org/OpenCoinProtocol/1.0',
'cdd_location' : 'http://opencent.net/OpenCent',
'issuer_public_master_key' : 'fdslllfdsajfd9s9ekfjlfsdajlkjfds',
'issuer_cipher_suite' : 'SHA512-RSA-CHAUM83',
'cdd_serial' : 1,
'cdd_signing_date' : '2012-06-01T18:30',
'cdd_expiry_date' : '2012-06-01T18:30',
'currency_name' : 'My Currency',
'currency_divisor' : 100,
'info_service' : [[30,'http://some.server'],
[10,'xmpp://info@some.server']],
'validation_service' : [[10,'http://some.server'],
[10,'xmpp://info@some.server']],
'renewal_service' : [[20,'http://other.server']],
'invalidation_service' : [[20,'http://some.server']],
'denominations' : [1,2,5,10],
'additional_info' : 'happy day'}
structure of cdd with signature:
{'type': 'cdd certificate',
'cdd': cdd,
'signature' : signature(cdd)}
2.1.3 The minting keys
For simplicity reasons, the terminology defines a mint key as containing
a signature/certificate.
struct: mint key = {
type = 'mint key'
id = base64(hash(public mint key)) [[MUST be verified when
receiving a mint_key. Why? Isn't the signature sufficient ?]]
issuer_id = base64(hash(public master key))
cdd_serial = integer [[Allows unique relation to CDD
version but may be ignored by clients for
now.]]
public_mint_key = JSON dict construct, depending on used crypto
algorithm. base64(public mint key)
denomination = integer [[The actual denomination is calculated
by dividing this denomination with the
currency_divisor of the CDD.]]
sign_coins_not_before = DATE TIME
sign_coins_not_after = DATE TIME
coins_expiry_date = DATE TIME
}
struct: mint key certificate {
type = 'mint key certificate'
mint_key = mint key,
signature = base64(signature) The mint key is signed with the issuer
master key.
}
Public Key
This struct is used for public RSA keys used within CDDs and mint keys.
public key = {
modulus = Base64
public_exponent = Base64
}
2.1.4 tokens
struct: payload {
type = 'payload'
protocol_version = http://opencoin.org/OpenCoinProtocol/1.0
issuer_id = base64(hash(public master key))
cdd_location = http://opencent.net/OpenCent [[Hint to
download the CDD if not available anyway.
Useful for clients to "bootstrap" a yet
unknown currency.]]
denomination = integer [[Only a hint, not verified value.
Denomination MUST be verified by checking the
mint key's denomination.]]
mint_key_id = base64(hash(public mint key)) [[The hex encoded
SHA-256 hash of the issuer's public key. It may
differ depending on denomination, validity
period and currency.]]
serial = base64(128bit random number) [[This random
value is generated by clients. It is used to
identify coins and prevent double spending. Once
the coin is spent, the serial will be stored
in the issuer's DSDB. Because of its sufficient
long length it is supposed to be unique for each
coin. A high entropy (crypto grade quality) is
important.]]
}
struct: blind = {
type = 'blinded payload hash'
reference = integer [[To be chosen by client in order to reference
between blinded payload and blind signature. Can be
random or incremental but should be unique within one gwop.
MUST NOT be derived from serial number or blinded factor.]]
blinded_payload_hash = base64(blind(prepare_signing(hash(serialize(payload)))))
RSA_blind(BigInt(hash(serialize(payload))))
ECC_blind(ECC_Point(hash(serialize(payload))))
mint_key_id = base64(hash(public mint key)) [[The client should
select a random mint key (for the appropriate
denomination) to prevent the issuer from smuggling in
tracking information by using a particular key.]]
}
struct: blind signature = {
type = 'blind signature'
reference = integer
blind_signature = base64(signature(base64_decode(blinded_payload_hash)))
}
struct: coin = {
type = 'coin',
payload = payload,
signature = base64(unblind(base64decode(blind_signature))) [[A hex encoded RSA
signature from the issuer (it's private key) over the SHA-256 hash
of the payload.]]
}
2.2.1 Message Types
struct: request_cdd_serial {
type: 'request cdd serial' [[Request the serial of latest CDD]]
message_reference: integer,
}
struct: response_cdd_serial {
type: 'response cdd serial'
message_reference: integer,
status_code: integer,
status_description: string,
cdd_serial: integer
}
struct: request_cdd {
type: 'request cdd',
message_reference: integer,
cdd_serial: integer [[not null to fetch specific cdd version]]
}
struct: response_cdd {
type: 'response cdd',
message_reference: integer,
status_code: integer,
status_description: string,
cdd: cdd
}
struct: request_mint_keys{
type: 'request mint keys',
message_reference: integer,
mint_key_ids: [mint_key_id,mint_key_id], //for specific keys
denominations:[d,d,d] //for most recent version
[[If both fields are empty, all latest mint keys will be responded.
If both are provided, all current keys for the particular
denominations as well as the mint keys with the specific ID will
be provided.]]
}
struct: response_mint_keys{
type: 'response mint keys',
message_reference: integer,
status_code: integer,
status_description: string,
keys: [mint_key_certificate,mint_key_certificate]
}
struct: request_validation {
type: 'request validation',
message_reference: integer,
transaction_reference: crypto_random_number,
authorization_info: string,
blinds: [n blinds]
}
struct: request_renewal {
type: 'request renewal',
message_reference: integer,
transaction_reference: crypto_random_number,
coins: [n coins],
blinds: [n blinds]
}
struct: response_minting {
type: 'response minting',
message_reference: integer,
status_code: integer,
status_description: string,
retry_after: DATETIME [[not empty if status 3XX / timestamp instead
of for asynchronous communication]]
blind_signatures: [blind_signature,...] [[not empty if status 2XX]]
}
struct: request_resume {
type: 'request resume',
message_reference: integer,
transaction_reference: crypto_random_number
}
struct: request_invalidation {
type: 'request invalidation',
message_reference: integer,
authorization_info: string,
coins: [n coins]
}
struct: response_invalidation {
type: 'response invalidation'
message_reference: integer,
status_code: integer,
status_description: string
}
struct: send_coins {
type: 'send coins',
message_reference: integer, [[Message ID to allow a reference of
response message.]]
subject: string, [[Information for recipient]]
coins: [n coins]
}
struct: received_coins {
type: 'received coins',
message_reference: integer,
status_code: integer,
status_description: string
}
Mandatory: Container encryption DRAFT
SHOULD WE INCLUDE A NONCE RESP. ITS RESPONSE IN ORDER TO PREVENT REPLAY
ATTACKS?
struct encrypted {
type: 'encrypted', [[encypt + sign]]
reference: string,
cipher: 'aes',
data: crypt(container)
}
There are RFC drafts with the same goal. These might be worth
considering:
* https://tools.ietf.org/html/draft-jones-json-web-signature-04
* https://tools.ietf.org/html/draft-ietf-jose-json-web-encryption-05
* https://tools.ietf.org/html/draft-rescorla-jsms-00
* https://tools.ietf.org/html/draft-jones-json-web-encryption-json-serialization-02
* OCSP/CRL of mint key certificates. Should be empty in normal case.
* wallet
* Glue certificates
ERROR CODES:
2XX SUCCESS
3XX DELAY / TEMPORARY ERROR
4XX PERMANENT ERROR
2.3.1 Order of actions/messages
* Alice should fetch and verify CDD [revocation check of master key]
* Alice should fetch and verify current Mintkeys [revocation check]
* Alice creates new payloads ("blanks")
* Alice requests validation [authorization might happen here]
* Mint responds with signatures [or delay]
* Alice unblinds and verifies signatures
* Alice attaches signatures to payloads (results in coins)
* Alice sends coins to Bob
* (Bob might respond "received" to Alice. Trusted case.)
* If not cached, Bob fetches and verify CDD. [revocation check of
master key]
* Bob selects preferred denominations for new coins.
* Bob should fetch and verify mint key certificates associated with
selected denominations and received coins, if not cached.
[revocation check] To mitigate traffic analysis, client may want
to fetch more keys than required.
* Bob verifies coins using mint key
* Bob creates new payloads
* Bob requests renewal
* Mint signs blinds
* Mint writes old coins in dsdb
* Instant response:
* Mint responds with signatures
* Bob unblinds and verifies signatures
* Bob attaches signatures to payloads (->coins)
* (Bob might respond OK to Alice)
* Delayed response:
* Mint responds with 'delayed'
* (Bob might respond OK to Alice)
* Bob requests resume
* Mint responds with signatures
* Bob unblinds and verifies signatures
* Bob attaches signatures to payloads (->coins)
* (Bob might respond OK to Alice)
* Bob requests invalidate (with authorizer or payment (?) message)
* Issuer stores old coins in dsdb
* Issuer responds with OK (and does whatever is required)
Actions
* get cdd -> cdd certificate
* get mintkey -> mint key certificates
* get crl/ocsp
* validate: (blinds, + authorizer information) -> delayed/(blind
signatures)
* renew: (blinds, coins) -> delayed/(blind signatures)
* invalidate (coins, + authorizer information)
* resume: transactionid -> delayed / (blind signatures)
* transaction: (coins A, coins B + optional cdd, messagestring)
Potential extensions:
* Mandatory: Fees
* Payment requests
* "Internet ATM"
* escrow (trusted third party) (fair exchanges without third party)
* currency exchanges
* receipts
Services
* info service = weighted_list_of_URLs
* CDDs
* mint key certificates
* certificate revocation list (CRL)
* fees: A list of fees e.g. {[1-1000, 2, 'coin'],[>1000, 1,
'percent']}
* icons and other funky shiny stuff
* [[Weighted to also allows round-robin, but also proper
preference]]
* validation service = weighted_list_of_URLs:
[(10, https://validate.opencent.net:8002),
(1, xmpp://1.2.3.4/opencoin)]
* renewal service = weighted_list_of_URLs
* invalidation service = weighted_list_of_URLs
Amendment
SHA512-RSA-CHAUM83:
* hash: sha512
* padding: ??
* public key = (bigint: e, bigint: n)
* 7 bit serialization: HAS TO BE DEFINED
* Examples:
* base64(json(list(bigint:e, bigint:n)))
* json(list(base64(bigint:e),base64(bigint:n)))
* signature = bigint
* 7 bit serialization: HAS TO BE DEFINED
* prepare_signing()
SHA512-ECC-XYZ
* ECC public key = (5 koordinaten, elements of a binary field)
* ECC signature = (tupel of field elements)
Open Questions:
* Should the Public Key structure contain the cipher suite or should
the cipher suite remain defined outside, next to the public key?
* Self referencing field names: Change name of cdd_location,
cdd_serial, cdd_signing_date, cdd_expiry_date and remove the
"cdd_" from their names?
* Should we allow negative denominations? -> JS: For the issuer
implementation I assume "no".
* Master key rollover. Following options:
* "Rollover" records in old CDD
* (rollover CDD info service = weighted_list_of_URLs
* rollover CDD cipher suite = string
* rollover CDD public master key = )
* 2nd signature (by old masterkey) in new CDD
* Glue certificates
* Protocol rollover?
* Move cdd_location from token to gwop?
* Alice marks token for bob
* How often should the CDD be fetched? Is this security related?
* OCSP or CRL? CRL may be cheaper.
* should the issuer enforce the order in which renewal requests are processed (order or
requests = order of responses) regarding competing requests containing same coins
* Shall the "hold-back time" be mentioned into the CDD
* Does the client need the option to say "Do *not* send me a DELAY"?
References
==========
[1] The OpenCoin project <http://opencoin.org/>
[2] David Chaum, "Blind signatures for untraceable payments", Advances in Cryptology - Crypto '82,
Springer-Verlag (1983), 199-203.