Compare commits
108 Commits
8684a9bfea
...
8cbe16a220
Author | SHA1 | Date | |
---|---|---|---|
|
8cbe16a220 | ||
|
133cf76f0d | ||
|
7eb989b2df | ||
|
17a30cbd70 | ||
|
e27ff05e63 | ||
|
a8b683fe3f | ||
|
b79457cec6 | ||
|
a5b8244948 | ||
|
271711ae64 | ||
|
ca7fa98016 | ||
|
e35e89f14d | ||
|
b84fb618c3 | ||
|
169d684342 | ||
|
b2e6fcae1a | ||
|
b9ea075d61 | ||
|
c7c0beedd5 | ||
|
fb9ba5b1d2 | ||
|
0d03f55282 | ||
|
d850ed9ca1 | ||
|
adeca20fe2 | ||
|
f7a1f41eee | ||
|
3ed39955b6 | ||
|
031e365814 | ||
|
2164c36f0f | ||
|
4a575f5044 | ||
|
5ff3189075 | ||
|
62d8368b1b | ||
|
66abbcac3f | ||
|
e735475623 | ||
|
f173296c3c | ||
|
57bbdb0997 | ||
|
cfa1283053 | ||
|
34a7f59060 | ||
|
9fc3b7a278 | ||
|
b280b1db04 | ||
|
251f2b5987 | ||
|
5a47863caf | ||
|
718ad3996f | ||
|
e8740316a7 | ||
|
41d132757b | ||
|
63da97630d | ||
|
f46dc9ea5e | ||
|
c42376cf40 | ||
|
aea7fc36c3 | ||
|
d81a6c7cf2 | ||
|
41acdf11b8 | ||
|
b30765c7d0 | ||
|
cfc6c3fcd0 | ||
|
d833966d52 | ||
|
bd5a25aff2 | ||
|
57dc3cd232 | ||
|
ed136c1f2d | ||
|
30c92a9b9e | ||
|
752c0aca43 | ||
|
37f54d3e5d | ||
|
03fd154a69 | ||
|
7d2a1a596a | ||
|
9d40bd5a1e | ||
|
a67786078b | ||
|
8674f32aec | ||
|
086cf05794 | ||
|
2213012866 | ||
|
be50c084f8 | ||
|
ae5f082c75 | ||
|
bcc159de17 | ||
|
3510f953b0 | ||
|
8d85c8b5b6 | ||
|
ea97729ba8 | ||
|
74ce114b83 | ||
|
5b7e8f9ac5 | ||
|
daa7fdcfb1 | ||
|
9c2aefaa51 | ||
|
9074e66ebc | ||
|
4c7aa09784 | ||
|
2d70c8c6d0 | ||
|
82405b0ce5 | ||
|
36f551ff33 | ||
|
106664ed0c | ||
|
875a8b397e | ||
|
d1fd3a485b | ||
|
9d9d4413df | ||
|
18db69be2d | ||
|
f239b01be1 | ||
|
fbb6d03f69 | ||
|
75eff1524a | ||
|
cf4fd36cc4 | ||
|
4bcbd704df | ||
|
ca247f6f58 | ||
|
3225566c93 | ||
|
db9b84970d | ||
|
5d2157a8f6 | ||
|
f1ec1e70a0 | ||
|
a02ab8f81b | ||
|
385eb51e93 | ||
|
f3fb7c29e6 | ||
|
0a459aeb13 | ||
|
9780625e09 | ||
|
dbaf21c215 | ||
|
71de8b1663 | ||
|
bde9bdb38d | ||
|
f7162e756c | ||
|
a0dd2de662 | ||
|
fc397f2634 | ||
|
5ea4e5b122 | ||
|
649c6b6f72 | ||
|
88f64e238c | ||
e6e0cabf08 | |||
32f1276b8c |
18
.gitignore
vendored
18
.gitignore
vendored
@ -5,6 +5,8 @@
|
||||
*.gcno
|
||||
*.gcda
|
||||
*.mo
|
||||
*.blg
|
||||
*.bbl
|
||||
.dirstamp
|
||||
m4/*.m4
|
||||
doc/coverage/
|
||||
@ -34,7 +36,8 @@ GRTAGS
|
||||
GTAGS
|
||||
*.swp
|
||||
src/include/taler_error_codes.h
|
||||
src/lib/test_exchange_api
|
||||
src/testing/test_exchange_api_rsa
|
||||
src/testing/test_exchange_api_cs
|
||||
doc/doxygen/doxygen_sqlite3.db
|
||||
src/auditor/taler-auditor-dbinit
|
||||
src/auditor/taler-auditor-sign
|
||||
@ -71,6 +74,9 @@ src/exchange-tools/taler-wire
|
||||
src/exchangedb/perf-exchangedb
|
||||
src/benchmark/taler-exchange-benchmark
|
||||
src/benchmark/auditor.in
|
||||
src/benchmark/exchange_benchmark_home/.local/share/taler/exchange-offline/
|
||||
src/benchmark/exchange_benchmark_home/.local/share/taler/exchange-secmod-eddsa/
|
||||
src/benchmark/exchange_benchmark_home/.local/share/taler/exchange-secmod-rsa/
|
||||
src/benchmark/exchange_benchmark_home/.local/share/taler/exchange/live-keys/*
|
||||
src/benchmark/exchange_benchmark_home/.local/share/taler/auditors/
|
||||
src/benchmark/exchange_benchmark_home/.local/share/taler/auditor/
|
||||
@ -110,9 +116,11 @@ doc/manual/manual.vr
|
||||
doc/prebuilt/*
|
||||
contrib/taler-exchange.tag
|
||||
doxygen-doc/
|
||||
src/testing/test_exchange_api_keys_cherry_picking
|
||||
src/testing/test_exchange_api_keys_cherry_picking_cs
|
||||
src/testing/test_exchange_api_keys_cherry_picking_rsa
|
||||
src/auditor/taler-auditor-sync
|
||||
src/auditor/taler-wire-auditor
|
||||
src/auditor/generate_auditordb_home/
|
||||
contrib/auditor-report.aux
|
||||
contrib/auditor-report.log
|
||||
contrib/auditor-report.tex
|
||||
@ -120,8 +128,10 @@ contrib/auditor-report.pdf
|
||||
src/bank-lib/taler-bank-transfer
|
||||
src/bank-lib/test_bank_api_twisted
|
||||
src/testing/test_exchange_api
|
||||
src/testing/test_auditor_api
|
||||
src/testing/test_exchange_api_overlapping_keys_bug
|
||||
src/testing/test_auditor_api_cs
|
||||
src/testing/test_auditor_api_rsa
|
||||
src/testing/test_exchange_api_overlapping_keys_bug_cs
|
||||
src/testing/test_exchange_api_overlapping_keys_bug_rsa
|
||||
src/testing/test_exchange_api_home/.local/share/taler/exchange/revocations/
|
||||
src/wire-plugins/test_wire_plugin_legacy_taler_bank
|
||||
uncrustify.cfg
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit b0dd85e8187f33a1f92dd5eb31082050d333e168
|
||||
Subproject commit c12314df0f82e192c6829a9c6cf3e9663b586da1
|
1375
doc/cbdc-it/agsm-mod.bst
Normal file
1375
doc/cbdc-it/agsm-mod.bst
Normal file
File diff suppressed because it is too large
Load Diff
561
doc/cbdc-it/cbdc-it.bib
Normal file
561
doc/cbdc-it/cbdc-it.bib
Normal file
@ -0,0 +1,561 @@
|
||||
%% To be used with modified bibliography style agsm-mod + hyperref + natbib + italian babel
|
||||
|
||||
@article{Adrian,
|
||||
author = {Adrian, Tobias and Mancini-Griffoli},
|
||||
year = {2019},
|
||||
title = {{The Rise of Digital Money}},
|
||||
journal = {IMF Fintech Note},
|
||||
volume = {19/01},
|
||||
}
|
||||
|
||||
@article{Agarwal,
|
||||
author = {Agarwal, Ruchir and Miles S. Kimball},
|
||||
year = {2019},
|
||||
title = {{Enabling Deep Negative Rates to Fight Recessions: A Guide}},
|
||||
journal = {IMF Working Paper},
|
||||
volume = {19/84},
|
||||
}
|
||||
|
||||
|
||||
@article{Agur,
|
||||
author = {Agur, Itai and Anil Ari and Giovanni Dell'Ariccia},
|
||||
year = {2019},
|
||||
title = {{Designing Central Bank Digital Currencies}},
|
||||
journal = {IMF Working Paper},
|
||||
volume = {19/252},
|
||||
}
|
||||
|
||||
@article{Allen,
|
||||
author = {Allen, Sarah and Srđjan Čapkun and Ittay Eyal and Giulia Fanti and Bryan A. Ford and James Grimmelmann and Ari Juels and Kari Kostiainen and Sarah Meiklejohn and Andrew Miller and Eswar Prasad and Karl Wüst and Fan Zhang},
|
||||
year = {2020},
|
||||
title = {{Design Choices for Central Bank Digital Currency: Policy and Technical Considerations}},
|
||||
journal = {NBER Working Paper},
|
||||
volume = {27634},
|
||||
}
|
||||
|
||||
@article{Alves,
|
||||
author = {Alves, Tiago and Don Felton},
|
||||
year = {2004},
|
||||
title = {TrustZone: Integrated hardware and software security},
|
||||
journal = {ARM IQ},
|
||||
volume = {3},
|
||||
number = {4},
|
||||
pages = {18--24},
|
||||
}
|
||||
|
||||
@article{AuerBoehme,
|
||||
author = {Auer, Raphael and Rainer Böhme},
|
||||
year = {2020},
|
||||
title = {The technology of retail central bank digital currency},
|
||||
journal = {BIS Quarterly Review},
|
||||
month = {March},
|
||||
pages = {85--96},
|
||||
}
|
||||
|
||||
@article{AuerCornelli,
|
||||
author = {Auer, Raphael and Giulio Cornelli and Jon Frost},
|
||||
year = {2020},
|
||||
title = {{Taking stock: ongoing retail CBDC projects}},
|
||||
journal = {BIS Quarterly Review},
|
||||
month = {March},
|
||||
pages = {97--98},
|
||||
}
|
||||
|
||||
@booklet{BIS,
|
||||
author = {{Bank for International Settlements}},
|
||||
year = {2018},
|
||||
title = {{Central Bank Digital Currencies. Joint Report of the Committee on Payments and Market Infrastructures and Markets Committee}},
|
||||
}
|
||||
|
||||
@booklet{BoE,
|
||||
author = {{Bank of England}},
|
||||
year = {2020},
|
||||
title = {{Central Bank Digital Currency: Opportunities, Challenges and Design. Discussion Paper}},
|
||||
month = {March},
|
||||
}
|
||||
|
||||
@article{Baiocchi,
|
||||
author = {Baiocchi, Giovanni and Walter Distaso},
|
||||
year = {2003},
|
||||
title = {{GRETL: Econometric Software for the GNU Generation}},
|
||||
journal = {Journal of Applied Econometrics},
|
||||
volume = {18},
|
||||
pages = {105-110},
|
||||
}
|
||||
|
||||
@article{Bech,
|
||||
author = {Bech, Morten and Rodney Garratt},
|
||||
year = {2017},
|
||||
title = {Central bank cryptocurrencies},
|
||||
journal = {BIS Quarterly Review},
|
||||
month = {September},
|
||||
pages = {55--70},
|
||||
}
|
||||
|
||||
@article{Berentsen,
|
||||
author = {Berentsen, Aleksander and Fabian Schär},
|
||||
year = {2018},
|
||||
title = {{The Case for Central Bank Electronic Money and the Non-case for Central Bank Cryptocurrencies}},
|
||||
journal = {Federal Reserve Bank of St. Louis Review},
|
||||
volume = {100},
|
||||
number = {2},
|
||||
pages = {97--106},
|
||||
}
|
||||
|
||||
@article{Bernstein2020,
|
||||
author = {Bernstein, Daniel J. and Tanja Lange},
|
||||
year = {2020},
|
||||
title = {{eBACS: ECRYPT Benchmarking of Cryptographic Systems}},
|
||||
url = {\url{https://bench.cr.yp.to}, consultato il 17 marzo 2020},
|
||||
}
|
||||
|
||||
@article{Bernstein2012,
|
||||
author = {Bernstein, Daniel J. and Niels Duif and Tanja Lange and Peter Schwabe and Bo-Yin Yang},
|
||||
year = {2012},
|
||||
title = {High-speed high-security signatures},
|
||||
journal = {Journal of Cryptographic Engineering},
|
||||
volume = {2},
|
||||
pages = {77--89},
|
||||
}
|
||||
|
||||
@InCollection{Bindseil,
|
||||
author = {Bindseil, Ulrich},
|
||||
year = {2020},
|
||||
title = {{Tiered CBDC and the financial system}},
|
||||
publisher = {European Central Bank},
|
||||
series = {ECB Working Paper},
|
||||
number = {2351},
|
||||
month = {January},
|
||||
}
|
||||
|
||||
@article{Boar,
|
||||
author = {Boar, Codruta and Henry Holden and Amber Wadsworth},
|
||||
year = {2020},
|
||||
title = {Impending arrival - a sequel to the survey on central bank digital currency},
|
||||
journal = {BIS Papers},
|
||||
volume = {107},
|
||||
}
|
||||
|
||||
@article{Boneh,
|
||||
author = {Boneh, Dan},
|
||||
year = {1999},
|
||||
title = {{Twenty Years of Attacks on the RSA Cryptosystem}},
|
||||
journal = {Notices of the AMS},
|
||||
volume = {42},
|
||||
number = {2},
|
||||
pages = {202--213},
|
||||
}
|
||||
|
||||
@InCollection{Bordo,
|
||||
author = {Bordo, Michael D. and Andrew T. Levin},
|
||||
year = {2017},
|
||||
title = {Central bank digital currency and the future of monetary policy},
|
||||
publisher = {National Bureau of Economic Research},
|
||||
series = {NBER Working Paper Series},
|
||||
number = {23711},
|
||||
}
|
||||
|
||||
@article{Brunnermeier,
|
||||
author = {Brunnermeier, Markus and Dirk Niepelt},
|
||||
year = {2019},
|
||||
title = {{On the Equivalence of Private and Public Money}},
|
||||
journal = {Journal of Monetary Economics},
|
||||
volume = {106},
|
||||
pages = {27--41},
|
||||
}
|
||||
|
||||
@article{Buiter,
|
||||
author = {Buiter, Willem H. and Nikolaos Panigirtzoglou},
|
||||
year = {2003},
|
||||
title = {{Overcoming the Zero Bound on Nominal Interest Rates with Negative Interest on Currency: Gesell's Solution}},
|
||||
journal = {The Economic Journal},
|
||||
volume = {113},
|
||||
number = {490},
|
||||
pages = {723--746},
|
||||
}
|
||||
|
||||
@InCollection{Bullmann,
|
||||
author = {Bullmann, Dirk and Jonas Klemm and Andrea Pinna},
|
||||
year = {2019},
|
||||
title = {In search for stability in crypto-assets: are stablecoins the solution?},
|
||||
publisher = {European Central Bank},
|
||||
series = {ECB Occasional Paper Series},
|
||||
number = {230},
|
||||
}
|
||||
|
||||
@inproceedings{Camenisch2007,
|
||||
author = {Camenisch, Jan and Aanna Lysyanskaya and Mira Meyerovich},
|
||||
year = {2007},
|
||||
title = {{Endorsed E-Cash}},
|
||||
booktitle = {\textit{2007 IEEE Symposium on Security and Privacy (SP'07)}},
|
||||
month = {May},
|
||||
pages = {101--115},
|
||||
}
|
||||
|
||||
@inproceedings{Camenisch2005,
|
||||
author = {Camenisch, Jan and Susan Hohenberger and Anna Lysyanskaya},
|
||||
year = {2005},
|
||||
title = {{Compact E-Cash}},
|
||||
booktitle = {\textit{Advances in Cryptology -- EUROCRYPT 2005: 24th Annual International Conference on the Theory and Applications of Cryptographic Techniques}},
|
||||
address = {Aarhus, Denmark},
|
||||
month = {May},
|
||||
day = {22-26},
|
||||
editor = {Ed. di Ronald Cramer},
|
||||
publisher = {Springer-Verlag Berlin Heidelberg},
|
||||
}
|
||||
|
||||
|
||||
|
||||
@inproceedings{Canard,
|
||||
author = {Canard, Sébastien and Aline Gouget},
|
||||
year = {2007},
|
||||
title = {Divisible e-cash systems can be truly anonymous},
|
||||
booktitle = {\textit{Annual International Conference on the Theory and Applications of Cryptographic Techniques}},
|
||||
pages = {482--497},
|
||||
}
|
||||
|
||||
@misc{CCC,
|
||||
author = {{CCC e.V.}},
|
||||
year = {2017},
|
||||
title = {{Chaos Computer Club hacks e-motor charging stations}},
|
||||
howpublished = {34c3},
|
||||
}
|
||||
|
||||
@article{Chapman,
|
||||
author = {Chapman, James and Rodney Garratt and Scott Hendry and Andrew McCormack and Wade McMahon},
|
||||
year = {2017},
|
||||
title = {{Project Jasper: Are Distributed Wholesale Payment Systems Feasible Yet?}},
|
||||
journal = {Financial System Review},
|
||||
publisher = {Bank of Canada},
|
||||
month = {June},
|
||||
pages = {59--69},
|
||||
}
|
||||
|
||||
@inproceedings{Chaum1983,
|
||||
author = {Chaum, David},
|
||||
year = {1983},
|
||||
title = {Blind signatures for untraceable payments},
|
||||
booktitle = {\textit{Advances in Cryptology: Proceedings of Crypto `82}},
|
||||
pages = {199--203},
|
||||
}
|
||||
|
||||
@inproceedings{Chaum1990,
|
||||
author = {Chaum, David and Amos Fiat and Moni Naor},
|
||||
year = {1990},
|
||||
title = {Untraceable electronic cash},
|
||||
booktitle = {\textit{Advances in Cryptology: Proceedings of CRYPTO '88}},
|
||||
pages = {319--327},
|
||||
}
|
||||
|
||||
@inproceedings{Danezis,
|
||||
author = {Danezis, George and Sarah Meiklejohn},
|
||||
year = {2016},
|
||||
title = {{Centrally Banked Cryptocurrencies}},
|
||||
booktitle = {\textit{23nd Annual Network and Distributed System Security Symposium, NDSS2016}},
|
||||
address = {San Diego, California, USA},
|
||||
month = {February},
|
||||
day = {21--24},
|
||||
publisher = {The Internet Society},
|
||||
}
|
||||
|
||||
@article{Diffie,
|
||||
author = {Diffie, Whitfield and Martin Hellmann},
|
||||
year = {1976},
|
||||
title = {{New Directions in Cryptography}},
|
||||
journal = {IEEE Trans. on Inf. Theory, IT-22},
|
||||
pages = {644--654},
|
||||
}
|
||||
|
||||
@phdthesis{Dold,
|
||||
author = {Dold, Florian},
|
||||
year = {2019},
|
||||
title = {{The GNU Taler System: Practical and Provably Secure Electronic Payments. PhD Thesis}},
|
||||
school = {University of Rennes 1},
|
||||
}
|
||||
|
||||
@article{ECB,
|
||||
author = {{European Central Bank}},
|
||||
year = {2019},
|
||||
title = {Exploring anonymity in central bank digital currencies},
|
||||
journal = {In Focus},
|
||||
number = {4},
|
||||
month = {December},
|
||||
}
|
||||
|
||||
@inproceedings{Fuchsbauer,
|
||||
author = {Fuchsbauer, Georg and David Pointcheval and Damien Vergnaud},
|
||||
year = {2009},
|
||||
title = {Transferable constant-size fair e-cash},
|
||||
booktitle = {International Conference on Cryptology and Network Security},
|
||||
publisher = {Springer-Verlag Berlin Heidelberg},
|
||||
pages = {226--247},
|
||||
}
|
||||
|
||||
@inproceedings{Garcia,
|
||||
author = {Garcia, Flavio and Gerhard de Koning Gans and Ruben Muijrers and Peter van Rossum and Roel Verdult and Ronny Wichers Schreur and Bart Jacobs},
|
||||
year = {2008},
|
||||
title = {{Dismantling MIFARE Classic}},
|
||||
booktitle = {\textit{European Symposium on Research in Computer Security}},
|
||||
}
|
||||
|
||||
@article{Garratt,
|
||||
author = {Garratt, Rod and Michael Lee and Brendan Malone and Antoine Martin},
|
||||
year = {2020},
|
||||
title = {{Token- or Account-Based? A Digital Currency Can Be Both}},
|
||||
journal = {Liberty Street Economics},
|
||||
publisher = {Federal Reserve Bank of New York},
|
||||
month = {August},
|
||||
day = {12},
|
||||
}
|
||||
|
||||
@article{Goodfriend,
|
||||
author = {Goodfriend, Marvin},
|
||||
year = {2000},
|
||||
title = {{Overcoming the Zero Bound on Interest Rate Policy}},
|
||||
journal = {Journal of Money, Credit, and Banking},
|
||||
volume = {32},
|
||||
number = {4},
|
||||
pages = {1007--1035},
|
||||
}
|
||||
|
||||
@article{Johnston,
|
||||
author = {Johnston, Casey},
|
||||
year = {2010},
|
||||
title = {PS3 hacked through poor cryptography implementation},
|
||||
journal = {Ars Technica},
|
||||
month = {December},
|
||||
day = {30},
|
||||
}
|
||||
|
||||
@Misc{Jordan,
|
||||
note = {Discorso in occasione del 30º anniversario del Centro di scienze economiche (WWZ) e dell’Associazione degli economisti basilesi (VBÖ)},
|
||||
author = {Jordan, Thomas J.},
|
||||
year = {2019},
|
||||
title = {Valute, moneta e token digitali},
|
||||
publisher = {University of Basel},
|
||||
month = {September},
|
||||
howpublished = {\url{https://www.snb.ch/it/mmr/speeches/id/ref_20190905_tjn/source/ref_20190905_tjn.it.pdf}},
|
||||
}
|
||||
|
||||
@article{Kahn2009,
|
||||
author = {Kahn, Charles M. and William Roberds},
|
||||
year = {2009},
|
||||
title = {{Why Pay? An Introduction to Payments Economics}},
|
||||
journal = {Journal of Financial Intermediation},
|
||||
number = {18},
|
||||
pages = {1--23},
|
||||
}
|
||||
|
||||
@article{Kahn2005,
|
||||
author = {Kahn, Charles M. and James McAndrews and William Roberds},
|
||||
year = {2005},
|
||||
title = {{Money is Privacy}},
|
||||
journal = {International Economic Review},
|
||||
volume = {46},
|
||||
number = {2},
|
||||
pages = {377--399},
|
||||
}
|
||||
|
||||
@article{Kasper,
|
||||
author = {Kasper, Timo and Michael Silbermann and Christof Paar},
|
||||
year = {2010},
|
||||
title = {All you can eat or breaking a real-world contactless payment system},
|
||||
journal = {Financial Cryptography and Data Security, Lecture Notes in Computer Science},
|
||||
volume = {6052},
|
||||
pages = {343--50},
|
||||
}
|
||||
|
||||
@inproceedings{Katzenbeisser,
|
||||
author = {Katzenbeisser, Stefan and Ünal Kocabaş and Vladimir Rožić and Ahmad-Reza Sadeghi and Ingrid Verbauwhede and Christian Wachsmann},
|
||||
year = {2012},
|
||||
title = {{PUFs: Myth, Fact or Busted? A Security Evaluation of Physically Unclonable Functions (PUFs) Cast in Silicon}},
|
||||
booktitle = {\textit{Cryptographic Hardware and Embedded Systems -- CHES 2012. Lecture Notes in Computer Science}},
|
||||
volume = {7428},
|
||||
pages = {283--301},
|
||||
}
|
||||
|
||||
@book{Keynes,
|
||||
author = {Keynes, John Maynard},
|
||||
year = {1936},
|
||||
title = {The General Theory of Employment, Interest and Money},
|
||||
publisher = {Macmillan},
|
||||
}
|
||||
|
||||
@article{Kiff,
|
||||
author = {Kiff, John and Jihad Alwazir and Sonja Davidovic and Aquiles Farias and Ashraf Khan and Tanai Khiaonarong and Majid Malaika and Hunter Monroe and Nobu Sugimoto and Hervé Tourpe and Peter Zhou},
|
||||
year = {2020},
|
||||
title = {{A Survey of Research on Retail Central Bank Digital Currency}},
|
||||
journal = {IMF Working Paper},
|
||||
volume = {20/104},
|
||||
}
|
||||
|
||||
@InCollection{Kumhof,
|
||||
author = {Kumhof, Michael and Clare Noone},
|
||||
year = {2018},
|
||||
title = {Central bank digital currencies - design principles and balance sheet implications},
|
||||
publisher = {Bank of England},
|
||||
series = {Staff Working Paper},
|
||||
number = {725},
|
||||
}
|
||||
|
||||
@inproceedings{Lapid,
|
||||
author = {Lapid, Ben and Avishai Wool},
|
||||
year = {2018},
|
||||
title = {{Cache-Attacks on the ARM TrustZone Implementations of AES-256 and AES-256-GCM via GPU-Based Analysis}},
|
||||
booktitle = {\textit{International Conference on Selected Areas in Cryptography. Lecture Notes in Computer Science}},
|
||||
volume = {11349},
|
||||
}
|
||||
|
||||
@article{Lerner,
|
||||
author = {Lerner, Josh and Jean Tirole},
|
||||
year = {2005},
|
||||
title = {{The Scope of Open Source Licensing}},
|
||||
journal = {Journal of Law, Economics \& Organization},
|
||||
volume = {21},
|
||||
pages = {20-56},
|
||||
}
|
||||
|
||||
@misc{Libra,
|
||||
author = {{Libra Association}},
|
||||
year = {2020},
|
||||
title = {{Libra White Paper v2.0}},
|
||||
url = {\url{https://libra.org/en-US/white-paper}},
|
||||
}
|
||||
|
||||
@inproceedings{Lim,
|
||||
author = {Lim, Chae Hoon and Phil Joong Lee},
|
||||
year = {1997},
|
||||
title = {A key recovery attack on discrete log-based schemes using a prime order subgroup},
|
||||
booktitle = {\textit{CRYPTO 1997. Lecture Notes in Computer Science}},
|
||||
volume = {1294},
|
||||
}
|
||||
|
||||
@InCollection{Lyons,
|
||||
author = {Lyons, Richard K. and Ganesh Viswanath-Natraj},
|
||||
year = {2020},
|
||||
title = {{What Keeps Stablecoins Stable?}},
|
||||
publisher = {National Bureau of Economic Research},
|
||||
series = {NBER Working Paper Series},
|
||||
number = {27136},
|
||||
month = {May},
|
||||
}
|
||||
|
||||
@article{Mancini-Griffoli,
|
||||
author = {Mancini-Griffoli and Maria Soledad Martinez Peria and Itai Agur and Anil Ari and John Kiff and Adina Popescu and Celine Rochon},
|
||||
year = {2018},
|
||||
title = {{Casting Light on Central Bank Digital Currency}},
|
||||
journal = {IMF Staff Discussion Notes},
|
||||
volume = {18/08},
|
||||
publisher = {International Monetary Fund},
|
||||
}
|
||||
|
||||
@misc{Nakamoto,
|
||||
author = {Nakamoto, Satoshi},
|
||||
year = {2008},
|
||||
title = {{Bitcoin: A Peer-to-Peer Electronic Cash System}},
|
||||
url = {\url{https://www.bitcoin.com/bitcoin.pdf}},
|
||||
}
|
||||
|
||||
@book{Narayanan,
|
||||
author = {Narayanan, Arvind and Joseph Bonneau and Edward Felten and Andrew Miller and Steven Goldfeder},
|
||||
year = {2016},
|
||||
title = {Bitcoin and Cryptocurrency Technologies: A Comprehensive Introduction},
|
||||
publisher = {Princeton University Press},
|
||||
}
|
||||
|
||||
@misc{Niepelt,
|
||||
author = {Niepelt, Dirk},
|
||||
year = {2020},
|
||||
title = {Digital money and central bank digital currency: An executive summary for policymakers},
|
||||
howpublished = {\url{https://voxeu.org/article/digital-money-and-central-bank-digital-currency-executive-summary}},
|
||||
}
|
||||
|
||||
@inproceedings{Okamoto,
|
||||
author = {Okamoto, Tatsuaki},
|
||||
year = {1995},
|
||||
title = {{An Efficient Divisible Electronic Cash Scheme}},
|
||||
booktitle = {\textit{Advances in Cryptology --- CRYPT0'95: 15th Annual International Cryptology Conference Santa Barbara, California, USA, 27--31 agosto, 1995 Proceedings}},
|
||||
editor = {Ed. di Don Coppersmith},
|
||||
publisher = {Springer-Verlag Berlin Heidelberg},
|
||||
pages = {438--451},
|
||||
}
|
||||
|
||||
@article{Pinto,
|
||||
author = {Pinto, S. and N. Santos},
|
||||
year = {2019},
|
||||
title = {{Demystifying ARM TrustZone: A Comprehensive Survey}},
|
||||
journal = {ACM Computing Surveys},
|
||||
volume = {51},
|
||||
number = {6},
|
||||
month = {January},
|
||||
pages = {1--31}
|
||||
}
|
||||
|
||||
@article{Rivest,
|
||||
author = {Rivest, Ronald L. and Adi Shamir and Leonard Adleman},
|
||||
year = {1978},
|
||||
title = {{A Method for Obtaining Digital Signatures and Public Key Cryptosystems}},
|
||||
journal = {Comm. ACM},
|
||||
volume = {21},
|
||||
number = {2},
|
||||
}
|
||||
|
||||
@book{Solove,
|
||||
author = {Solove, Daniel J.},
|
||||
year = {2011},
|
||||
title = {Nothing to Hide: The false tradeoff between privacy and security},
|
||||
publisher = {New Haven \& London: Yale University Press},
|
||||
}
|
||||
|
||||
@article{Soukup,
|
||||
author = {Soukup, Michael and Bruno Muff},
|
||||
year = {2007},
|
||||
title = {{Die Postcard lässt sich fälschen}},
|
||||
journal = {Sonntagszeitung},
|
||||
month = {April},
|
||||
day = {22},
|
||||
}
|
||||
|
||||
@article{Stallman,
|
||||
author = {Stallman, Richard},
|
||||
year = {1985},
|
||||
title = {{The GNU manifesto}},
|
||||
journal = {Dr. Dobb's Journal of Software Tools},
|
||||
volume = {10},
|
||||
number = {3},
|
||||
pages = {30--35},
|
||||
}
|
||||
|
||||
@TechReport{Riksbank,
|
||||
author = {{Sveriges Riksbank}},
|
||||
year = {2020},
|
||||
title = {{The Riksbank's e-krona project}},
|
||||
month = {February},
|
||||
institution = {Sveriges Riksbank},
|
||||
url = {\url{https://www.riksbank.se/globalassets/media/rapporter/e-krona/2019/the-riksbanks-e-krona-pilot.pdf}},
|
||||
}
|
||||
|
||||
@misc{Wojtczuk,
|
||||
author = {Wojtczuk, Rafal and Joanna Rutkowska},
|
||||
year = {2009},
|
||||
title = {{Attacking Intel Trusted Execution Technology}},
|
||||
howpublished = {BlackHat-DC 2009},
|
||||
}
|
||||
|
||||
@article{Yalta2010,
|
||||
author = {Yalta, A. Talha and A. Yasemin Yalta},
|
||||
year = {2010},
|
||||
title = {{Should Economists Use Open Source Software for Doing Research?}},
|
||||
journal = {Computational Economics},
|
||||
volume = {35},
|
||||
pages = {371--394},
|
||||
}
|
||||
|
||||
@article{Yalta2008,
|
||||
author = {Yalta, A. Talha and Riccardo Lucchetti},
|
||||
year = {2008},
|
||||
title = {{The GNU/Linux Platform and Freedom Respecting Software for Economists}},
|
||||
journal = {Journal of Applied Econometrics},
|
||||
volume = {23},
|
||||
pages = {279-286},
|
||||
}
|
1303
doc/cbdc-it/cbdc-it.tex
Normal file
1303
doc/cbdc-it/cbdc-it.tex
Normal file
File diff suppressed because it is too large
Load Diff
566
doc/cbdc-it/cbdc.bib
Normal file
566
doc/cbdc-it/cbdc.bib
Normal file
@ -0,0 +1,566 @@
|
||||
@article{Adrian,
|
||||
author = {Adrian, Tobias and Tommaso Mancini-Griffoli},
|
||||
year = {2019},
|
||||
title = {The Rise of Digital Money},
|
||||
journal = {IMF Fintech Note},
|
||||
volume = {19/01},
|
||||
}
|
||||
|
||||
@article{Agarwal,
|
||||
author = {Agarwal, Ruchir and Miles S. Kimball},
|
||||
year = {2019},
|
||||
title = {Enabling Deep Negative Rates to Fight Recessions: A Guide},
|
||||
journal = {IMF Working Paper},
|
||||
volume = {19/84},
|
||||
}
|
||||
|
||||
|
||||
@article{Agur,
|
||||
author = {Agur, Itai and Anil Ari and Giovanni Dell'Ariccia},
|
||||
year = {2019},
|
||||
title = {Designing Central Bank Digital Currencies},
|
||||
journal = {IMF Working Paper},
|
||||
volume = {19/252},
|
||||
}
|
||||
|
||||
@article{Allen,
|
||||
author = {Allen, Sarah and Srđjan Čapkun and Ittay Eyal and Giulia Fanti and Bryan A. Ford and James Grimmelmann and Ari Juels and Kari Kostiainen and Sarah Meiklejohn and Andrew Miller and Eswar Prasad and Karl Wüst and Fan Zhang},
|
||||
year = {2020},
|
||||
title = {Design Choices for Central Bank Digital Currency: Policy and Technical Considerations},
|
||||
journal = {NBER Working Paper},
|
||||
volume = {27634},
|
||||
}
|
||||
|
||||
@article{Alves,
|
||||
author = {Alves, Tiago and Don Felton},
|
||||
year = {2004},
|
||||
title = {TrustZone: Integrated hardware and software security},
|
||||
journal = {ARM IQ},
|
||||
volume = {3},
|
||||
number = {4},
|
||||
pages = {18--24},
|
||||
}
|
||||
|
||||
@article{AuerBoehme,
|
||||
author = {Auer, Raphael and Rainer Böhme},
|
||||
year = {2020},
|
||||
title = {The technology of retail central bank digital currency},
|
||||
journal = {BIS Quarterly Review},
|
||||
month = {March},
|
||||
pages = {85--96},
|
||||
}
|
||||
|
||||
@article{AuerCornelli,
|
||||
author = {Auer, Raphael and Giulio Cornelli and Jon Frost},
|
||||
year = {2020},
|
||||
title = {Taking stock: ongoing retail {CBDC} projects},
|
||||
journal = {BIS Quarterly Review},
|
||||
month = {March},
|
||||
pages = {97--98},
|
||||
}
|
||||
|
||||
@booklet{BIS,
|
||||
author = {{Bank for International Settlements}},
|
||||
year = {2018},
|
||||
title = {Central Bank Digital Currencies. Joint Report of the Committee on Payments and Market Infrastructures and Markets Committee},
|
||||
}
|
||||
|
||||
@booklet{BoE,
|
||||
author = {{Bank of England}},
|
||||
year = {2020},
|
||||
title = {Central Bank Digital Currency: Opportunities, Challenges and Design. Discussion Paper},
|
||||
month = {March},
|
||||
}
|
||||
|
||||
@article{Baiocchi,
|
||||
author = {Baiocchi, Giovanni and Walter Distaso},
|
||||
year = {2003},
|
||||
title = {{GRETL}: Econometric Software for the {GNU} Generation},
|
||||
journal = {Journal of Applied Econometrics},
|
||||
volume = {18},
|
||||
pages = {105-110},
|
||||
}
|
||||
|
||||
@article{Bech,
|
||||
author = {Bech, Morten and Rodney Garratt},
|
||||
year = {2017},
|
||||
title = {Central bank cryptocurrencies},
|
||||
journal = {BIS Quarterly Review},
|
||||
month = {September},
|
||||
pages = {55--70},
|
||||
}
|
||||
|
||||
@article{Berentsen,
|
||||
author = {Berentsen, Aleksander and Fabian Schär},
|
||||
year = {2018},
|
||||
title = {The Case for Central Bank Electronic Money and the Non-case for Central Bank Cryptocurrencies},
|
||||
journal = {Federal Reserve Bank of St. Louis Review},
|
||||
volume = {100},
|
||||
number = {2},
|
||||
pages = {97--106},
|
||||
}
|
||||
|
||||
@article{Bernstein2020,
|
||||
author = {Bernstein, Daniel J. and Tanja Lange},
|
||||
year = {2020},
|
||||
title = {{eBACS}: {ECRYPT} Benchmarking of Cryptographic Systems},
|
||||
url = {\url{https://bench.cr.yp.to}, accessed 17 March 2020},
|
||||
}
|
||||
|
||||
@article{Bernstein2012,
|
||||
author = {Bernstein, Daniel J. and Niels Duif and Tanja Lange and Peter Schwabe and Bo-Yin Yang},
|
||||
year = {2012},
|
||||
title = {High-speed high-security signatures},
|
||||
journal = {Journal of Cryptographic Engineering},
|
||||
volume = {2},
|
||||
pages = {77--89},
|
||||
}
|
||||
|
||||
@InCollection{Bindseil,
|
||||
author = {Bindseil, Ulrich},
|
||||
year = {2020},
|
||||
title = {Tiered {CBDC} and the financial system},
|
||||
publisher = {European Central Bank},
|
||||
series = {ECB Working Paper},
|
||||
number = {2351},
|
||||
month = {January},
|
||||
}
|
||||
|
||||
@article{Boar,
|
||||
author = {Boar, Codruta and Henry Holden and Amber Wadsworth},
|
||||
year = {2020},
|
||||
title = {Impending arrival - a sequel to the survey on central bank digital currency},
|
||||
journal = {BIS Papers},
|
||||
volume = {107},
|
||||
}
|
||||
|
||||
@article{Boneh,
|
||||
author = {Boneh, Dan},
|
||||
year = {1999},
|
||||
title = {Twenty Years of Attacks on the {RSA} Cryptosystem},
|
||||
journal = {Notices of the AMS},
|
||||
volume = {42},
|
||||
number = {2},
|
||||
pages = {202--213},
|
||||
}
|
||||
|
||||
|
||||
@InCollection{Bordo,
|
||||
author = {Bordo, Michael D. and Andrew T. Levin},
|
||||
year = {2017},
|
||||
title = {Central bank digital currency and the future of monetary policy},
|
||||
publisher = {National Bureau of Economic Research},
|
||||
series = {NBER Working Paper Series},
|
||||
number = {23711},
|
||||
}
|
||||
|
||||
@article{Brunnermeier,
|
||||
author = {Brunnermeier, Markus and Dirk Niepelt},
|
||||
year = {2019},
|
||||
title = {On the Equivalence of Private and Public Money},
|
||||
journal = {Journal of Monetary Economics},
|
||||
volume = {106},
|
||||
pages = {27--41},
|
||||
}
|
||||
|
||||
@article{Buiter,
|
||||
author = {Buiter, Willem H. and Nikolaos Panigirtzoglou},
|
||||
year = {2003},
|
||||
title = {Overcoming the Zero Bound on Nominal Interest Rates with Negative Interest on Currency: Gesell's Solution},
|
||||
journal = {The Economic Journal},
|
||||
volume = {113},
|
||||
number = {490},
|
||||
pages = {723--746},
|
||||
}
|
||||
|
||||
@InCollection{Bullmann,
|
||||
author = {Bullmann, Dirk and Jonas Klemm and Andrea Pinna},
|
||||
year = {2019},
|
||||
title = {In search for stability in crypto-assets: are stablecoins the solution?},
|
||||
publisher = {European Central Bank},
|
||||
series = {ECB Occasional Paper Series},
|
||||
number = {230},
|
||||
}
|
||||
|
||||
@inproceedings{Camenisch2007,
|
||||
author = {Camenisch, Jan and Aanna Lysyanskaya and Mira Meyerovich},
|
||||
year = {2007},
|
||||
title = {Endorsed E-Cash},
|
||||
booktitle = {2007 IEEE Symposium on Security and Privacy (SP'07)},
|
||||
month = {May},
|
||||
pages = {101--115},
|
||||
}
|
||||
|
||||
@inproceedings{Camenisch2005,
|
||||
author = {Camenisch, Jan and Susan Hohenberger and Anna Lysyanskaya},
|
||||
year = {2005},
|
||||
title = {Compact E-Cash},
|
||||
booktitle = {Advances in Cryptology -- EUROCRYPT 2005: 24th Annual International Conference on the Theory and Applications of Cryptographic Techniques},
|
||||
address = {Aarhus, Denmark},
|
||||
month = {May},
|
||||
day = {22-26},
|
||||
editor = {Ed. by Ronald Cramer},
|
||||
publisher = {Springer-Verlag Berlin Heidelberg},
|
||||
}
|
||||
|
||||
|
||||
|
||||
@inproceedings{Canard,
|
||||
author = {Canard, Sébastien and Aline Gouget},
|
||||
year = {2007},
|
||||
title = {Divisible e-cash systems can be truly anonymous},
|
||||
booktitle = {Annual International Conference on the Theory and Applications of Cryptographic Techniques},
|
||||
pages = {482--497},
|
||||
}
|
||||
|
||||
|
||||
|
||||
@misc{CCC,
|
||||
author = {{CCC e.V.}},
|
||||
year = {2017},
|
||||
title = {Chaos Computer Club hacks e-motor charging stations},
|
||||
howpublished = {34c3},
|
||||
}
|
||||
|
||||
@article{Chapman,
|
||||
author = {Chapman, James and Rodney Garratt and Scott Hendry and Andrew McCormack and Wade McMahon},
|
||||
year = {2017},
|
||||
title = {Project {J}asper: Are Distributed Wholesale Payment Systems Feasible Yet?},
|
||||
journal = {Financial System Review},
|
||||
publisher = {Bank of Canada},
|
||||
month = {June},
|
||||
pages = {59--69},
|
||||
}
|
||||
|
||||
@inproceedings{Chaum1983,
|
||||
author = {Chaum, David},
|
||||
year = {1983},
|
||||
title = {Blind signatures for untraceable payments},
|
||||
booktitle = {Advances in Cryptology: Proceedings of Crypto `82},
|
||||
pages = {199--203},
|
||||
}
|
||||
|
||||
@inproceedings{Chaum1990,
|
||||
author = {Chaum, David and Amos Fiat and Moni Naor},
|
||||
year = {1990},
|
||||
title = {Untraceable electronic cash},
|
||||
booktitle = {Advances in Cryptology: Proceedings of CRYPTO '88},
|
||||
pages = {319--327},
|
||||
}
|
||||
|
||||
@inproceedings{Danezis,
|
||||
author = {Danezis, George and Sarah Meiklejohn},
|
||||
year = {2016},
|
||||
title = {Centrally Banked Cryptocurrencies},
|
||||
booktitle = {23nd Annual Network and Distributed System Security Symposium, NDSS2016},
|
||||
address = {San Diego, California, USA},
|
||||
month = {February},
|
||||
day = {21--24},
|
||||
publisher = {The Internet Society},
|
||||
}
|
||||
|
||||
@article{Diffie,
|
||||
author = {Diffie, Whitfield and Martin Hellmann},
|
||||
year = {1976},
|
||||
title = {New Directions in Cryptography},
|
||||
journal = {IEEE Trans. on Inf. Theory, IT-22},
|
||||
pages = {644--654},
|
||||
}
|
||||
|
||||
@phdthesis{Dold,
|
||||
author = {Dold, Florian},
|
||||
year = {2019},
|
||||
title = {The {GNU} {T}aler System: Practical and Provably Secure Electronic Payments. PhD Thesis},
|
||||
school = {University of Rennes 1},
|
||||
}
|
||||
|
||||
@article{ECB,
|
||||
author = {{European Central Bank}},
|
||||
year = {2019},
|
||||
title = {Exploring anonymity in central bank digital currencies},
|
||||
journal = {In Focus},
|
||||
number = {4},
|
||||
month = {December},
|
||||
}
|
||||
|
||||
@inproceedings{Fuchsbauer,
|
||||
author = {Fuchsbauer, Georg and David Pointcheval and Damien Vergnaud},
|
||||
year = {2009},
|
||||
title = {Transferable constant-size fair e-cash},
|
||||
booktitle = {International Conference on Cryptology and Network Security},
|
||||
publisher = {Springer-Verlag Berlin Heidelberg},
|
||||
pages = {226--247},
|
||||
}
|
||||
|
||||
@inproceedings{Garcia,
|
||||
author = {Garcia, Flavio and Gerhard de Koning Gans and Ruben Muijrers and Peter van Rossum and Roel Verdult and Ronny Wichers Schreur and Bart Jacobs},
|
||||
year = {2008},
|
||||
title = {Dismantling MIFARE Classic},
|
||||
booktitle = {European Symposium on Research in Computer Security},
|
||||
}
|
||||
|
||||
@article{Garratt,
|
||||
author = {Garratt, Rod and Michael Lee and Brendan Malone and Antoine Martin},
|
||||
year = {2020},
|
||||
title = {Token- or Account-Based? A Digital Currency Can Be Both},
|
||||
journal = {Liberty Street Economics},
|
||||
publisher = {Federal Reserve Bank of New York},
|
||||
month = {August},
|
||||
day = {12},
|
||||
}
|
||||
|
||||
@article{Goodfriend,
|
||||
author = {Goodfriend, Marvin},
|
||||
year = {2000},
|
||||
title = {Overcoming the Zero Bound on Interest Rate Policy},
|
||||
journal = {Journal of Money, Credit, and Banking},
|
||||
volume = {32},
|
||||
number = {4},
|
||||
pages = {1007--1035},
|
||||
}
|
||||
|
||||
@article{Johnston,
|
||||
author = {Johnston, Casey},
|
||||
year = {2010},
|
||||
title = {PS3 hacked through poor cryptography implementation},
|
||||
journal = {Ars Technica},
|
||||
month = {December},
|
||||
day = {30},
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Misc{Jordan,
|
||||
note = {Speech given at the 30th anniversary of the WWZ and VBÖ},
|
||||
author = {Jordan, Thomas J.},
|
||||
year = {2019},
|
||||
title = {Currencies, money and digital tokens},
|
||||
publisher = {University of Basel},
|
||||
month = {September},
|
||||
howpublished = {\url{https://www.snb.ch/en/mmr/speeches/id/ref\_20190905\_tjn/source/ref\_20190905\_tjn.en.pdf}},
|
||||
}
|
||||
|
||||
|
||||
@article{Kahn2009,
|
||||
author = {Kahn, Charles M. and William Roberds},
|
||||
year = {2009},
|
||||
title = {Why Pay? An Introduction to Payments Economics},
|
||||
journal = {Journal of Financial Intermediation},
|
||||
number = {18},
|
||||
pages = {1--23},
|
||||
}
|
||||
|
||||
@article{Kahn2005,
|
||||
author = {Kahn, Charles M. and James McAndrews and William Roberds},
|
||||
year = {2005},
|
||||
title = {Money is Privacy},
|
||||
journal = {International Economic Review},
|
||||
volume = {46},
|
||||
number = {2},
|
||||
pages = {377--399},
|
||||
}
|
||||
|
||||
@article{Kasper,
|
||||
author = {Kasper, Timo and Michael Silbermann and Christof Paar},
|
||||
year = {2010},
|
||||
title = {All you can eat or breaking a real-world contactless payment system},
|
||||
journal = {Financial Cryptography and Data Security, Lecture Notes in Computer Science},
|
||||
volume = {6052},
|
||||
pages = {343--50},
|
||||
}
|
||||
|
||||
@inproceedings{Katzenbeisser,
|
||||
author = {Katzenbeisser, Stefan and Ünal Kocabaş and Vladimir Rožić and Ahmad-Reza Sadeghi and Ingrid Verbauwhede and Christian Wachsmann},
|
||||
year = {2012},
|
||||
title = {{PUF}s: Myth, Fact or Busted? A Security Evaluation of Physically Unclonable Functions ({PUF}s) Cast in Silicon},
|
||||
booktitle = {Cryptographic Hardware and Embedded Systems -- CHES 2012. Lecture Notes in Computer Science},
|
||||
volume = {7428},
|
||||
pages = {283--301},
|
||||
}
|
||||
|
||||
@book{Keynes,
|
||||
author = {Keynes, John Maynard},
|
||||
year = {1936},
|
||||
title = {The General Theory of Employment, Interest and Money},
|
||||
publisher = {Macmillan},
|
||||
}
|
||||
|
||||
@article{Kiff,
|
||||
author = {Kiff, John and Jihad Alwazir and Sonja Davidovic and Aquiles Farias and Ashraf Khan and Tanai Khiaonarong and Majid Malaika and Hunter Monroe and Nobu Sugimoto and Hervé Tourpe and Peter Zhou},
|
||||
year = {2020},
|
||||
title = {A Survey of Research on Retail Central Bank Digital Currency},
|
||||
journal = {IMF Working Paper},
|
||||
volume = {20/104},
|
||||
}
|
||||
|
||||
@InCollection{Kumhof,
|
||||
author = {Kumhof, Michael and Clare Noone},
|
||||
year = {2018},
|
||||
title = {Central bank digital currencies - design principles and balance sheet implications},
|
||||
publisher = {Bank of England},
|
||||
series = {Staff Working Paper},
|
||||
number = {725},
|
||||
}
|
||||
|
||||
@inproceedings{Lapid,
|
||||
author = {Lapid, Ben and Avishai Wool},
|
||||
year = {2018},
|
||||
title = {Cache-Attacks on the {ARM} TrustZone Implementations of {AES}-256 and {AES}-256-{GCM} via {GPU}-Based Analysis},
|
||||
booktitle = {International Conference on Selected Areas in Cryptography. Lecture Notes in Computer Science},
|
||||
volume = {11349},
|
||||
}
|
||||
|
||||
@article{Lerner,
|
||||
author = {Lerner, Josh and Jean Tirole},
|
||||
year = {2005},
|
||||
title = {The Scope of Open Source Licensing},
|
||||
journal = {Journal of Law, Economics \& Organization},
|
||||
volume = {21},
|
||||
pages = {20-56},
|
||||
}
|
||||
|
||||
@misc{Libra,
|
||||
author = {{Libra Association}},
|
||||
year = {2020},
|
||||
title = {Libra White Paper v2.0},
|
||||
url = {\url{https://libra.org/en-US/white-paper}},
|
||||
}
|
||||
|
||||
@inproceedings{Lim,
|
||||
author = {Lim, Chae Hoon and Phil Joong Lee},
|
||||
year = {1997},
|
||||
title = {A key recovery attack on discrete log-based schemes using a prime order subgroup},
|
||||
booktitle = {CRYPTO 1997. Lecture Notes in Computer Science},
|
||||
volume = {1294},
|
||||
}
|
||||
|
||||
@InCollection{Lyons,
|
||||
author = {Lyons, Richard K. and Ganesh Viswanath-Natraj},
|
||||
year = {2020},
|
||||
title = {What Keeps Stablecoins Stable?},
|
||||
publisher = {National Bureau of Economic Research},
|
||||
series = {NBER Working Paper Series},
|
||||
number = {27136},
|
||||
month = {May},
|
||||
}
|
||||
|
||||
@article{Mancini-Griffoli,
|
||||
author = {Mancini-Griffoli, Tommaso and Maria Soledad Martinez Peria and Itai Agur and Anil Ari and John Kiff and Adina Popescu and Celine Rochon},
|
||||
year = {2018},
|
||||
title = {Casting Light on Central Bank Digital Currency},
|
||||
journal = {IMF Staff Discussion Notes},
|
||||
volume = {18/08},
|
||||
publisher = {International Monetary Fund},
|
||||
}
|
||||
|
||||
@misc{Nakamoto,
|
||||
author = {Nakamoto, Satoshi},
|
||||
year = {2008},
|
||||
title = {Bitcoin: A Peer-to-Peer Electronic Cash System},
|
||||
url = {\url{https://www.bitcoin.com/bitcoin.pdf}},
|
||||
}
|
||||
|
||||
@book{Narayanan,
|
||||
author = {Narayanan, Arvind and Joseph Bonneau and Edward Felten and Andrew Miller and Steven Goldfeder},
|
||||
year = {2016},
|
||||
title = {Bitcoin and Cryptocurrency Technologies: A Comprehensive Introduction},
|
||||
publisher = {Princeton University Press},
|
||||
}
|
||||
|
||||
@misc{Niepelt,
|
||||
author = {Niepelt, Dirk},
|
||||
year = {2020},
|
||||
title = {Digital money and central bank digital currency: An executive summary for policymakers},
|
||||
url = {https://voxeu.org/article/digital-money-and-central-bank-digital-currency-executive-summary},
|
||||
}
|
||||
|
||||
@inproceedings{Okamoto,
|
||||
author = {Okamoto, Tatsuaki},
|
||||
year = {1995},
|
||||
title = {An Efficient Divisible Electronic Cash Scheme},
|
||||
booktitle = {Advances in Cryptology --- CRYPT0'95: 15th Annual International Cryptology Conference Santa Barbara, California, USA, August 27--31, 1995 Proceedings},
|
||||
editor = {Ed. by Don Coppersmith},
|
||||
publisher = {Springer-Verlag Berlin Heidelberg},
|
||||
pages = {438--451},
|
||||
}
|
||||
|
||||
@article{Pinto,
|
||||
author = {Pinto, S. and N. Santos},
|
||||
year = {2019},
|
||||
title = {Demystifying {ARM} TrustZone: A Comprehensive Survey},
|
||||
journal = {ACM Computing Surveys},
|
||||
volume = {51},
|
||||
number = {6},
|
||||
month = {January},
|
||||
pages = {1--31}
|
||||
}
|
||||
|
||||
@article{Rivest,
|
||||
author = {Rivest, Ronald L. and Adi Shamir and Leonard Adleman},
|
||||
year = {1978},
|
||||
title = {A Method for Obtaining Digital Signatures and Public Key Cryptosystems},
|
||||
journal = {Comm. ACM},
|
||||
volume = {21},
|
||||
number = {2},
|
||||
}
|
||||
|
||||
@book{Solove,
|
||||
author = {Solove, Daniel J.},
|
||||
year = {2011},
|
||||
title = {Nothing to Hide: The false tradeoff between privacy and security},
|
||||
publisher = {New Haven \& London: Yale University Press},
|
||||
}
|
||||
|
||||
@article{Soukup,
|
||||
author = {Soukup, Michael and Bruno Muff},
|
||||
year = {2007},
|
||||
title = {Die {P}ostcard lässt sich fälschen},
|
||||
journal = {Sonntagszeitung},
|
||||
month = {April},
|
||||
day = {22},
|
||||
}
|
||||
|
||||
@article{Stallman,
|
||||
author = {Stallman, Richard},
|
||||
year = {1985},
|
||||
title = {The {GNU} manifesto},
|
||||
journal = {Dr. Dobb's Journal of Software Tools},
|
||||
volume = {10},
|
||||
number = {3},
|
||||
pages = {30--35},
|
||||
}
|
||||
|
||||
|
||||
@TechReport{Riksbank,
|
||||
author = {{Sveriges Riksbank}},
|
||||
year = {2020},
|
||||
title = {The {R}iksbank's e-krona project},
|
||||
month = {Feb},
|
||||
institution = {Sveriges Riksbank},
|
||||
url = {\url{https://www.riksbank.se/globalassets/media/rapporter/e-krona/2019/the-riksbanks-e-krona-pilot.pdf}},
|
||||
}
|
||||
|
||||
@misc{Wojtczuk,
|
||||
author = {Wojtczuk, Rafal and Joanna Rutkowska},
|
||||
year = {2009},
|
||||
title = {Attacking {I}ntel Trusted Execution Technology},
|
||||
howpublished = {BlackHat-DC 2009},
|
||||
}
|
||||
|
||||
@article{Yalta2010,
|
||||
author = {Yalta, A. Talha and A. Yasemin Yalta},
|
||||
year = {2010},
|
||||
title = {Should Economists Use Open Source Software for Doing Research?},
|
||||
journal = {Computational Economics},
|
||||
volume = {35},
|
||||
pages = {371--394},
|
||||
}
|
||||
|
||||
@article{Yalta2008,
|
||||
author = {Yalta, A. Talha and Riccardo Lucchetti},
|
||||
year = {2008},
|
||||
title = {The {GNU/L}inux Platform and Freedom Respecting Software for Economists},
|
||||
journal = {Journal of Applied Econometrics},
|
||||
volume = {23},
|
||||
pages = {279-286},
|
||||
}
|
BIN
doc/cbdc-it/diagramma1-it.png
Normal file
BIN
doc/cbdc-it/diagramma1-it.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 106 KiB |
BIN
doc/cbdc-it/diagramma2-it.png
Normal file
BIN
doc/cbdc-it/diagramma2-it.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 119 KiB |
BIN
doc/cbdc-it/graphics-it.odp
Normal file
BIN
doc/cbdc-it/graphics-it.odp
Normal file
Binary file not shown.
@ -106,6 +106,7 @@ fee_withdraw = TESTKUDOS:0.01
|
||||
fee_deposit = TESTKUDOS:0.01
|
||||
fee_refresh = TESTKUDOS:0.01
|
||||
fee_refund = TESTKUDOS:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_kudos_ct_10]
|
||||
@ -117,6 +118,7 @@ fee_withdraw = TESTKUDOS:0.01
|
||||
fee_deposit = TESTKUDOS:0.01
|
||||
fee_refresh = TESTKUDOS:0.03
|
||||
fee_refund = TESTKUDOS:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_kudos_1]
|
||||
@ -128,6 +130,7 @@ fee_withdraw = TESTKUDOS:0.02
|
||||
fee_deposit = TESTKUDOS:0.02
|
||||
fee_refresh = TESTKUDOS:0.03
|
||||
fee_refund = TESTKUDOS:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_kudos_2]
|
||||
@ -139,6 +142,7 @@ fee_withdraw = TESTKUDOS:0.03
|
||||
fee_deposit = TESTKUDOS:0.03
|
||||
fee_refresh = TESTKUDOS:0.04
|
||||
fee_refund = TESTKUDOS:0.02
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_kudos_4]
|
||||
@ -150,6 +154,7 @@ fee_withdraw = TESTKUDOS:0.03
|
||||
fee_deposit = TESTKUDOS:0.03
|
||||
fee_refresh = TESTKUDOS:0.04
|
||||
fee_refund = TESTKUDOS:0.02
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_kudos_5]
|
||||
@ -161,6 +166,7 @@ fee_withdraw = TESTKUDOS:0.01
|
||||
fee_deposit = TESTKUDOS:0.01
|
||||
fee_refresh = TESTKUDOS:0.03
|
||||
fee_refund = TESTKUDOS:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_kudos_8]
|
||||
@ -172,6 +178,7 @@ fee_withdraw = TESTKUDOS:0.05
|
||||
fee_deposit = TESTKUDOS:0.02
|
||||
fee_refresh = TESTKUDOS:0.03
|
||||
fee_refund = TESTKUDOS:0.04
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_kudos_10]
|
||||
@ -183,6 +190,31 @@ fee_withdraw = TESTKUDOS:0.01
|
||||
fee_deposit = TESTKUDOS:0.01
|
||||
fee_refresh = TESTKUDOS:0.03
|
||||
fee_refund = TESTKUDOS:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_kudos_ct_1]
|
||||
value = TESTKUDOS:0.01
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = TESTKUDOS:0.01
|
||||
fee_deposit = TESTKUDOS:0.01
|
||||
fee_refresh = TESTKUDOS:0.01
|
||||
fee_refund = TESTKUDOS:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_kudos_ct_10]
|
||||
value = TESTKUDOS:0.10
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = TESTKUDOS:0.01
|
||||
fee_deposit = TESTKUDOS:0.01
|
||||
fee_refresh = TESTKUDOS:0.03
|
||||
fee_refund = TESTKUDOS:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[benchmark]
|
||||
|
128
src/benchmark/bank-benchmark-cs.conf
Normal file
128
src/benchmark/bank-benchmark-cs.conf
Normal file
@ -0,0 +1,128 @@
|
||||
# This file is in the public domain.
|
||||
#
|
||||
[paths]
|
||||
# Persistent data storage for the testcase
|
||||
# This value is a default for `taler_config_home'
|
||||
taler_test_home = exchange_benchmark_home/
|
||||
|
||||
[taler]
|
||||
# Currency supported by the exchange (can only be one)
|
||||
currency = EUR
|
||||
CURRENCY_ROUND_UNIT = EUR:0.01
|
||||
|
||||
[exchange]
|
||||
# how long is one signkey valid?
|
||||
signkey_duration = 4 weeks
|
||||
signkey_legal_duration = 2 years
|
||||
# how long do we provide to clients denomination and signing keys
|
||||
# ahead of time?
|
||||
# Keep it short so the test runs fast.
|
||||
lookahead_sign = 12h
|
||||
# HTTP port the exchange listens to
|
||||
port = 8081
|
||||
# Master public key used to sign the exchange's various keys
|
||||
master_public_key = 98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG
|
||||
# How to access our database
|
||||
DB = postgres
|
||||
# Base URL of the exchange. Must be set to a URL where the
|
||||
# exchange (or the twister) is actually listening.
|
||||
base_url = "http://localhost:8081/"
|
||||
|
||||
WIREWATCH_IDLE_SLEEP_INTERVAL = 1500 ms
|
||||
|
||||
[exchange-offline]
|
||||
MASTER_PRIV_FILE = ${TALER_DATA_HOME}/exchange/offline-keys/master.priv
|
||||
|
||||
[auditor]
|
||||
BASE_URL = "http://localhost:8083/"
|
||||
|
||||
[exchangedb-postgres]
|
||||
config = "postgres:///talercheck"
|
||||
|
||||
[benchmark-remote-exchange]
|
||||
host = localhost
|
||||
# Adjust $HOME to match remote target!
|
||||
dir = $HOME/repos/taler/exchange/src/benchmark
|
||||
|
||||
[bank]
|
||||
HTTP_PORT = 8082
|
||||
SERVE = http
|
||||
MAX_DEBT = EUR:100000000000.0
|
||||
MAX_DEBT_BANK = EUR:1000000000000000.0
|
||||
|
||||
[benchmark]
|
||||
USER_PAYTO_URI = payto://x-taler-bank/localhost:8082/42
|
||||
|
||||
[exchange-account-2]
|
||||
# What is the payto://-URL of the exchange (to generate wire response)
|
||||
PAYTO_URI = "payto://x-taler-bank/localhost:8082/Exchange"
|
||||
enable_debit = YES
|
||||
enable_credit = YES
|
||||
|
||||
[exchange-accountcredentials-2]
|
||||
# What is the bank account (with the "Taler Bank" demo system)? Must end with "/".
|
||||
WIRE_GATEWAY_URL = http://localhost:8082/Exchange/
|
||||
# Authentication information for basic authentication
|
||||
WIRE_GATEWAY_AUTH_METHOD = "basic"
|
||||
username = Exchange
|
||||
password = x
|
||||
|
||||
|
||||
|
||||
|
||||
# Sections starting with "coin_" specify which denominations
|
||||
# the exchange should support (and their respective fee structure)
|
||||
[coin_eur_ct_1]
|
||||
value = EUR:0.01
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.00
|
||||
fee_deposit = EUR:0.00
|
||||
fee_refresh = EUR:0.01
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_ct_10]
|
||||
value = EUR:0.10
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_1]
|
||||
value = EUR:1
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_5]
|
||||
value = EUR:5
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_10]
|
||||
value = EUR:10
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
@ -81,6 +81,7 @@ fee_withdraw = EUR:0.00
|
||||
fee_deposit = EUR:0.00
|
||||
fee_refresh = EUR:0.01
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 2048
|
||||
|
||||
[coin_eur_ct_10]
|
||||
@ -92,6 +93,7 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 2048
|
||||
|
||||
[coin_eur_1]
|
||||
@ -103,6 +105,7 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 2048
|
||||
|
||||
[coin_eur_5]
|
||||
@ -114,6 +117,7 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 2048
|
||||
|
||||
[coin_eur_10]
|
||||
@ -125,4 +129,5 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 2048
|
126
src/benchmark/benchmark-cs.conf
Normal file
126
src/benchmark/benchmark-cs.conf
Normal file
@ -0,0 +1,126 @@
|
||||
# This file is in the public domain.
|
||||
#
|
||||
[paths]
|
||||
# Persistent data storage for the testcase
|
||||
# This value is a default for `taler_config_home'
|
||||
TALER_TEST_HOME = exchange_benchmark_home/
|
||||
|
||||
[taler]
|
||||
# Currency supported by the exchange (can only be one)
|
||||
CURRENCY = EUR
|
||||
CURRENCY_ROUND_UNIT = EUR:0.01
|
||||
|
||||
[exchange]
|
||||
|
||||
SIGNKEY_LEGAL_DURATION = 2 years
|
||||
|
||||
# HTTP port the exchange listens to
|
||||
PORT = 8081
|
||||
# Master public key used to sign the exchange's various keys
|
||||
MASTER_PUBLIC_KEY = 98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG
|
||||
# How to access our database
|
||||
DB = postgres
|
||||
# Base URL of the exchange. Must be set to a URL where the
|
||||
# exchange (or the twister) is actually listening.
|
||||
BASE_URL = "http://localhost:8081/"
|
||||
|
||||
AGGREGATOR_SHARD_SIZE = 67108864
|
||||
#AGGREGATOR_SHARD_SIZE = 2147483648
|
||||
|
||||
|
||||
|
||||
WIREWATCH_IDLE_SLEEP_INTERVAL = 5 ms
|
||||
|
||||
[exchange-offline]
|
||||
MASTER_PRIV_FILE = ${TALER_DATA_HOME}/exchange/offline-keys/master.priv
|
||||
|
||||
[auditor]
|
||||
BASE_URL = "http://localhost:8083/"
|
||||
|
||||
[exchangedb-postgres]
|
||||
CONFIG = "postgres:///talercheck"
|
||||
|
||||
[benchmark-remote-exchange]
|
||||
HOST = localhost
|
||||
# Adjust $HOME to match remote target!
|
||||
DIR = $HOME/repos/taler/exchange/src/benchmark
|
||||
|
||||
[bank]
|
||||
HTTP_PORT = 8082
|
||||
SERVE = http
|
||||
MAX_DEBT = EUR:100000000000.0
|
||||
MAX_DEBT_BANK = EUR:1000000000000000.0
|
||||
|
||||
[benchmark]
|
||||
USER_PAYTO_URI = payto://x-taler-bank/localhost:8082/42
|
||||
|
||||
[exchange-account-test]
|
||||
# What is the bank account (with the "Taler Bank" demo system)? Must end with "/".
|
||||
PAYTO_URI = "payto://x-taler-bank/localhost/Exchange"
|
||||
# Authentication information for basic authentication
|
||||
ENABLE_DEBIT = YES
|
||||
ENABLE_CREDIT = YES
|
||||
|
||||
[exchange-accountcredentials-test]
|
||||
WIRE_GATEWAY_URL = http://localhost:8082/Exchange/
|
||||
WIRE_GATEWAY_AUTH_METHOD = "basic"
|
||||
USERNAME = Exchange
|
||||
PASSWORD = x
|
||||
|
||||
|
||||
# Sections starting with "coin_" specify which denominations
|
||||
# the exchange should support (and their respective fee structure)
|
||||
[coin_eur_ct_1]
|
||||
value = EUR:0.01
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.00
|
||||
fee_deposit = EUR:0.00
|
||||
fee_refresh = EUR:0.01
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_ct_10]
|
||||
value = EUR:0.10
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_1]
|
||||
value = EUR:1
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_5]
|
||||
value = EUR:5
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_10]
|
||||
value = EUR:10
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
@ -79,6 +79,7 @@ fee_withdraw = EUR:0.00
|
||||
fee_deposit = EUR:0.00
|
||||
fee_refresh = EUR:0.01
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 2048
|
||||
|
||||
[coin_eur_ct_10]
|
||||
@ -90,6 +91,7 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 2048
|
||||
|
||||
[coin_eur_1]
|
||||
@ -101,6 +103,7 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 2048
|
||||
|
||||
[coin_eur_5]
|
||||
@ -112,6 +115,7 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 2048
|
||||
|
||||
[coin_eur_10]
|
||||
@ -123,4 +127,5 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 2048
|
@ -228,7 +228,7 @@ struct Merchant
|
||||
/**
|
||||
* Salt used when computing @e h_wire.
|
||||
*/
|
||||
struct TALER_WireSalt wire_salt;
|
||||
struct TALER_WireSaltP wire_salt;
|
||||
|
||||
/**
|
||||
* Account information for the merchant.
|
||||
@ -490,8 +490,10 @@ run (void *cls,
|
||||
struct TALER_CoinPubHash c_hash;
|
||||
struct TALER_PlanchetDetail pd;
|
||||
struct TALER_BlindedDenominationSignature bds;
|
||||
union TALER_DenominationBlindingKeyP bks;
|
||||
struct TALER_PlanchetSecretsP ps;
|
||||
struct TALER_ExchangeWithdrawValues alg_values;
|
||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||
union TALER_DenominationBlindingKeyP bks;
|
||||
|
||||
RANDOMIZE (&coin_pub);
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
@ -499,6 +501,7 @@ run (void *cls,
|
||||
&denom_pub,
|
||||
TALER_DENOMINATION_RSA,
|
||||
1024));
|
||||
alg_values.cipher = TALER_DENOMINATION_RSA;
|
||||
TALER_denom_pub_hash (&denom_pub,
|
||||
&h_denom_pub);
|
||||
make_amountN (2, 0, &issue.properties.value);
|
||||
@ -518,21 +521,23 @@ run (void *cls,
|
||||
return;
|
||||
}
|
||||
|
||||
TALER_blinding_secret_create (&bks);
|
||||
|
||||
TALER_planchet_blinding_secret_create (&ps,
|
||||
&alg_values,
|
||||
&bks);
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_denom_blind (&denom_pub,
|
||||
&bks,
|
||||
NULL, /* FIXME-oec */
|
||||
&coin_pub,
|
||||
&alg_values,
|
||||
&c_hash,
|
||||
&pd.coin_ev,
|
||||
&pd.coin_ev_size));
|
||||
&pd.blinded_planchet));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_denom_sign_blinded (&bds,
|
||||
&pk,
|
||||
pd.coin_ev,
|
||||
pd.coin_ev_size));
|
||||
GNUNET_free (pd.coin_ev);
|
||||
&pd.blinded_planchet));
|
||||
TALER_blinded_planchet_free (&pd.blinded_planchet);
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_denom_sig_unblind (&denom_sig,
|
||||
&bds,
|
||||
|
@ -178,6 +178,7 @@ run (void *cls,
|
||||
"sent response\n");
|
||||
continue;
|
||||
}
|
||||
#if FIXME_FLORIAN
|
||||
if (0 == strcmp ("setup_refresh_planchet", op))
|
||||
{
|
||||
struct TALER_TransferSecretP transfer_secret;
|
||||
@ -204,7 +205,7 @@ run (void *cls,
|
||||
global_ret = 1;
|
||||
return;
|
||||
}
|
||||
TALER_planchet_setup_refresh (&transfer_secret,
|
||||
TALER_transfer_secret_to_planchet_secret (&transfer_secret,
|
||||
coin_index,
|
||||
&ps);
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&ps.coin_priv.eddsa_priv,
|
||||
@ -222,6 +223,7 @@ run (void *cls,
|
||||
"sent response\n");
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"unsupported operation '%s'\n",
|
||||
op);
|
||||
|
@ -2531,10 +2531,10 @@ do_download (char *const *args)
|
||||
* #GNUNET_SYSERR if keys changed from what we remember or other error
|
||||
*/
|
||||
static int
|
||||
tofu_check (const struct TALER_SecurityModulePublicKeyP secm[2])
|
||||
tofu_check (const struct TALER_SecurityModulePublicKeySetP *secmset)
|
||||
{
|
||||
char *fn;
|
||||
struct TALER_SecurityModulePublicKeyP old[2];
|
||||
struct TALER_SecurityModulePublicKeySetP oldset;
|
||||
ssize_t ret;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
@ -2552,11 +2552,11 @@ tofu_check (const struct TALER_SecurityModulePublicKeyP secm[2])
|
||||
GNUNET_DISK_file_test (fn))
|
||||
{
|
||||
ret = GNUNET_DISK_fn_read (fn,
|
||||
&old,
|
||||
sizeof (old));
|
||||
&oldset,
|
||||
sizeof (oldset));
|
||||
if (GNUNET_SYSERR != ret)
|
||||
{
|
||||
if (ret != sizeof (old))
|
||||
if (ret != sizeof (oldset))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"File `%s' corrupt\n",
|
||||
@ -2565,9 +2565,9 @@ tofu_check (const struct TALER_SecurityModulePublicKeyP secm[2])
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
/* TOFU check */
|
||||
if (0 != memcmp (old,
|
||||
secm,
|
||||
sizeof (old)))
|
||||
if (0 != memcmp (&oldset,
|
||||
secmset,
|
||||
sizeof (*secmset)))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Fatal: security module keys changed (file `%s')!\n",
|
||||
@ -2608,7 +2608,7 @@ tofu_check (const struct TALER_SecurityModulePublicKeyP secm[2])
|
||||
GNUNET_free (key);
|
||||
if (0 !=
|
||||
GNUNET_memcmp (&k,
|
||||
&secm[1]))
|
||||
&secmset->eddsa))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"ESIGN security module key does not match SECM_ESIGN_PUBKEY in configuration\n");
|
||||
@ -2639,13 +2639,44 @@ tofu_check (const struct TALER_SecurityModulePublicKeyP secm[2])
|
||||
GNUNET_free (key);
|
||||
if (0 !=
|
||||
GNUNET_memcmp (&k,
|
||||
&secm[0]))
|
||||
&secmset->rsa))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"DENOM security module key does not match SECM_DENOM_PUBKEY in configuration\n");
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
}
|
||||
if (GNUNET_OK ==
|
||||
GNUNET_CONFIGURATION_get_value_string (kcfg,
|
||||
"exchange-offline",
|
||||
"SECM_DENOM_CS_PUBKEY",
|
||||
&key))
|
||||
{
|
||||
struct TALER_SecurityModulePublicKeyP k;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_STRINGS_string_to_data (key,
|
||||
strlen (key),
|
||||
&k,
|
||||
sizeof (k)))
|
||||
{
|
||||
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
||||
"exchange-offline",
|
||||
"SECM_DENOM_CS_PUBKEY",
|
||||
"key malformed");
|
||||
GNUNET_free (key);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
GNUNET_free (key);
|
||||
if (0 !=
|
||||
GNUNET_memcmp (&k,
|
||||
&secmset->cs))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"DENOM security module key does not match SECM_DENOM_CS_PUBKEY in configuration\n");
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_DISK_directory_create_for_file (fn))
|
||||
@ -2659,8 +2690,8 @@ tofu_check (const struct TALER_SecurityModulePublicKeyP secm[2])
|
||||
/* persist keys for future runs */
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_DISK_fn_write (fn,
|
||||
secm,
|
||||
sizeof (old),
|
||||
secmset,
|
||||
sizeof (oldset),
|
||||
GNUNET_DISK_PERM_USER_READ))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
@ -2766,11 +2797,14 @@ show_signkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub,
|
||||
* Output @a denomkeys for human consumption.
|
||||
*
|
||||
* @param secm_pub security module public key used to sign the denominations
|
||||
* element 0: RSA
|
||||
* element 1: CS
|
||||
* @param denomkeys keys to output
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static int
|
||||
show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub,
|
||||
show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
|
||||
const struct TALER_SecurityModulePublicKeyP *secm_pub_cs,
|
||||
const json_t *denomkeys)
|
||||
{
|
||||
size_t index;
|
||||
@ -2863,7 +2897,21 @@ show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub,
|
||||
section_name,
|
||||
stamp_start,
|
||||
duration,
|
||||
secm_pub,
|
||||
secm_pub_rsa,
|
||||
&secm_sig);
|
||||
}
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
{
|
||||
struct TALER_CsPubHashP h_cs;
|
||||
|
||||
TALER_cs_pub_hash (&denom_pub.details.cs_public_key,
|
||||
&h_cs);
|
||||
ok = TALER_exchange_secmod_cs_verify (&h_cs,
|
||||
section_name,
|
||||
stamp_start,
|
||||
duration,
|
||||
secm_pub_cs,
|
||||
&secm_sig);
|
||||
}
|
||||
break;
|
||||
@ -3018,7 +3066,7 @@ do_show (char *const *args)
|
||||
json_t *denomkeys;
|
||||
json_t *signkeys;
|
||||
struct TALER_MasterPublicKeyP mpub;
|
||||
struct TALER_SecurityModulePublicKeyP secm[2];
|
||||
struct TALER_SecurityModulePublicKeySetP secmset;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_json ("future_denoms",
|
||||
&denomkeys),
|
||||
@ -3027,9 +3075,11 @@ do_show (char *const *args)
|
||||
GNUNET_JSON_spec_fixed_auto ("master_pub",
|
||||
&mpub),
|
||||
GNUNET_JSON_spec_fixed_auto ("denom_secmod_public_key",
|
||||
&secm[0]),
|
||||
&secmset.rsa),
|
||||
GNUNET_JSON_spec_fixed_auto ("denom_secmod_cs_public_key",
|
||||
&secmset.cs),
|
||||
GNUNET_JSON_spec_fixed_auto ("signkey_secmod_public_key",
|
||||
&secm[1]),
|
||||
&secmset.eddsa),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
@ -3070,7 +3120,7 @@ do_show (char *const *args)
|
||||
return;
|
||||
}
|
||||
if (GNUNET_SYSERR ==
|
||||
tofu_check (secm))
|
||||
tofu_check (&secmset))
|
||||
{
|
||||
global_ret = EXIT_FAILURE;
|
||||
test_shutdown ();
|
||||
@ -3079,10 +3129,11 @@ do_show (char *const *args)
|
||||
return;
|
||||
}
|
||||
if ( (GNUNET_OK !=
|
||||
show_signkeys (&secm[1],
|
||||
show_signkeys (&secmset.eddsa,
|
||||
signkeys)) ||
|
||||
(GNUNET_OK !=
|
||||
show_denomkeys (&secm[0],
|
||||
show_denomkeys (&secmset.rsa,
|
||||
&secmset.cs,
|
||||
denomkeys)) )
|
||||
{
|
||||
global_ret = EXIT_FAILURE;
|
||||
@ -3200,12 +3251,15 @@ sign_signkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub,
|
||||
* Sign @a denomkeys with offline key.
|
||||
*
|
||||
* @param secm_pub security module public key used to sign the denominations
|
||||
* element 0: RSA
|
||||
* element 1: CS
|
||||
* @param denomkeys keys to output
|
||||
* @param[in,out] result array where to output the signatures
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub,
|
||||
sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub_rsa,
|
||||
const struct TALER_SecurityModulePublicKeyP *secm_pub_cs,
|
||||
const json_t *denomkeys,
|
||||
json_t *result)
|
||||
{
|
||||
@ -3300,7 +3354,31 @@ sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub,
|
||||
section_name,
|
||||
stamp_start,
|
||||
duration,
|
||||
secm_pub,
|
||||
secm_pub_rsa,
|
||||
&secm_sig))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Invalid security module signature for denomination key %s (aborting)\n",
|
||||
GNUNET_h2s (&h_denom_pub.hash));
|
||||
global_ret = EXIT_FAILURE;
|
||||
test_shutdown ();
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
{
|
||||
struct TALER_CsPubHashP h_cs;
|
||||
|
||||
TALER_cs_pub_hash (&denom_pub.details.cs_public_key,
|
||||
&h_cs);
|
||||
if (GNUNET_OK !=
|
||||
TALER_exchange_secmod_cs_verify (&h_cs,
|
||||
section_name,
|
||||
stamp_start,
|
||||
duration,
|
||||
secm_pub_cs,
|
||||
&secm_sig))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
@ -3364,7 +3442,7 @@ do_sign (char *const *args)
|
||||
json_t *denomkeys;
|
||||
json_t *signkeys;
|
||||
struct TALER_MasterPublicKeyP mpub;
|
||||
struct TALER_SecurityModulePublicKeyP secm[2];
|
||||
struct TALER_SecurityModulePublicKeySetP secmset;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_json ("future_denoms",
|
||||
&denomkeys),
|
||||
@ -3373,9 +3451,11 @@ do_sign (char *const *args)
|
||||
GNUNET_JSON_spec_fixed_auto ("master_pub",
|
||||
&mpub),
|
||||
GNUNET_JSON_spec_fixed_auto ("denom_secmod_public_key",
|
||||
&secm[0]),
|
||||
&secmset.rsa),
|
||||
GNUNET_JSON_spec_fixed_auto ("denom_secmod_cs_public_key",
|
||||
&secmset.cs),
|
||||
GNUNET_JSON_spec_fixed_auto ("signkey_secmod_public_key",
|
||||
&secm[1]),
|
||||
&secmset.eddsa),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
@ -3419,7 +3499,7 @@ do_sign (char *const *args)
|
||||
return;
|
||||
}
|
||||
if (GNUNET_SYSERR ==
|
||||
tofu_check (secm))
|
||||
tofu_check (&secmset))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Fatal: security module keys changed!\n");
|
||||
@ -3436,11 +3516,12 @@ do_sign (char *const *args)
|
||||
GNUNET_assert (NULL != signkey_sig_array);
|
||||
GNUNET_assert (NULL != denomkey_sig_array);
|
||||
if ( (GNUNET_OK !=
|
||||
sign_signkeys (&secm[1],
|
||||
sign_signkeys (&secmset.eddsa,
|
||||
signkeys,
|
||||
signkey_sig_array)) ||
|
||||
(GNUNET_OK !=
|
||||
sign_denomkeys (&secm[0],
|
||||
sign_denomkeys (&secmset.rsa,
|
||||
&secmset.cs,
|
||||
denomkeys,
|
||||
denomkey_sig_array)) )
|
||||
{
|
||||
|
@ -79,6 +79,7 @@ taler_exchange_transfer_LDADD = \
|
||||
taler_exchange_httpd_SOURCES = \
|
||||
taler-exchange-httpd.c taler-exchange-httpd.h \
|
||||
taler-exchange-httpd_auditors.c taler-exchange-httpd_auditors.h \
|
||||
taler-exchange-httpd_csr.c taler-exchange-httpd_csr \
|
||||
taler-exchange-httpd_db.c taler-exchange-httpd_db.h \
|
||||
taler-exchange-httpd_deposit.c taler-exchange-httpd_deposit.h \
|
||||
taler-exchange-httpd_deposits_get.c taler-exchange-httpd_deposits_get.h \
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <limits.h>
|
||||
#include "taler_mhd_lib.h"
|
||||
#include "taler-exchange-httpd_auditors.h"
|
||||
#include "taler-exchange-httpd_csr.h"
|
||||
#include "taler-exchange-httpd_deposit.h"
|
||||
#include "taler-exchange-httpd_deposits_get.h"
|
||||
#include "taler-exchange-httpd_extensions.h"
|
||||
@ -910,6 +911,13 @@ handle_mhd_request (void *cls,
|
||||
.method = MHD_HTTP_METHOD_GET,
|
||||
.handler.get = &TEH_handler_wire
|
||||
},
|
||||
/* request R, used in clause schnorr withdraw and refresh */
|
||||
{
|
||||
.url = "csr",
|
||||
.method = MHD_HTTP_METHOD_POST,
|
||||
.handler.post = &TEH_handler_csr,
|
||||
.nargs = 0
|
||||
},
|
||||
/* Withdrawing coins / interaction with reserves */
|
||||
{
|
||||
.url = "reserves",
|
||||
|
206
src/exchange/taler-exchange-httpd_csr.c
Normal file
206
src/exchange/taler-exchange-httpd_csr.c
Normal file
@ -0,0 +1,206 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2021 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation; either version 3,
|
||||
or (at your option) any later version.
|
||||
|
||||
TALER is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General
|
||||
Public License along with TALER; see the file COPYING. If not,
|
||||
see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file taler-exchange-httpd_csr.c
|
||||
* @brief Handle /csr requests
|
||||
* @author Lucien Heuzeveldt
|
||||
* @author Gian Demarmles
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include <jansson.h>
|
||||
#include "taler_json_lib.h"
|
||||
#include "taler_mhd_lib.h"
|
||||
#include "taler-exchange-httpd_csr.h"
|
||||
#include "taler-exchange-httpd_responses.h"
|
||||
#include "taler-exchange-httpd_keys.h"
|
||||
|
||||
|
||||
MHD_RESULT
|
||||
TEH_handler_csr (struct TEH_RequestContext *rc,
|
||||
const json_t *root,
|
||||
const char *const args[])
|
||||
{
|
||||
unsigned int csr_requests_num;
|
||||
json_t *csr_requests;
|
||||
json_t *csr_response;
|
||||
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_json ("nks",
|
||||
&csr_requests),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
enum TALER_ErrorCode ec;
|
||||
struct TEH_DenominationKey *dk;
|
||||
|
||||
(void) args;
|
||||
|
||||
// parse input
|
||||
{
|
||||
enum GNUNET_GenericReturnValue res;
|
||||
|
||||
res = TALER_MHD_parse_json_data (rc->connection,
|
||||
root,
|
||||
spec);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
if (GNUNET_OK != res)
|
||||
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
|
||||
}
|
||||
csr_requests_num = json_array_size (csr_requests);
|
||||
if (TALER_MAX_FRESH_COINS <= csr_requests_num)
|
||||
{
|
||||
return TALER_MHD_reply_with_error (
|
||||
rc->connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
// FIXME: generalize error message
|
||||
TALER_EC_EXCHANGE_REFRESHES_REVEAL_NEW_DENOMS_ARRAY_SIZE_EXCESSIVE,
|
||||
NULL);
|
||||
}
|
||||
struct TALER_CsNonce nonces[GNUNET_NZL (csr_requests_num)];
|
||||
struct TALER_DenominationHash denom_pub_hashes[GNUNET_NZL (csr_requests_num)];
|
||||
for (unsigned int i = 0; i < csr_requests_num; i++)
|
||||
{
|
||||
struct TALER_CsNonce *nonce = &nonces[i];
|
||||
struct TALER_DenominationHash *denom_pub_hash = &denom_pub_hashes[i];
|
||||
struct GNUNET_JSON_Specification csr_spec[] = {
|
||||
GNUNET_JSON_spec_fixed ("nonce",
|
||||
nonce,
|
||||
sizeof (struct TALER_CsNonce)),
|
||||
GNUNET_JSON_spec_fixed ("denom_pub_hash",
|
||||
denom_pub_hash,
|
||||
sizeof (struct TALER_DenominationHash)),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
enum GNUNET_GenericReturnValue res;
|
||||
|
||||
res = TALER_MHD_parse_json_array (rc->connection,
|
||||
root,
|
||||
csr_spec,
|
||||
i,
|
||||
-1);
|
||||
if (GNUNET_OK != res)
|
||||
return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
|
||||
}
|
||||
|
||||
struct TALER_DenominationCSPublicRPairP r_pubs[GNUNET_NZL (csr_requests_num)];
|
||||
for (unsigned int i = 0; i < csr_requests_num; i++)
|
||||
{
|
||||
const struct TALER_CsNonce *nonce = &nonces[i];
|
||||
const struct TALER_DenominationHash *denom_pub_hash = &denom_pub_hashes[i];
|
||||
struct TALER_DenominationCSPublicRPairP *r_pub = &r_pubs[i];
|
||||
|
||||
// check denomination referenced by denom_pub_hash
|
||||
{
|
||||
struct TEH_KeyStateHandle *ksh;
|
||||
|
||||
ksh = TEH_keys_get_state ();
|
||||
if (NULL == ksh)
|
||||
{
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
|
||||
NULL);
|
||||
}
|
||||
dk = TEH_keys_denomination_by_hash2 (ksh,
|
||||
denom_pub_hash,
|
||||
NULL,
|
||||
NULL);
|
||||
if (NULL == dk)
|
||||
{
|
||||
return TEH_RESPONSE_reply_unknown_denom_pub_hash (
|
||||
rc->connection,
|
||||
&denom_pub_hash[i]);
|
||||
}
|
||||
if (GNUNET_TIME_absolute_is_past (dk->meta.expire_withdraw.abs_time))
|
||||
{
|
||||
/* This denomination is past the expiration time for withdraws/refreshes*/
|
||||
return TEH_RESPONSE_reply_expired_denom_pub_hash (
|
||||
rc->connection,
|
||||
denom_pub_hash,
|
||||
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
|
||||
"CSR");
|
||||
}
|
||||
if (GNUNET_TIME_absolute_is_future (dk->meta.start.abs_time))
|
||||
{
|
||||
/* This denomination is not yet valid, no need to check
|
||||
for idempotency! */
|
||||
return TEH_RESPONSE_reply_expired_denom_pub_hash (
|
||||
rc->connection,
|
||||
denom_pub_hash,
|
||||
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
|
||||
"CSR");
|
||||
}
|
||||
if (dk->recoup_possible)
|
||||
{
|
||||
/* This denomination has been revoked */
|
||||
return TEH_RESPONSE_reply_expired_denom_pub_hash (
|
||||
rc->connection,
|
||||
denom_pub_hash,
|
||||
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED,
|
||||
"CSR");
|
||||
}
|
||||
if (TALER_DENOMINATION_CS != dk->denom_pub.cipher)
|
||||
{
|
||||
// denomination is valid but not CS
|
||||
return TEH_RESPONSE_reply_invalid_denom_cipher_for_operation (
|
||||
rc->connection,
|
||||
denom_pub_hash);
|
||||
}
|
||||
}
|
||||
|
||||
// derive r_pub
|
||||
// FIXME: bundle all requests into one derivation request (TEH_keys_..., crypto helper, security module)
|
||||
ec = TEH_keys_denomination_cs_r_pub (denom_pub_hash,
|
||||
nonce,
|
||||
r_pub);
|
||||
if (TALER_EC_NONE != ec)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TALER_MHD_reply_with_ec (rc->connection,
|
||||
ec,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// send response
|
||||
csr_response = json_array ();
|
||||
for (unsigned int i = 0; i < csr_requests_num; i++)
|
||||
{
|
||||
const struct TALER_DenominationCSPublicRPairP *r_pub = &r_pubs[i];
|
||||
json_t *csr_obj;
|
||||
|
||||
csr_obj = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_varsize ("r_pub_0",
|
||||
&r_pub->r_pub[0],
|
||||
sizeof(struct GNUNET_CRYPTO_CsRPublic)),
|
||||
GNUNET_JSON_pack_data_varsize ("r_pub_1",
|
||||
&r_pub->r_pub[1],
|
||||
sizeof(struct GNUNET_CRYPTO_CsRPublic)));
|
||||
GNUNET_assert (NULL != csr_obj);
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (csr_response,
|
||||
csr_obj));
|
||||
}
|
||||
return TALER_MHD_reply_json (rc->connection,
|
||||
csr_response,
|
||||
MHD_HTTP_OK);
|
||||
}
|
||||
|
||||
|
||||
/* end of taler-exchange-httpd_csr.c */
|
43
src/exchange/taler-exchange-httpd_csr.h
Normal file
43
src/exchange/taler-exchange-httpd_csr.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2021 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Affero General Public License as published by the Free Software
|
||||
Foundation; either version 3, or (at your option) any later version.
|
||||
|
||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License along with
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file taler-exchange-httpd_csr.h
|
||||
* @brief Handle /csr requests
|
||||
* @author Lucien Heuzeveldt
|
||||
* @author Gian Demarmles
|
||||
*/
|
||||
#ifndef TALER_EXCHANGE_HTTPD_CSR_H
|
||||
#define TALER_EXCHANGE_HTTPD_CSR_H
|
||||
|
||||
#include <microhttpd.h>
|
||||
#include "taler-exchange-httpd.h"
|
||||
|
||||
|
||||
/**
|
||||
* Handle a "/csr" request. Parses the "nonce" and
|
||||
* the "denom_pub_hash" (identifying a denomination) used to derive the r_pub.
|
||||
*
|
||||
* @param rc request context
|
||||
* @param root uploaded JSON data
|
||||
* @param args empty array
|
||||
* @return MHD result code
|
||||
*/
|
||||
MHD_RESULT
|
||||
TEH_handler_csr (struct TEH_RequestContext *rc,
|
||||
const json_t *root,
|
||||
const char *const args[]);
|
||||
|
||||
#endif
|
@ -356,6 +356,15 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
||||
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED,
|
||||
"DEPOSIT");
|
||||
}
|
||||
if (dk->denom_pub.cipher != deposit.coin.denom_sig.cipher)
|
||||
{
|
||||
/* denomination cipher and denomination signature cipher not the same */
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_EXCHANGE_GENERIC_CIPHER_MISMATCH,
|
||||
NULL);
|
||||
}
|
||||
|
||||
deposit.deposit_fee = dk->meta.fee_deposit;
|
||||
/* check coin signature */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2020, 2021 Taler Systems SA
|
||||
Copyright (C) 2020-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Affero General Public License as published by the Free Software
|
||||
@ -103,6 +103,11 @@ struct HelperDenomination
|
||||
*/
|
||||
struct TALER_RsaPubHashP h_rsa;
|
||||
|
||||
/**
|
||||
* Hash of the CS key.
|
||||
*/
|
||||
struct TALER_CsPubHashP h_cs;
|
||||
|
||||
} h_details;
|
||||
|
||||
/**
|
||||
@ -188,7 +193,12 @@ struct HelperState
|
||||
/**
|
||||
* Handle for the denom/RSA helper.
|
||||
*/
|
||||
struct TALER_CRYPTO_RsaDenominationHelper *dh;
|
||||
struct TALER_CRYPTO_RsaDenominationHelper *rsadh;
|
||||
|
||||
/**
|
||||
* Handle for the denom/CS helper.
|
||||
*/
|
||||
struct TALER_CRYPTO_CsDenominationHelper *csdh;
|
||||
|
||||
/**
|
||||
* Map from H(denom_pub) to `struct HelperDenomination` entries.
|
||||
@ -200,6 +210,11 @@ struct HelperState
|
||||
*/
|
||||
struct GNUNET_CONTAINER_MultiHashMap *rsa_keys;
|
||||
|
||||
/**
|
||||
* Map from H(cs_pub) to `struct HelperDenomination` entries.
|
||||
*/
|
||||
struct GNUNET_CONTAINER_MultiHashMap *cs_keys;
|
||||
|
||||
/**
|
||||
* Map from `struct TALER_ExchangePublicKey` to `struct HelperSignkey`
|
||||
* entries. Based on the fact that a `struct GNUNET_PeerIdentity` is also
|
||||
@ -424,7 +439,12 @@ static struct GNUNET_TIME_Relative signkey_legal_duration;
|
||||
/**
|
||||
* RSA security module public key, all zero if not known.
|
||||
*/
|
||||
static struct TALER_SecurityModulePublicKeyP denom_sm_pub;
|
||||
static struct TALER_SecurityModulePublicKeyP denom_rsa_sm_pub;
|
||||
|
||||
/**
|
||||
* CS security module public key, all zero if not known.
|
||||
*/
|
||||
static struct TALER_SecurityModulePublicKeyP denom_cs_sm_pub;
|
||||
|
||||
/**
|
||||
* EdDSA security module public key, all zero if not known.
|
||||
@ -541,6 +561,7 @@ check_dk (void *cls,
|
||||
if (TALER_DENOMINATION_RSA == dk->denom_pub.cipher)
|
||||
GNUNET_assert (GNUNET_CRYPTO_rsa_public_key_check (
|
||||
dk->denom_pub.details.rsa_public_key));
|
||||
// nothing to do for TALER_DENOMINATION_CS
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
@ -609,19 +630,43 @@ clear_response_cache (struct TEH_KeyStateHandle *ksh)
|
||||
* @param sm_pub RSA security module public key to check
|
||||
*/
|
||||
static void
|
||||
check_denom_sm_pub (const struct TALER_SecurityModulePublicKeyP *sm_pub)
|
||||
check_denom_rsa_sm_pub (const struct TALER_SecurityModulePublicKeyP *sm_pub)
|
||||
{
|
||||
if (0 !=
|
||||
GNUNET_memcmp (sm_pub,
|
||||
&denom_sm_pub))
|
||||
&denom_rsa_sm_pub))
|
||||
{
|
||||
if (! GNUNET_is_zero (&denom_sm_pub))
|
||||
if (! GNUNET_is_zero (&denom_rsa_sm_pub))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Our RSA security module changed its key. This must not happen.\n");
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
denom_sm_pub = *sm_pub; /* TOFU ;-) */
|
||||
denom_rsa_sm_pub = *sm_pub; /* TOFU ;-) */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check that the given CS security module's public key is the one
|
||||
* we have pinned. If it does not match, we die hard.
|
||||
*
|
||||
* @param sm_pub RSA security module public key to check
|
||||
*/
|
||||
static void
|
||||
check_denom_cs_sm_pub (const struct TALER_SecurityModulePublicKeyP *sm_pub)
|
||||
{
|
||||
if (0 !=
|
||||
GNUNET_memcmp (sm_pub,
|
||||
&denom_cs_sm_pub))
|
||||
{
|
||||
if (! GNUNET_is_zero (&denom_cs_sm_pub))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Our CS security module changed its key. This must not happen.\n");
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
denom_cs_sm_pub = *sm_pub; /* TOFU ;-) */
|
||||
}
|
||||
}
|
||||
|
||||
@ -659,7 +704,7 @@ check_esign_sm_pub (const struct TALER_SecurityModulePublicKeyP *sm_pub)
|
||||
* @param value the `struct HelperDenomination` to release
|
||||
* @return #GNUNET_OK (continue to iterate)
|
||||
*/
|
||||
static int
|
||||
static enum GNUNET_GenericReturnValue
|
||||
free_denom_cb (void *cls,
|
||||
const struct GNUNET_HashCode *h_denom_pub,
|
||||
void *value)
|
||||
@ -712,6 +757,8 @@ destroy_key_helpers (struct HelperState *hs)
|
||||
hs);
|
||||
GNUNET_CONTAINER_multihashmap_destroy (hs->rsa_keys);
|
||||
hs->rsa_keys = NULL;
|
||||
GNUNET_CONTAINER_multihashmap_destroy (hs->cs_keys);
|
||||
hs->cs_keys = NULL;
|
||||
GNUNET_CONTAINER_multihashmap_destroy (hs->denom_keys);
|
||||
hs->denom_keys = NULL;
|
||||
GNUNET_CONTAINER_multipeermap_iterate (hs->esign_keys,
|
||||
@ -719,10 +766,15 @@ destroy_key_helpers (struct HelperState *hs)
|
||||
hs);
|
||||
GNUNET_CONTAINER_multipeermap_destroy (hs->esign_keys);
|
||||
hs->esign_keys = NULL;
|
||||
if (NULL != hs->dh)
|
||||
if (NULL != hs->rsadh)
|
||||
{
|
||||
TALER_CRYPTO_helper_rsa_disconnect (hs->dh);
|
||||
hs->dh = NULL;
|
||||
TALER_CRYPTO_helper_rsa_disconnect (hs->rsadh);
|
||||
hs->rsadh = NULL;
|
||||
}
|
||||
if (NULL != hs->csdh)
|
||||
{
|
||||
TALER_CRYPTO_helper_cs_disconnect (hs->csdh);
|
||||
hs->csdh = NULL;
|
||||
}
|
||||
if (NULL != hs->esh)
|
||||
{
|
||||
@ -752,8 +804,7 @@ load_age_mask (const char*section_name)
|
||||
/* TODO: optimize by putting this into global? */
|
||||
if (TALER_extensions_is_enabled (age_ext))
|
||||
age_mask = *(struct TALER_AgeMask *) age_ext->config;
|
||||
|
||||
if (age_mask.mask == 0)
|
||||
if (0 == age_mask.mask)
|
||||
{
|
||||
/* Age restriction support is not enabled. Ignore the AGE_RESTRICTED field
|
||||
* for the particular denomination and simply return the null_mask
|
||||
@ -767,7 +818,9 @@ load_age_mask (const char*section_name)
|
||||
"AGE_RESTRICTED")))
|
||||
{
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
if (GNUNET_SYSERR == (ret = GNUNET_CONFIGURATION_get_value_yesno (TEH_cfg,
|
||||
|
||||
if (GNUNET_SYSERR ==
|
||||
(ret = GNUNET_CONFIGURATION_get_value_yesno (TEH_cfg,
|
||||
section_name,
|
||||
"AGE_RESTRICTED")))
|
||||
{
|
||||
@ -778,7 +831,6 @@ load_age_mask (const char*section_name)
|
||||
return null_mask;
|
||||
}
|
||||
}
|
||||
|
||||
return age_mask;
|
||||
}
|
||||
|
||||
@ -795,7 +847,7 @@ load_age_mask (const char*section_name)
|
||||
* zero if the key has been revoked or purged
|
||||
* @param validity_duration how long does the key remain available for signing;
|
||||
* zero if the key has been revoked or purged
|
||||
* @param h_denom_pub hash of the @a denom_pub that is available (or was purged)
|
||||
* @param h_rsa hash of the @a denom_pub that is available (or was purged)
|
||||
* @param denom_pub the public key itself, NULL if the key was revoked or purged
|
||||
* @param sm_pub public key of the security module, NULL if the key was revoked or purged
|
||||
* @param sm_sig signature from the security module, NULL if the key was revoked or purged
|
||||
@ -822,6 +874,7 @@ helper_rsa_cb (
|
||||
GNUNET_STRINGS_relative_time_to_string (validity_duration,
|
||||
GNUNET_NO));
|
||||
key_generation++;
|
||||
// FIXME: wait for sync?
|
||||
TEH_resume_keys_requests (false);
|
||||
hd = GNUNET_CONTAINER_multihashmap_get (hs->rsa_keys,
|
||||
&h_rsa->hash);
|
||||
@ -832,7 +885,7 @@ helper_rsa_cb (
|
||||
return;
|
||||
}
|
||||
GNUNET_assert (NULL != sm_pub);
|
||||
check_denom_sm_pub (sm_pub);
|
||||
check_denom_rsa_sm_pub (sm_pub);
|
||||
hd = GNUNET_new (struct HelperDenomination);
|
||||
hd->start_time = start_time;
|
||||
hd->validity_duration = validity_duration;
|
||||
@ -864,6 +917,87 @@ helper_rsa_cb (
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called with information about available CS keys for signing. Usually
|
||||
* only called once per key upon connect. Also called again in case a key is
|
||||
* being revoked, in that case with an @a end_time of zero.
|
||||
*
|
||||
* @param cls closure with the `struct HelperState *`
|
||||
* @param section_name name of the denomination type in the configuration;
|
||||
* NULL if the key has been revoked or purged
|
||||
* @param start_time when does the key become available for signing;
|
||||
* zero if the key has been revoked or purged
|
||||
* @param validity_duration how long does the key remain available for signing;
|
||||
* zero if the key has been revoked or purged
|
||||
* @param h_cs hash of the @a denom_pub that is available (or was purged)
|
||||
* @param denom_pub the public key itself, NULL if the key was revoked or purged
|
||||
* @param sm_pub public key of the security module, NULL if the key was revoked or purged
|
||||
* @param sm_sig signature from the security module, NULL if the key was revoked or purged
|
||||
* The signature was already verified against @a sm_pub.
|
||||
*/
|
||||
static void
|
||||
helper_cs_cb (
|
||||
void *cls,
|
||||
const char *section_name,
|
||||
struct GNUNET_TIME_Timestamp start_time,
|
||||
struct GNUNET_TIME_Relative validity_duration,
|
||||
const struct TALER_CsPubHashP *h_cs,
|
||||
const struct TALER_DenominationPublicKey *denom_pub,
|
||||
const struct TALER_SecurityModulePublicKeyP *sm_pub,
|
||||
const struct TALER_SecurityModuleSignatureP *sm_sig)
|
||||
{
|
||||
struct HelperState *hs = cls;
|
||||
struct HelperDenomination *hd;
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"CS helper announces key %s for denomination type %s with validity %s\n",
|
||||
GNUNET_h2s (&h_cs->hash),
|
||||
section_name,
|
||||
GNUNET_STRINGS_relative_time_to_string (validity_duration,
|
||||
GNUNET_NO));
|
||||
key_generation++;
|
||||
// FIXME: wait for sync?
|
||||
TEH_resume_keys_requests (false);
|
||||
hd = GNUNET_CONTAINER_multihashmap_get (hs->cs_keys,
|
||||
&h_cs->hash);
|
||||
if (NULL != hd)
|
||||
{
|
||||
/* should be just an update (revocation!), so update existing entry */
|
||||
hd->validity_duration = validity_duration;
|
||||
return;
|
||||
}
|
||||
GNUNET_assert (NULL != sm_pub);
|
||||
check_denom_cs_sm_pub (sm_pub);
|
||||
hd = GNUNET_new (struct HelperDenomination);
|
||||
hd->start_time = start_time;
|
||||
hd->validity_duration = validity_duration;
|
||||
hd->h_details.h_cs = *h_cs;
|
||||
hd->sm_sig = *sm_sig;
|
||||
GNUNET_assert (TALER_DENOMINATION_CS == denom_pub->cipher);
|
||||
TALER_denom_pub_deep_copy (&hd->denom_pub,
|
||||
denom_pub);
|
||||
/* load the age mask for the denomination, if applicable */
|
||||
hd->denom_pub.age_mask = load_age_mask (section_name);
|
||||
TALER_denom_pub_hash (&hd->denom_pub,
|
||||
&hd->h_denom_pub);
|
||||
hd->section_name = GNUNET_strdup (section_name);
|
||||
GNUNET_assert (
|
||||
GNUNET_OK ==
|
||||
GNUNET_CONTAINER_multihashmap_put (
|
||||
hs->denom_keys,
|
||||
&hd->h_denom_pub.hash,
|
||||
hd,
|
||||
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
|
||||
GNUNET_assert (
|
||||
GNUNET_OK ==
|
||||
GNUNET_CONTAINER_multihashmap_put (
|
||||
hs->cs_keys,
|
||||
&hd->h_details.h_cs.hash,
|
||||
hd,
|
||||
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called with information about available keys for signing. Usually
|
||||
* only called once per key upon connect. Also called again in case a key is
|
||||
@ -940,13 +1074,24 @@ setup_key_helpers (struct HelperState *hs)
|
||||
hs->rsa_keys
|
||||
= GNUNET_CONTAINER_multihashmap_create (1024,
|
||||
GNUNET_YES);
|
||||
hs->cs_keys
|
||||
= GNUNET_CONTAINER_multihashmap_create (1024,
|
||||
GNUNET_YES);
|
||||
hs->esign_keys
|
||||
= GNUNET_CONTAINER_multipeermap_create (32,
|
||||
GNUNET_NO /* MUST BE NO! */);
|
||||
hs->dh = TALER_CRYPTO_helper_rsa_connect (TEH_cfg,
|
||||
hs->rsadh = TALER_CRYPTO_helper_rsa_connect (TEH_cfg,
|
||||
&helper_rsa_cb,
|
||||
hs);
|
||||
if (NULL == hs->dh)
|
||||
if (NULL == hs->rsadh)
|
||||
{
|
||||
destroy_key_helpers (hs);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
hs->csdh = TALER_CRYPTO_helper_cs_connect (TEH_cfg,
|
||||
&helper_cs_cb,
|
||||
hs);
|
||||
if (NULL == hs->csdh)
|
||||
{
|
||||
destroy_key_helpers (hs);
|
||||
return GNUNET_SYSERR;
|
||||
@ -971,7 +1116,8 @@ setup_key_helpers (struct HelperState *hs)
|
||||
static void
|
||||
sync_key_helpers (struct HelperState *hs)
|
||||
{
|
||||
TALER_CRYPTO_helper_rsa_poll (hs->dh);
|
||||
TALER_CRYPTO_helper_rsa_poll (hs->rsadh);
|
||||
TALER_CRYPTO_helper_cs_poll (hs->csdh);
|
||||
TALER_CRYPTO_helper_esign_poll (hs->esh);
|
||||
}
|
||||
|
||||
@ -984,7 +1130,7 @@ sync_key_helpers (struct HelperState *hs)
|
||||
* @param value a `struct TEH_DenominationKey` to free
|
||||
* @return #GNUNET_OK (continue to iterate)
|
||||
*/
|
||||
static int
|
||||
static enum GNUNET_GenericReturnValue
|
||||
clear_denomination_cb (void *cls,
|
||||
const struct GNUNET_HashCode *h_denom_pub,
|
||||
void *value)
|
||||
@ -1015,7 +1161,7 @@ clear_denomination_cb (void *cls,
|
||||
* @param value a `struct SigningKey` to free
|
||||
* @return #GNUNET_OK (continue to iterate)
|
||||
*/
|
||||
static int
|
||||
static enum GNUNET_GenericReturnValue
|
||||
clear_signkey_cb (void *cls,
|
||||
const struct GNUNET_PeerIdentity *pid,
|
||||
void *value)
|
||||
@ -1255,7 +1401,7 @@ struct GetAuditorSigsContext
|
||||
* @param value a `struct TEH_DenominationKey`
|
||||
* @return #GNUNET_OK (continue to iterate)
|
||||
*/
|
||||
static int
|
||||
static enum GNUNET_GenericReturnValue
|
||||
get_auditor_sigs (void *cls,
|
||||
const struct GNUNET_HashCode *h_denom_pub,
|
||||
void *value)
|
||||
@ -1388,7 +1534,7 @@ struct SignKeyCtx
|
||||
* @param value a `struct SigningKey`
|
||||
* @return #GNUNET_OK (continue to iterate)
|
||||
*/
|
||||
static int
|
||||
static enum GNUNET_GenericReturnValue
|
||||
add_sign_key_cb (void *cls,
|
||||
const struct GNUNET_PeerIdentity *pid,
|
||||
void *value)
|
||||
@ -1457,7 +1603,7 @@ struct DenomKeyCtx
|
||||
* @param value a `struct TEH_DenominationKey`
|
||||
* @return #GNUNET_OK (continue to iterate)
|
||||
*/
|
||||
static int
|
||||
static enum GNUNET_GenericReturnValue
|
||||
add_denom_key_cb (void *cls,
|
||||
const struct GNUNET_HashCode *h_denom_pub,
|
||||
void *value)
|
||||
@ -2265,8 +2411,7 @@ TEH_keys_denomination_by_hash2 (
|
||||
|
||||
struct TALER_BlindedDenominationSignature
|
||||
TEH_keys_denomination_sign (const struct TALER_DenominationHash *h_denom_pub,
|
||||
const void *msg,
|
||||
size_t msg_size,
|
||||
const struct TEH_SignDetails *msg,
|
||||
enum TALER_ErrorCode *ec)
|
||||
{
|
||||
struct TEH_KeyStateHandle *ksh;
|
||||
@ -2289,13 +2434,23 @@ TEH_keys_denomination_sign (const struct TALER_DenominationHash *h_denom_pub,
|
||||
*ec = TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN;
|
||||
return none;
|
||||
}
|
||||
if (msg->cipher != hd->denom_pub.cipher)
|
||||
{
|
||||
*ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
|
||||
return none;
|
||||
}
|
||||
switch (hd->denom_pub.cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
return TALER_CRYPTO_helper_rsa_sign (ksh->helpers->dh,
|
||||
return TALER_CRYPTO_helper_rsa_sign (ksh->helpers->rsadh,
|
||||
&hd->h_details.h_rsa,
|
||||
msg,
|
||||
msg_size,
|
||||
msg->details.rsa_message.msg,
|
||||
msg->details.rsa_message.msg_size,
|
||||
ec);
|
||||
case TALER_DENOMINATION_CS:
|
||||
return TALER_CRYPTO_helper_cs_sign (ksh->helpers->csdh,
|
||||
&hd->h_details.h_cs,
|
||||
&msg->details.cs_message,
|
||||
ec);
|
||||
default:
|
||||
*ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
|
||||
@ -2304,6 +2459,40 @@ TEH_keys_denomination_sign (const struct TALER_DenominationHash *h_denom_pub,
|
||||
}
|
||||
|
||||
|
||||
enum TALER_ErrorCode
|
||||
TEH_keys_denomination_cs_r_pub (const struct
|
||||
TALER_DenominationHash *h_denom_pub,
|
||||
const struct TALER_CsNonce *nonce,
|
||||
struct TALER_DenominationCSPublicRPairP *r_pub)
|
||||
{
|
||||
struct TEH_KeyStateHandle *ksh;
|
||||
struct HelperDenomination *hd;
|
||||
enum TALER_ErrorCode r_derive_ec;
|
||||
|
||||
ksh = TEH_keys_get_state ();
|
||||
if (NULL == ksh)
|
||||
{
|
||||
return TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING;
|
||||
}
|
||||
hd = GNUNET_CONTAINER_multihashmap_get (ksh->helpers->denom_keys,
|
||||
&h_denom_pub->hash);
|
||||
if (NULL == hd)
|
||||
{
|
||||
return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN;
|
||||
}
|
||||
if (TALER_DENOMINATION_CS != hd->denom_pub.cipher)
|
||||
{
|
||||
return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
|
||||
}
|
||||
|
||||
*r_pub = TALER_CRYPTO_helper_cs_r_derive (ksh->helpers->csdh,
|
||||
&hd->h_details.h_cs,
|
||||
nonce,
|
||||
&r_derive_ec);
|
||||
return r_derive_ec;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TEH_keys_denomination_revoke (const struct TALER_DenominationHash *h_denom_pub)
|
||||
{
|
||||
@ -2326,10 +2515,15 @@ TEH_keys_denomination_revoke (const struct TALER_DenominationHash *h_denom_pub)
|
||||
switch (hd->denom_pub.cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
TALER_CRYPTO_helper_rsa_revoke (ksh->helpers->dh,
|
||||
TALER_CRYPTO_helper_rsa_revoke (ksh->helpers->rsadh,
|
||||
&hd->h_details.h_rsa);
|
||||
TEH_keys_update_states ();
|
||||
return;
|
||||
case TALER_DENOMINATION_CS:
|
||||
TALER_CRYPTO_helper_cs_revoke (ksh->helpers->csdh,
|
||||
&hd->h_details.h_cs);
|
||||
TEH_keys_update_states ();
|
||||
return;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
return;
|
||||
@ -2923,7 +3117,8 @@ TEH_keys_management_get_keys_handler (const struct TEH_RequestHandler *rh,
|
||||
.signkeys = json_array ()
|
||||
};
|
||||
|
||||
if (GNUNET_is_zero (&denom_sm_pub))
|
||||
if ( (GNUNET_is_zero (&denom_rsa_sm_pub)) &&
|
||||
(GNUNET_is_zero (&denom_cs_sm_pub)) )
|
||||
{
|
||||
return TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_BAD_GATEWAY,
|
||||
@ -2954,7 +3149,9 @@ TEH_keys_management_get_keys_handler (const struct TEH_RequestHandler *rh,
|
||||
GNUNET_JSON_pack_data_auto ("master_pub",
|
||||
&TEH_master_public_key),
|
||||
GNUNET_JSON_pack_data_auto ("denom_secmod_public_key",
|
||||
&denom_sm_pub),
|
||||
&denom_rsa_sm_pub),
|
||||
GNUNET_JSON_pack_data_auto ("denom_secmod_cs_public_key",
|
||||
&denom_cs_sm_pub),
|
||||
GNUNET_JSON_pack_data_auto ("signkey_secmod_public_key",
|
||||
&esign_sm_pub));
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
|
@ -82,6 +82,42 @@ struct TEH_DenominationKey
|
||||
};
|
||||
|
||||
|
||||
struct TEH_SignDetails_RSA
|
||||
{
|
||||
/**
|
||||
* message to sign
|
||||
*/
|
||||
const void *msg;
|
||||
|
||||
/**
|
||||
* number of bytes in msg
|
||||
*/
|
||||
size_t msg_size;
|
||||
};
|
||||
|
||||
|
||||
struct TEH_SignDetails
|
||||
{
|
||||
/**
|
||||
* Cipher type of the message
|
||||
*/
|
||||
enum TALER_DenominationCipher cipher;
|
||||
|
||||
union
|
||||
{
|
||||
/**
|
||||
* If we use #TALER_DENOMINATION_RSA in @a cipher.
|
||||
*/
|
||||
struct TEH_SignDetails_RSA rsa_message;
|
||||
|
||||
/**
|
||||
* If we use #TALER_DENOMINATION_CS in @a cipher.
|
||||
*/
|
||||
struct TALER_BlindedCsPlanchet cs_message;
|
||||
} details;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Snapshot of the (coin and signing) keys (including private keys) of
|
||||
* the exchange. There can be multiple instances of this struct, as it is
|
||||
@ -179,11 +215,27 @@ TEH_keys_denomination_by_hash2 (struct TEH_KeyStateHandle *ksh,
|
||||
*/
|
||||
struct TALER_BlindedDenominationSignature
|
||||
TEH_keys_denomination_sign (const struct TALER_DenominationHash *h_denom_pub,
|
||||
const void *msg,
|
||||
size_t msg_size,
|
||||
const struct TEH_SignDetails *msg,
|
||||
enum TALER_ErrorCode *ec);
|
||||
|
||||
|
||||
/**
|
||||
* Request to derive CS r_pub using the denomination corresponding to @a h_denom_pub
|
||||
* and @a nonce.
|
||||
*
|
||||
* @param h_denom_pub hash of the public key to use to derive r_pub
|
||||
* @param nonce withdraw/refresh nonce
|
||||
* @param[out] ec set to the error code (or #TALER_EC_NONE on success)
|
||||
* @return r_pub, the value inside the structure will be NULL on failure,
|
||||
* see @a ec for details about the failure
|
||||
*/
|
||||
enum TALER_ErrorCode
|
||||
TEH_keys_denomination_cs_r_pub (const struct
|
||||
TALER_DenominationHash *h_denom_pub,
|
||||
const struct TALER_CsNonce *nonce,
|
||||
struct TALER_DenominationCSPublicRPairP *r_pub);
|
||||
|
||||
|
||||
/**
|
||||
* Revoke the public key associated with @param h_denom_pub .
|
||||
* This function should be called AFTER the database was
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2021 Taler Systems SA
|
||||
Copyright (C) 2014-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Affero General Public License as published by the Free Software
|
||||
@ -183,6 +183,7 @@ melt_transaction (void *cls,
|
||||
}
|
||||
if (! balance_ok)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
TEH_plugin->rollback (TEH_plugin->cls);
|
||||
*mhd_ret
|
||||
= TEH_RESPONSE_reply_coin_insufficient_funds (
|
||||
@ -299,6 +300,9 @@ check_melt_valid (struct MHD_Connection *connection,
|
||||
|
||||
rmc->coin_refresh_fee = dk->meta.fee_refresh;
|
||||
rmc->coin_value = dk->meta.value;
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Melted coin's denomination is worth %s\n",
|
||||
TALER_amount2s (&dk->meta.value));
|
||||
/* sanity-check that "total melt amount > melt fee" */
|
||||
if (0 <
|
||||
TALER_amount_cmp (&rmc->coin_refresh_fee,
|
||||
|
@ -241,18 +241,17 @@ verify_and_execute_recoup_refresh (
|
||||
}
|
||||
|
||||
{
|
||||
void *coin_ev;
|
||||
size_t coin_ev_size;
|
||||
struct TALER_CoinPubHash c_hash;
|
||||
struct TALER_BlindedPlanchet blinded_planchet;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_denom_blind (&dk->denom_pub,
|
||||
coin_bks,
|
||||
NULL, /* FIXME-Oec: TALER_AgeHash * */
|
||||
&coin->coin_pub,
|
||||
NULL, /* FIXME: Implement CS */
|
||||
&c_hash,
|
||||
&coin_ev,
|
||||
&coin_ev_size))
|
||||
&blinded_planchet))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TALER_MHD_reply_with_error (
|
||||
@ -261,10 +260,10 @@ verify_and_execute_recoup_refresh (
|
||||
TALER_EC_EXCHANGE_RECOUP_REFRESH_BLINDING_FAILED,
|
||||
NULL);
|
||||
}
|
||||
TALER_coin_ev_hash (coin_ev,
|
||||
coin_ev_size,
|
||||
TALER_coin_ev_hash (&blinded_planchet,
|
||||
&coin->denom_pub_hash,
|
||||
&h_blind);
|
||||
GNUNET_free (coin_ev);
|
||||
TALER_blinded_planchet_free (&blinded_planchet);
|
||||
}
|
||||
|
||||
pc.coin_sig = coin_sig;
|
||||
|
@ -243,18 +243,17 @@ verify_and_execute_recoup (
|
||||
}
|
||||
|
||||
{
|
||||
void *coin_ev;
|
||||
size_t coin_ev_size;
|
||||
struct TALER_CoinPubHash c_hash;
|
||||
struct TALER_BlindedPlanchet blinded_planchet;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_denom_blind (&dk->denom_pub,
|
||||
coin_bks,
|
||||
NULL, /* FIXME-Oec: TALER_AgeHash * */
|
||||
&coin->coin_pub,
|
||||
NULL, /* FIXME: handle CS */
|
||||
&c_hash,
|
||||
&coin_ev,
|
||||
&coin_ev_size))
|
||||
&blinded_planchet))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TALER_MHD_reply_with_error (
|
||||
@ -263,10 +262,17 @@ verify_and_execute_recoup (
|
||||
TALER_EC_EXCHANGE_RECOUP_BLINDING_FAILED,
|
||||
NULL);
|
||||
}
|
||||
TALER_coin_ev_hash (coin_ev,
|
||||
coin_ev_size,
|
||||
&pc.h_blind);
|
||||
GNUNET_free (coin_ev);
|
||||
if (GNUNET_OK != TALER_coin_ev_hash (&blinded_planchet,
|
||||
&coin->denom_pub_hash,
|
||||
&pc.h_blind))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
|
||||
NULL);
|
||||
}
|
||||
TALER_blinded_planchet_free (&blinded_planchet);
|
||||
}
|
||||
|
||||
pc.coin_sig = coin_sig;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2019, 2021 Taler Systems SA
|
||||
Copyright (C) 2014-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Affero General Public License as published by the Free Software
|
||||
@ -31,12 +31,6 @@
|
||||
#include "taler-exchange-httpd_keys.h"
|
||||
|
||||
|
||||
/**
|
||||
* Maximum number of fresh coins we allow per refresh operation.
|
||||
*/
|
||||
#define MAX_FRESH_COINS 256
|
||||
|
||||
|
||||
/**
|
||||
* Send a response for "/refreshes/$RCH/reveal".
|
||||
*
|
||||
@ -180,21 +174,33 @@ check_commitment (struct RevealContext *rctx,
|
||||
for (unsigned int j = 0; j<rctx->num_fresh_coins; j++)
|
||||
{
|
||||
struct TALER_RefreshCoinData *rcd = &rce->new_coins[j];
|
||||
struct TALER_PlanchetSecretsP ps;
|
||||
struct TALER_CoinSpendPrivateKeyP coin_priv;
|
||||
union TALER_DenominationBlindingKeyP bks;
|
||||
struct TALER_ExchangeWithdrawValues alg_values;
|
||||
struct TALER_PlanchetDetail pd;
|
||||
struct TALER_CoinPubHash c_hash;
|
||||
struct TALER_PlanchetSecretsP ps;
|
||||
|
||||
rcd->dk = &rctx->dks[j]->denom_pub;
|
||||
TALER_planchet_setup_refresh (&ts,
|
||||
TALER_transfer_secret_to_planchet_secret (&ts,
|
||||
j,
|
||||
&ps);
|
||||
// TODO: implement cipher handling
|
||||
alg_values.cipher = TALER_DENOMINATION_RSA;
|
||||
TALER_planchet_setup_coin_priv (&ps,
|
||||
&alg_values,
|
||||
&coin_priv);
|
||||
TALER_planchet_blinding_secret_create (&ps,
|
||||
&alg_values,
|
||||
&bks);
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_planchet_prepare (rcd->dk,
|
||||
&ps,
|
||||
&alg_values,
|
||||
&bks,
|
||||
&coin_priv,
|
||||
&c_hash,
|
||||
&pd));
|
||||
rcd->coin_ev = pd.coin_ev;
|
||||
rcd->coin_ev_size = pd.coin_ev_size;
|
||||
rcd->blinded_planchet = pd.blinded_planchet;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -216,7 +222,7 @@ check_commitment (struct RevealContext *rctx,
|
||||
{
|
||||
struct TALER_RefreshCoinData *rcd = &rce->new_coins[j];
|
||||
|
||||
GNUNET_free (rcd->coin_ev);
|
||||
TALER_blinded_planchet_free (&rcd->blinded_planchet);
|
||||
}
|
||||
GNUNET_free (rce->new_coins);
|
||||
}
|
||||
@ -296,7 +302,7 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
|
||||
const json_t *coin_evs)
|
||||
{
|
||||
unsigned int num_fresh_coins = json_array_size (new_denoms_h_json);
|
||||
/* We know num_fresh_coins is bounded by #MAX_FRESH_COINS, so this is safe */
|
||||
/* We know num_fresh_coins is bounded by #TALER_MAX_FRESH_COINS, so this is safe */
|
||||
const struct TEH_DenominationKey *dks[num_fresh_coins];
|
||||
struct TALER_RefreshCoinData rcds[num_fresh_coins];
|
||||
struct TALER_EXCHANGEDB_RefreshRevealedCoin rrcs[num_fresh_coins];
|
||||
@ -375,9 +381,8 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
|
||||
{
|
||||
struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i];
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_varsize (NULL,
|
||||
&rrc->coin_ev,
|
||||
&rrc->coin_ev_size),
|
||||
TALER_JSON_spec_blinded_planchet (NULL,
|
||||
&rrc->blinded_planchet),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
enum GNUNET_GenericReturnValue res;
|
||||
@ -390,12 +395,12 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
|
||||
if (GNUNET_OK != res)
|
||||
{
|
||||
for (unsigned int j = 0; j<i; j++)
|
||||
GNUNET_free (rrcs[j].coin_ev);
|
||||
TALER_blinded_planchet_free (&rrcs[j].blinded_planchet);
|
||||
return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
|
||||
}
|
||||
GNUNET_CRYPTO_hash (rrc->coin_ev,
|
||||
rrc->coin_ev_size,
|
||||
&rrc->coin_envelope_hash.hash);
|
||||
TALER_coin_ev_hash (&rrc->blinded_planchet,
|
||||
&rrcs[i].h_denom_pub,
|
||||
&rrc->coin_envelope_hash);
|
||||
}
|
||||
|
||||
/* lookup old_coin_pub in database */
|
||||
@ -485,9 +490,18 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
|
||||
const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i];
|
||||
struct TALER_RefreshCoinData *rcd = &rcds[i];
|
||||
|
||||
rcd->coin_ev = rrc->coin_ev;
|
||||
rcd->coin_ev_size = rrc->coin_ev_size;
|
||||
rcd->blinded_planchet = rrc->blinded_planchet;
|
||||
rcd->dk = &dks[i]->denom_pub;
|
||||
if (rcd->blinded_planchet.cipher != rcd->dk->cipher)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
ret = TALER_MHD_REPLY_JSON_PACK (
|
||||
connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_JSON_pack_ec (
|
||||
TALER_EC_EXCHANGE_GENERIC_CIPHER_MISMATCH));
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
rctx->dks = dks;
|
||||
rctx->rcds = rcds;
|
||||
@ -504,12 +518,18 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
|
||||
for (unsigned int i = 0; i<rctx->num_fresh_coins; i++)
|
||||
{
|
||||
enum TALER_ErrorCode ec = TALER_EC_NONE;
|
||||
struct TEH_SignDetails sign_details;
|
||||
const struct TALER_BlindedRsaPlanchet *rp;
|
||||
|
||||
// FIXME: implement cipher handling
|
||||
rp = &rcds[i].blinded_planchet.details.rsa_blinded_planchet;
|
||||
sign_details.cipher = TALER_DENOMINATION_RSA;
|
||||
sign_details.details.rsa_message.msg = rp->blinded_msg;
|
||||
sign_details.details.rsa_message.msg_size = rp->blinded_msg_size;
|
||||
rrcs[i].coin_sig
|
||||
= TEH_keys_denomination_sign (
|
||||
&rrcs[i].h_denom_pub,
|
||||
rcds[i].coin_ev,
|
||||
rcds[i].coin_ev_size,
|
||||
&sign_details,
|
||||
&ec);
|
||||
if (TALER_EC_NONE != ec)
|
||||
{
|
||||
@ -530,8 +550,7 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
|
||||
{
|
||||
struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i];
|
||||
|
||||
rrc->coin_ev = rcds[i].coin_ev;
|
||||
rrc->coin_ev_size = rcds[i].coin_ev_size;
|
||||
rrc->blinded_planchet = rcds[i].blinded_planchet;
|
||||
}
|
||||
qs = TEH_plugin->insert_refresh_reveal (TEH_plugin->cls,
|
||||
melt_serial_id,
|
||||
@ -564,7 +583,7 @@ cleanup:
|
||||
struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i];
|
||||
|
||||
TALER_blinded_denom_sig_free (&rrc->coin_sig);
|
||||
GNUNET_free (rrc->coin_ev);
|
||||
TALER_blinded_planchet_free (&rrc->blinded_planchet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -597,7 +616,7 @@ handle_refreshes_reveal_json (struct MHD_Connection *connection,
|
||||
unsigned int num_tprivs = json_array_size (tp_json);
|
||||
|
||||
GNUNET_assert (num_tprivs == TALER_CNC_KAPPA - 1); /* checked just earlier */
|
||||
if ( (num_fresh_coins >= MAX_FRESH_COINS) ||
|
||||
if ( (num_fresh_coins >= TALER_MAX_FRESH_COINS) ||
|
||||
(0 == num_fresh_coins) )
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
|
@ -491,6 +491,53 @@ TEH_RESPONSE_reply_expired_denom_pub_hash (
|
||||
}
|
||||
|
||||
|
||||
MHD_RESULT
|
||||
TEH_RESPONSE_reply_invalid_denom_cipher_for_operation (
|
||||
struct MHD_Connection *connection,
|
||||
const struct TALER_DenominationHash *dph)
|
||||
{
|
||||
struct TALER_ExchangePublicKeyP epub;
|
||||
struct TALER_ExchangeSignatureP esig;
|
||||
struct GNUNET_TIME_Timestamp now;
|
||||
enum TALER_ErrorCode ec;
|
||||
|
||||
now = GNUNET_TIME_timestamp_get ();
|
||||
{
|
||||
struct TALER_DenominationUnknownAffirmationPS dua = {
|
||||
.purpose.size = htonl (sizeof (dua)),
|
||||
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN),
|
||||
.timestamp = GNUNET_TIME_timestamp_hton (now),
|
||||
.h_denom_pub = *dph,
|
||||
};
|
||||
|
||||
ec = TEH_keys_exchange_sign (&dua,
|
||||
&epub,
|
||||
&esig);
|
||||
}
|
||||
if (TALER_EC_NONE != ec)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
ec,
|
||||
NULL);
|
||||
}
|
||||
return TALER_MHD_REPLY_JSON_PACK (
|
||||
connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
TALER_JSON_pack_ec (
|
||||
TALER_EC_EXCHANGE_GENERIC_INVALID_DENOMINATION_CIPHER_FOR_OPERATION),
|
||||
GNUNET_JSON_pack_timestamp ("timestamp",
|
||||
now),
|
||||
GNUNET_JSON_pack_data_auto ("exchange_pub",
|
||||
&epub),
|
||||
GNUNET_JSON_pack_data_auto ("exchange_sig",
|
||||
&esig),
|
||||
GNUNET_JSON_pack_data_auto ("h_denom_pub",
|
||||
dph));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send proof that a request is invalid to client because of
|
||||
* insufficient funds. This function will create a message with all
|
||||
|
@ -79,6 +79,19 @@ TEH_RESPONSE_reply_expired_denom_pub_hash (
|
||||
const char *oper);
|
||||
|
||||
|
||||
/**
|
||||
* Send assertion that the given denomination cannot be used for this operation.
|
||||
*
|
||||
* @param connection connection to the client
|
||||
* @param dph denomination public key hash
|
||||
* @return MHD result code
|
||||
*/
|
||||
MHD_RESULT
|
||||
TEH_RESPONSE_reply_invalid_denom_cipher_for_operation (
|
||||
struct MHD_Connection *connection,
|
||||
const struct TALER_DenominationHash *dph);
|
||||
|
||||
|
||||
/**
|
||||
* Send proof that a request is invalid to client because of
|
||||
* insufficient funds. This function will create a message with all
|
||||
|
@ -98,12 +98,7 @@ struct WithdrawContext
|
||||
/**
|
||||
* Blinded planchet.
|
||||
*/
|
||||
void *blinded_msg;
|
||||
|
||||
/**
|
||||
* Number of bytes in @e blinded_msg.
|
||||
*/
|
||||
size_t blinded_msg_len;
|
||||
struct TALER_BlindedPlanchet blinded_planchet;
|
||||
|
||||
/**
|
||||
* Set to the resulting signed coin data to be returned to the client.
|
||||
@ -324,13 +319,12 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
|
||||
{
|
||||
struct WithdrawContext wc;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_varsize ("coin_ev",
|
||||
&wc.blinded_msg,
|
||||
&wc.blinded_msg_len),
|
||||
GNUNET_JSON_spec_fixed_auto ("reserve_sig",
|
||||
&wc.collectable.reserve_sig),
|
||||
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
|
||||
&wc.collectable.denom_pub_hash),
|
||||
TALER_JSON_spec_blinded_planchet ("coin_ev",
|
||||
&wc.blinded_planchet),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
enum TALER_ErrorCode ec;
|
||||
@ -444,6 +438,15 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return mret;
|
||||
}
|
||||
if (dk->denom_pub.cipher != wc.blinded_planchet.cipher)
|
||||
{
|
||||
/* denomination cipher and blinded planchet cipher not the same */
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_EXCHANGE_GENERIC_CIPHER_MISMATCH,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (0 >
|
||||
@ -468,9 +471,17 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
|
||||
= htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW);
|
||||
wc.wsrd.h_denomination_pub
|
||||
= wc.collectable.denom_pub_hash;
|
||||
TALER_coin_ev_hash (wc.blinded_msg,
|
||||
wc.blinded_msg_len,
|
||||
&wc.wsrd.h_coin_envelope);
|
||||
if (GNUNET_OK != TALER_coin_ev_hash (&wc.blinded_planchet,
|
||||
&wc.collectable.denom_pub_hash,
|
||||
&wc.wsrd.h_coin_envelope))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
|
||||
NULL);
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CRYPTO_eddsa_verify (
|
||||
TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW,
|
||||
@ -487,13 +498,38 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
|
||||
NULL);
|
||||
}
|
||||
|
||||
// TODO: if CS: check nonce for reuse
|
||||
|
||||
/* Sign before transaction! */
|
||||
ec = TALER_EC_NONE;
|
||||
wc.collectable.sig
|
||||
= TEH_keys_denomination_sign (&wc.collectable.denom_pub_hash,
|
||||
wc.blinded_msg,
|
||||
wc.blinded_msg_len,
|
||||
{
|
||||
struct TEH_SignDetails sign_details;
|
||||
sign_details.cipher = wc.blinded_planchet.cipher;
|
||||
switch (wc.blinded_planchet.cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
sign_details.details.rsa_message.msg =
|
||||
wc.blinded_planchet.details.rsa_blinded_planchet.blinded_msg;
|
||||
sign_details.details.rsa_message.msg_size =
|
||||
wc.blinded_planchet.details.rsa_blinded_planchet.blinded_msg_size;
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
sign_details.details.cs_message =
|
||||
wc.blinded_planchet.details.cs_blinded_planchet;
|
||||
break;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
|
||||
NULL);
|
||||
}
|
||||
wc.collectable.sig = TEH_keys_denomination_sign (
|
||||
&wc.collectable.denom_pub_hash,
|
||||
&sign_details,
|
||||
&ec);
|
||||
}
|
||||
if (TALER_EC_NONE != ec)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
|
@ -70,7 +70,7 @@ PASSWORD = x
|
||||
WIRE_GATEWAY_URL = "http://localhost:8082/3/"
|
||||
|
||||
# Coins for the tests.
|
||||
[coin_eur_ct_1]
|
||||
[coin_eur_ct_1_rsa]
|
||||
value = EUR:0.01
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
@ -79,9 +79,21 @@ fee_withdraw = EUR:0.00
|
||||
fee_deposit = EUR:0.00
|
||||
fee_refresh = EUR:0.01
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_eur_ct_10]
|
||||
[coin_eur_ct_1_cs]
|
||||
value = EUR:0.01
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.00
|
||||
fee_deposit = EUR:0.00
|
||||
fee_refresh = EUR:0.01
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_ct_10_rsa]
|
||||
value = EUR:0.10
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
@ -90,9 +102,21 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_eur_1]
|
||||
[coin_eur_ct_10_cs]
|
||||
value = EUR:0.10
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_1_rsa]
|
||||
value = EUR:1
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
@ -101,4 +125,16 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_eur_1_cs]
|
||||
value = EUR:1
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
@ -70,7 +70,7 @@ TALER_BANK_AUTH_METHOD = NONE
|
||||
|
||||
|
||||
# Coins for the tests.
|
||||
[coin_eur_ct_1]
|
||||
[coin_eur_ct_1_rsa]
|
||||
value = EUR:0.01
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
@ -79,9 +79,21 @@ fee_withdraw = EUR:0.00
|
||||
fee_deposit = EUR:0.00
|
||||
fee_refresh = EUR:0.01
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_eur_ct_10]
|
||||
[coin_eur_ct_1_cs]
|
||||
value = EUR:0.01
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.00
|
||||
fee_deposit = EUR:0.00
|
||||
fee_refresh = EUR:0.01
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_ct_10_rsa]
|
||||
value = EUR:0.10
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
@ -90,9 +102,21 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_eur_1]
|
||||
[coin_eur_ct_10_cs]
|
||||
value = EUR:0.10
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_1_rsa]
|
||||
value = EUR:1
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
@ -101,4 +125,16 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_eur_1_cs]
|
||||
value = EUR:1
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
@ -6094,8 +6094,7 @@ postgres_insert_refresh_reveal (
|
||||
GNUNET_PQ_query_param_uint32 (&i),
|
||||
GNUNET_PQ_query_param_auto_from_type (&rrc->orig_coin_link_sig),
|
||||
GNUNET_PQ_query_param_auto_from_type (&rrc->h_denom_pub),
|
||||
GNUNET_PQ_query_param_fixed_size (rrc->coin_ev,
|
||||
rrc->coin_ev_size),
|
||||
TALER_PQ_query_param_blinded_planchet (&rrc->blinded_planchet),
|
||||
GNUNET_PQ_query_param_auto_from_type (&rrc->coin_envelope_hash),
|
||||
TALER_PQ_query_param_blinded_denom_sig (&rrc->coin_sig),
|
||||
GNUNET_PQ_query_param_end
|
||||
@ -6202,15 +6201,14 @@ add_revealed_coins (void *cls,
|
||||
&rrc->orig_coin_link_sig),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("h_coin_ev",
|
||||
&rrc->coin_envelope_hash),
|
||||
GNUNET_PQ_result_spec_variable_size ("coin_ev",
|
||||
(void **) &rrc->coin_ev,
|
||||
&rrc->coin_ev_size),
|
||||
TALER_PQ_result_spec_blinded_planchet ("coin_ev",
|
||||
&rrc->blinded_planchet),
|
||||
TALER_PQ_result_spec_blinded_denom_sig ("ev_sig",
|
||||
&rrc->coin_sig),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
|
||||
if (NULL != rrc->coin_ev)
|
||||
if (TALER_DENOMINATION_INVALID != rrc->blinded_planchet.cipher)
|
||||
{
|
||||
/* duplicate offset, not allowed */
|
||||
GNUNET_break (0);
|
||||
@ -6293,10 +6291,9 @@ cleanup:
|
||||
struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &grctx.rrcs[i];
|
||||
|
||||
TALER_blinded_denom_sig_free (&rrc->coin_sig);
|
||||
GNUNET_free (rrc->coin_ev);
|
||||
TALER_blinded_planchet_free (&rrc->blinded_planchet);
|
||||
}
|
||||
GNUNET_free (grctx.rrcs);
|
||||
|
||||
return qs;
|
||||
}
|
||||
|
||||
@ -7212,7 +7209,7 @@ postgres_lookup_transfer_by_deposit (
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
char *payto_uri;
|
||||
struct TALER_WireSalt wire_salt;
|
||||
struct TALER_WireSaltP wire_salt;
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
|
||||
wtid),
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2021 Taler Systems SA
|
||||
Copyright (C) 2014-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -433,10 +433,9 @@ check_refresh_reveal_cb (
|
||||
&revealed_coins[cnt];
|
||||
const struct TALER_EXCHANGEDB_RefreshRevealedCoin *bcoin = &rrcs[cnt];
|
||||
|
||||
GNUNET_assert (acoin->coin_ev_size == bcoin->coin_ev_size);
|
||||
GNUNET_assert (0 ==
|
||||
GNUNET_memcmp (acoin->coin_ev,
|
||||
bcoin->coin_ev));
|
||||
TALER_blinded_planchet_cmp (&acoin->blinded_planchet,
|
||||
&bcoin->blinded_planchet));
|
||||
GNUNET_assert (0 ==
|
||||
GNUNET_memcmp (&acoin->h_denom_pub,
|
||||
&bcoin->h_denom_pub));
|
||||
@ -531,7 +530,7 @@ handle_link_data_cb (void *cls,
|
||||
break;
|
||||
}
|
||||
}
|
||||
GNUNET_assert (found);
|
||||
GNUNET_assert (GNUNET_NO != found);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1345,8 +1344,7 @@ run (void *cls)
|
||||
unsigned int cnt;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
struct GNUNET_TIME_Timestamp now;
|
||||
struct TALER_WireSalt salt;
|
||||
union TALER_DenominationBlindingKeyP bks;
|
||||
struct TALER_WireSaltP salt;
|
||||
struct TALER_CoinPubHash c_hash;
|
||||
uint64_t known_coin_id;
|
||||
uint64_t rrc_serial;
|
||||
@ -1354,6 +1352,13 @@ run (void *cls)
|
||||
struct TALER_DenominationPublicKey *new_denom_pubs = NULL;
|
||||
uint64_t reserve_out_serial_id;
|
||||
uint64_t melt_serial_id;
|
||||
struct TALER_PlanchetSecretsP ps;
|
||||
union TALER_DenominationBlindingKeyP bks;
|
||||
struct TALER_ExchangeWithdrawValues alg_values = {
|
||||
/* RSA is simpler, and for the DB there is no real difference between
|
||||
CS and RSA, just one should be used, so we use RSA */
|
||||
.cipher = TALER_DENOMINATION_RSA
|
||||
};
|
||||
|
||||
memset (&deposit,
|
||||
0,
|
||||
@ -1415,7 +1420,6 @@ run (void *cls)
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":1.000010",
|
||||
&amount_with_fee));
|
||||
|
||||
result = 4;
|
||||
now = GNUNET_TIME_timestamp_get ();
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
@ -1464,36 +1468,42 @@ run (void *cls)
|
||||
TALER_denom_pub_hash (&dkp->pub,
|
||||
&cbc.denom_pub_hash);
|
||||
RND_BLK (&cbc.reserve_sig);
|
||||
TALER_planchet_blinding_secret_create (&ps,
|
||||
&alg_values,
|
||||
&bks);
|
||||
{
|
||||
struct TALER_PlanchetDetail pd;
|
||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||
struct TALER_AgeHash age_hash;
|
||||
struct TALER_AgeHash *p_ah[2] = {NULL, &age_hash};
|
||||
struct TALER_AgeHash *p_ah[2] = {
|
||||
NULL,
|
||||
&age_hash
|
||||
};
|
||||
|
||||
// FIXME:
|
||||
/* Call TALER_denom_blind()/TALER_denom_sign_blinded() twice, once without
|
||||
* age_hash, once with age_hash */
|
||||
RND_BLK (&age_hash);
|
||||
for (size_t i = 0; i < sizeof(p_ah) / sizeof(p_ah[0]); i++)
|
||||
{
|
||||
RND_BLK (&coin_pub);
|
||||
TALER_blinding_secret_create (&bks);
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_denom_blind (&dkp->pub,
|
||||
&bks,
|
||||
p_ah[i],
|
||||
&coin_pub,
|
||||
&alg_values,
|
||||
&c_hash,
|
||||
&pd.coin_ev,
|
||||
&pd.coin_ev_size));
|
||||
TALER_coin_ev_hash (pd.coin_ev,
|
||||
pd.coin_ev_size,
|
||||
&cbc.h_coin_envelope);
|
||||
&pd.blinded_planchet));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_coin_ev_hash (&pd.blinded_planchet,
|
||||
&cbc.denom_pub_hash,
|
||||
&cbc.h_coin_envelope));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_denom_sign_blinded (&cbc.sig,
|
||||
&dkp->priv,
|
||||
pd.coin_ev,
|
||||
pd.coin_ev_size));
|
||||
GNUNET_free (pd.coin_ev);
|
||||
&pd.blinded_planchet));
|
||||
TALER_blinded_planchet_free (&pd.blinded_planchet);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1724,6 +1734,8 @@ run (void *cls)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin;
|
||||
struct GNUNET_TIME_Timestamp now;
|
||||
struct TALER_BlindedRsaPlanchet *rp;
|
||||
struct TALER_BlindedPlanchet *bp;
|
||||
|
||||
now = GNUNET_TIME_timestamp_get ();
|
||||
new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
|
||||
@ -1736,23 +1748,25 @@ run (void *cls)
|
||||
GNUNET_assert (NULL != new_dkp[cnt]);
|
||||
new_denom_pubs[cnt] = new_dkp[cnt]->pub;
|
||||
ccoin = &revealed_coins[cnt];
|
||||
ccoin->coin_ev_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
|
||||
bp = &ccoin->blinded_planchet;
|
||||
bp->cipher = TALER_DENOMINATION_RSA;
|
||||
rp = &bp->details.rsa_blinded_planchet;
|
||||
rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
|
||||
GNUNET_CRYPTO_QUALITY_WEAK,
|
||||
(RSA_KEY_SIZE / 8) - 1);
|
||||
ccoin->coin_ev = GNUNET_malloc (ccoin->coin_ev_size);
|
||||
rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size);
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||
ccoin->coin_ev,
|
||||
ccoin->coin_ev_size);
|
||||
GNUNET_CRYPTO_hash (ccoin->coin_ev,
|
||||
ccoin->coin_ev_size,
|
||||
&ccoin->coin_envelope_hash.hash);
|
||||
rp->blinded_msg,
|
||||
rp->blinded_msg_size);
|
||||
TALER_denom_pub_hash (&new_dkp[cnt]->pub,
|
||||
&ccoin->h_denom_pub);
|
||||
TALER_coin_ev_hash (bp,
|
||||
&ccoin->h_denom_pub,
|
||||
&ccoin->coin_envelope_hash);
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_denom_sign_blinded (&ccoin->coin_sig,
|
||||
&new_dkp[cnt]->priv,
|
||||
ccoin->coin_ev,
|
||||
ccoin->coin_ev_size));
|
||||
bp));
|
||||
}
|
||||
RND_BLK (&tprivs);
|
||||
RND_BLK (&tpub);
|
||||
@ -1772,11 +1786,13 @@ run (void *cls)
|
||||
{
|
||||
struct TALER_BlindedCoinHash h_coin_ev;
|
||||
struct TALER_CoinSpendPublicKeyP ocp;
|
||||
struct TALER_DenominationHash denom_hash;
|
||||
|
||||
GNUNET_CRYPTO_hash (revealed_coins[0].coin_ev,
|
||||
revealed_coins[0].coin_ev_size,
|
||||
&h_coin_ev.hash);
|
||||
|
||||
TALER_denom_pub_hash (&new_denom_pubs[0],
|
||||
&denom_hash);
|
||||
TALER_coin_ev_hash (&revealed_coins[0].blinded_planchet,
|
||||
&denom_hash,
|
||||
&h_coin_ev);
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->get_old_coin_by_h_blind (plugin->cls,
|
||||
&h_coin_ev,
|
||||
@ -2385,7 +2401,7 @@ drop:
|
||||
for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
|
||||
{
|
||||
TALER_blinded_denom_sig_free (&revealed_coins[cnt].coin_sig);
|
||||
GNUNET_free (revealed_coins[cnt].coin_ev);
|
||||
TALER_blinded_planchet_free (&revealed_coins[cnt].blinded_planchet);
|
||||
}
|
||||
GNUNET_free (revealed_coins);
|
||||
revealed_coins = NULL;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2021 Taler Systems SA
|
||||
Copyright (C) 2014-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Affero General Public License as published by the Free Software
|
||||
@ -922,7 +922,7 @@ TALER_EXCHANGE_deposit (
|
||||
const struct TALER_Amount *amount,
|
||||
struct GNUNET_TIME_Timestamp wire_deadline,
|
||||
const char *merchant_payto_uri,
|
||||
const struct TALER_WireSalt *wire_salt,
|
||||
const struct TALER_WireSaltP *wire_salt,
|
||||
const struct TALER_PrivateContractHash *h_contract_terms,
|
||||
const json_t *extension_details,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
@ -1033,6 +1033,119 @@ void
|
||||
TALER_EXCHANGE_refund_cancel (struct TALER_EXCHANGE_RefundHandle *refund);
|
||||
|
||||
|
||||
/* ********************* POST /csr *********************** */
|
||||
|
||||
|
||||
/**
|
||||
* @brief A /csr Handle
|
||||
*/
|
||||
struct TALER_EXCHANGE_CsRHandle;
|
||||
|
||||
|
||||
/**
|
||||
* Details about a response for a CS R request.
|
||||
*/
|
||||
struct TALER_EXCHANGE_CsRResponse
|
||||
{
|
||||
/**
|
||||
* HTTP response data.
|
||||
*/
|
||||
struct TALER_EXCHANGE_HttpResponse hr;
|
||||
|
||||
/**
|
||||
* Details about the response.
|
||||
*/
|
||||
union
|
||||
{
|
||||
/**
|
||||
* Details if the status is #MHD_HTTP_OK.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
/**
|
||||
* Length of the @e alg_values array.
|
||||
*/
|
||||
unsigned int alg_values_len;
|
||||
|
||||
/**
|
||||
* Values contributed by the exchange for the
|
||||
* respective coin's withdraw operation.
|
||||
*/
|
||||
const struct TALER_ExchangeWithdrawValues *alg_values;
|
||||
} success;
|
||||
|
||||
/**
|
||||
* Details if the status is #MHD_HTTP_GONE.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
/* TODO: returning full details is not implemented */
|
||||
} gone;
|
||||
|
||||
} details;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Callbacks of this type are used to serve the result of submitting a
|
||||
* CS R request to a exchange.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param csrr response details
|
||||
*/
|
||||
typedef void
|
||||
(*TALER_EXCHANGE_CsRCallback) (void *cls,
|
||||
const struct TALER_EXCHANGE_CsRResponse *csrr);
|
||||
|
||||
|
||||
/**
|
||||
* Information we pass per coin to a /csr request.
|
||||
*/
|
||||
struct TALER_EXCHANGE_NonceKey
|
||||
{
|
||||
/**
|
||||
* Which denomination key is the /csr request for?
|
||||
*/
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *pk;
|
||||
|
||||
/**
|
||||
* What is the client nonce for the request?
|
||||
*/
|
||||
struct TALER_CsNonce nonce;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get a CS R using a /csr request.
|
||||
*
|
||||
* @param exchange the exchange handle; the exchange must be ready to operate
|
||||
* @param nks_len length of the @a nks array
|
||||
* @param nks array of denominations and nonces
|
||||
* @param res_cb the callback to call when the final result for this request is available
|
||||
* @param res_cb_cls closure for the above callback
|
||||
* @return handle for the operation on success, NULL on error, i.e.
|
||||
* if the inputs are invalid (i.e. denomination key not with this exchange).
|
||||
* In this case, the callback is not called.
|
||||
*/
|
||||
struct TALER_EXCHANGE_CsRHandle *
|
||||
TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange,
|
||||
unsigned int nks_len,
|
||||
struct TALER_EXCHANGE_NonceKey *nks,
|
||||
TALER_EXCHANGE_CsRCallback res_cb,
|
||||
void *res_cb_cls);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Cancel a CS R request. This function cannot be used
|
||||
* on a request handle if a response is already served for it.
|
||||
*
|
||||
* @param csrh the withdraw handle
|
||||
*/
|
||||
void
|
||||
TALER_EXCHANGE_csr_cancel (struct TALER_EXCHANGE_CsRHandle *csrh);
|
||||
|
||||
|
||||
/* ********************* GET /reserves/$RESERVE_PUB *********************** */
|
||||
|
||||
|
||||
@ -1293,10 +1406,27 @@ struct TALER_EXCHANGE_WithdrawResponse
|
||||
*/
|
||||
struct
|
||||
{
|
||||
/**
|
||||
* Private key of the coin.
|
||||
*/
|
||||
struct TALER_CoinSpendPrivateKeyP coin_priv;
|
||||
|
||||
/**
|
||||
* Value used to blind the key for the signature.
|
||||
* Needed for recoup operations.
|
||||
*/
|
||||
union TALER_DenominationBlindingKeyP bks;
|
||||
|
||||
/**
|
||||
* Signature over the coin.
|
||||
*/
|
||||
struct TALER_DenominationSignature sig;
|
||||
|
||||
/**
|
||||
* Values contributed from the exchange during the
|
||||
* withdraw protocol.
|
||||
*/
|
||||
struct TALER_ExchangeWithdrawValues exchange_vals;
|
||||
} success;
|
||||
|
||||
/**
|
||||
@ -1451,50 +1581,45 @@ TALER_EXCHANGE_withdraw2_cancel (struct TALER_EXCHANGE_Withdraw2Handle *wh);
|
||||
|
||||
|
||||
/**
|
||||
* Melt (partially spent) coins to obtain fresh coins that are
|
||||
* unlinkable to the original coin(s). Note that melting more
|
||||
* than one coin in a single request will make those coins linkable,
|
||||
* so the safest operation only melts one coin at a time.
|
||||
*
|
||||
* This API is typically used by a wallet. Note that to ensure that
|
||||
* no money is lost in case of hardware failures, is operation does
|
||||
* not actually initiate the request. Instead, it generates a buffer
|
||||
* which the caller must store before proceeding with the actual call
|
||||
* to #TALER_EXCHANGE_melt() that will generate the request.
|
||||
*
|
||||
* This function does verify that the given request data is internally
|
||||
* consistent. However, the @a melts_sigs are NOT verified.
|
||||
*
|
||||
* Aside from some non-trivial cryptographic operations that might
|
||||
* take a bit of CPU time to complete, this function returns
|
||||
* its result immediately and does not start any asynchronous
|
||||
* processing. This function is also thread-safe.
|
||||
*
|
||||
* @param melt_priv private keys of the coin to melt
|
||||
* @param melt_amount amount specifying how much
|
||||
* the coin will contribute to the melt (including fee)
|
||||
* @param melt_sig signatures affirming the
|
||||
* validity of the public keys corresponding to the
|
||||
* @a melt_priv private key
|
||||
* @param melt_pk denomination key information
|
||||
* record corresponding to the @a melt_sig
|
||||
* validity of the keys
|
||||
* @param fresh_pks_len length of the @a pks array
|
||||
* @param fresh_pks array of @a pks_len denominations of fresh coins to create
|
||||
* @return NULL
|
||||
* if the inputs are invalid (i.e. denomination key not with this exchange).
|
||||
* Otherwise, JSON data structure to store persistently
|
||||
* before proceeding to #TALER_EXCHANGE_melt().
|
||||
* Non-null results should be freed using GNUNET_free().
|
||||
* Information needed to melt (partially spent) coins to obtain fresh coins
|
||||
* that are unlinkable to the original coin(s). Note that melting more than
|
||||
* one coin in a single request will make those coins linkable, so we only melt one coin at a time.
|
||||
*/
|
||||
json_t *
|
||||
TALER_EXCHANGE_refresh_prepare (
|
||||
const struct TALER_CoinSpendPrivateKeyP *melt_priv,
|
||||
const struct TALER_Amount *melt_amount,
|
||||
const struct TALER_DenominationSignature *melt_sig,
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *melt_pk,
|
||||
unsigned int fresh_pks_len,
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks);
|
||||
struct TALER_EXCHANGE_RefreshData
|
||||
{
|
||||
/**
|
||||
* private key of the coin to melt
|
||||
*/
|
||||
struct TALER_CoinSpendPrivateKeyP melt_priv;
|
||||
|
||||
/**
|
||||
* amount specifying how much the coin will contribute to the melt
|
||||
* (including fee)
|
||||
*/
|
||||
struct TALER_Amount melt_amount;
|
||||
|
||||
/**
|
||||
* signatures affirming the validity of the public keys corresponding to the
|
||||
* @e melt_priv private key
|
||||
*/
|
||||
struct TALER_DenominationSignature melt_sig;
|
||||
|
||||
/**
|
||||
* denomination key information record corresponding to the @e melt_sig
|
||||
* validity of the keys
|
||||
*/
|
||||
struct TALER_EXCHANGE_DenomPublicKey melt_pk;
|
||||
|
||||
/**
|
||||
* array of @e pks_len denominations of fresh coins to create
|
||||
*/
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks;
|
||||
|
||||
/**
|
||||
* length of the @e pks array
|
||||
*/
|
||||
unsigned int fresh_pks_len;
|
||||
};
|
||||
|
||||
|
||||
/* ********************* /coins/$COIN_PUB/melt ***************************** */
|
||||
@ -1513,6 +1638,9 @@ struct TALER_EXCHANGE_MeltHandle;
|
||||
*
|
||||
* @param cls closure
|
||||
* @param hr HTTP response data
|
||||
* @param num_coins number of fresh coins to be created, length of the @a exchange_vals array, 0 if the operation failed
|
||||
* @param alg_values array @a num_coins of exchange values contributed to the refresh operation
|
||||
* @param bks array of @a num_coins blinding keys used to blind the fresh coins
|
||||
* @param noreveal_index choice by the exchange in the cut-and-choose protocol,
|
||||
* UINT32_MAX on error
|
||||
* @param sign_key exchange key used to sign @a full_response, or NULL
|
||||
@ -1521,6 +1649,9 @@ typedef void
|
||||
(*TALER_EXCHANGE_MeltCallback) (
|
||||
void *cls,
|
||||
const struct TALER_EXCHANGE_HttpResponse *hr,
|
||||
unsigned int num_coins,
|
||||
const struct TALER_ExchangeWithdrawValues *alg_values,
|
||||
const union TALER_DenominationBlindingKeyP *bks,
|
||||
uint32_t noreveal_index,
|
||||
const struct TALER_ExchangePublicKeyP *sign_key);
|
||||
|
||||
@ -1536,8 +1667,8 @@ typedef void
|
||||
* prior to calling this function.
|
||||
*
|
||||
* @param exchange the exchange handle; the exchange must be ready to operate
|
||||
* @param refresh_data the refresh data as returned from
|
||||
#TALER_EXCHANGE_refresh_prepare())
|
||||
* @param ps the fresh secret that defines the refresh operation
|
||||
* @param rd the refresh data specifying the characteristics of the operation
|
||||
* @param melt_cb the callback to call with the result
|
||||
* @param melt_cb_cls closure for @a melt_cb
|
||||
* @return a handle for this request; NULL if the argument was invalid.
|
||||
@ -1545,7 +1676,8 @@ typedef void
|
||||
*/
|
||||
struct TALER_EXCHANGE_MeltHandle *
|
||||
TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
|
||||
const json_t *refresh_data,
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
const struct TALER_EXCHANGE_RefreshData *rd,
|
||||
TALER_EXCHANGE_MeltCallback melt_cb,
|
||||
void *melt_cb_cls);
|
||||
|
||||
@ -1574,6 +1706,7 @@ TALER_EXCHANGE_melt_cancel (struct TALER_EXCHANGE_MeltHandle *mh);
|
||||
* @param cls closure
|
||||
* @param hr HTTP response data
|
||||
* @param num_coins number of fresh coins created, length of the @a sigs and @a coin_privs arrays, 0 if the operation failed
|
||||
* @param exchange_vals array of contributions from the exchange on the refreshes
|
||||
* @param coin_privs array of @a num_coins private keys for the coins that were created, NULL on error
|
||||
* @param sigs array of signature over @a num_coins coins, NULL on error
|
||||
*/
|
||||
@ -1582,7 +1715,7 @@ typedef void
|
||||
void *cls,
|
||||
const struct TALER_EXCHANGE_HttpResponse *hr,
|
||||
unsigned int num_coins,
|
||||
const struct TALER_PlanchetSecretsP *coin_privs,
|
||||
const struct TALER_CoinSpendPrivateKeyP *coin_privs,
|
||||
const struct TALER_DenominationSignature *sigs);
|
||||
|
||||
|
||||
@ -1602,8 +1735,10 @@ struct TALER_EXCHANGE_RefreshesRevealHandle;
|
||||
* prior to calling this function.
|
||||
*
|
||||
* @param exchange the exchange handle; the exchange must be ready to operate
|
||||
* @param refresh_data the refresh data as returned from
|
||||
#TALER_EXCHANGE_refresh_prepare())
|
||||
* @param ps the fresh secret that defines the refresh operation
|
||||
* @param rd the refresh data that characterizes the refresh operation
|
||||
* @param num_coins number of fresh coins to be created, length of the @a exchange_vals array, must match value in @a rd
|
||||
* @param alg_values array @a num_coins of exchange values contributed to the refresh operation
|
||||
* @param noreveal_index response from the exchange to the
|
||||
* #TALER_EXCHANGE_melt() invocation
|
||||
* @param reveal_cb the callback to call with the final result of the
|
||||
@ -1615,7 +1750,10 @@ struct TALER_EXCHANGE_RefreshesRevealHandle;
|
||||
struct TALER_EXCHANGE_RefreshesRevealHandle *
|
||||
TALER_EXCHANGE_refreshes_reveal (
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
const json_t *refresh_data,
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
const struct TALER_EXCHANGE_RefreshData *rd,
|
||||
unsigned int num_coins,
|
||||
const struct TALER_ExchangeWithdrawValues *alg_values,
|
||||
uint32_t noreveal_index,
|
||||
TALER_EXCHANGE_RefreshesRevealCallback reveal_cb,
|
||||
void *reveal_cb_cls);
|
||||
@ -2034,6 +2172,7 @@ typedef void
|
||||
* @param exchange the exchange handle; the exchange must be ready to operate
|
||||
* @param pk kind of coin to pay back
|
||||
* @param denom_sig signature over the coin by the exchange using @a pk
|
||||
* @param exchange_vals contribution from the exchange on the withdraw
|
||||
* @param ps secret internals of the original planchet
|
||||
* @param recoup_cb the callback to call when the final result for this request is available
|
||||
* @param recoup_cb_cls closure for @a recoup_cb
|
||||
@ -2045,6 +2184,7 @@ struct TALER_EXCHANGE_RecoupHandle *
|
||||
TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange,
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *pk,
|
||||
const struct TALER_DenominationSignature *denom_sig,
|
||||
const struct TALER_ExchangeWithdrawValues *exchange_vals,
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
TALER_EXCHANGE_RecoupResultCallback recoup_cb,
|
||||
void *recoup_cb_cls);
|
||||
@ -2094,7 +2234,8 @@ typedef void
|
||||
* @param exchange the exchange handle; the exchange must be ready to operate
|
||||
* @param pk kind of coin to pay back
|
||||
* @param denom_sig signature over the coin by the exchange using @a pk
|
||||
* @param ps secret internals of the original planchet
|
||||
* @param exchange_vals contribution from the exchange on the withdraw
|
||||
* @param ps secret internals of the original refresh-reveal operation
|
||||
* @param recoup_cb the callback to call when the final result for this request is available
|
||||
* @param recoup_cb_cls closure for @a recoup_cb
|
||||
* @return NULL
|
||||
@ -2106,6 +2247,7 @@ TALER_EXCHANGE_recoup_refresh (
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *pk,
|
||||
const struct TALER_DenominationSignature *denom_sig,
|
||||
const struct TALER_ExchangeWithdrawValues *exchange_vals,
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
TALER_EXCHANGE_RecoupRefreshResultCallback recoup_cb,
|
||||
void *recoup_cb_cls);
|
||||
@ -2497,10 +2639,15 @@ struct TALER_EXCHANGE_FutureKeys
|
||||
struct TALER_SecurityModulePublicKeyP signkey_secmod_public_key;
|
||||
|
||||
/**
|
||||
* Public key of the denomination security module.
|
||||
* Public key of the RSA denomination security module.
|
||||
*/
|
||||
struct TALER_SecurityModulePublicKeyP denom_secmod_public_key;
|
||||
|
||||
/**
|
||||
* Public key of the CS denomination security module.
|
||||
*/
|
||||
struct TALER_SecurityModulePublicKeyP denom_secmod_cs_public_key;
|
||||
|
||||
/**
|
||||
* Offline master public key used by this exchange.
|
||||
*/
|
||||
|
@ -340,7 +340,7 @@ struct TALER_EXCHANGEDB_TableData
|
||||
struct TALER_MerchantPublicKeyP merchant_pub;
|
||||
struct TALER_PrivateContractHash h_contract_terms;
|
||||
struct TALER_CoinSpendSignatureP coin_sig;
|
||||
struct TALER_WireSalt wire_salt;
|
||||
struct TALER_WireSaltP wire_salt;
|
||||
uint64_t wire_target_serial_id;
|
||||
bool tiny;
|
||||
bool done;
|
||||
@ -1027,7 +1027,7 @@ struct TALER_EXCHANGEDB_Deposit
|
||||
/**
|
||||
* Salt used by the merchant to compute "h_wire".
|
||||
*/
|
||||
struct TALER_WireSalt wire_salt;
|
||||
struct TALER_WireSaltP wire_salt;
|
||||
|
||||
/**
|
||||
* Information about the receiver for executing the transaction. URI in
|
||||
@ -1126,7 +1126,7 @@ struct TALER_EXCHANGEDB_DepositListEntry
|
||||
/**
|
||||
* Salt used to compute h_wire from the @e receiver_wire_account.
|
||||
*/
|
||||
struct TALER_WireSalt wire_salt;
|
||||
struct TALER_WireSaltP wire_salt;
|
||||
|
||||
/**
|
||||
* Time when this request was generated. Used, for example, to
|
||||
@ -1646,14 +1646,9 @@ struct TALER_EXCHANGEDB_RefreshRevealedCoin
|
||||
struct TALER_BlindedDenominationSignature coin_sig;
|
||||
|
||||
/**
|
||||
* Blinded message to be signed (in envelope), with @e coin_env_size bytes.
|
||||
* Blinded message to be signed (in envelope).
|
||||
*/
|
||||
void *coin_ev;
|
||||
|
||||
/**
|
||||
* Number of bytes in @e coin_ev.
|
||||
*/
|
||||
size_t coin_ev_size;
|
||||
struct TALER_BlindedPlanchet blinded_planchet;
|
||||
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014, 2015, 2016, 2021 Taler Systems SA
|
||||
Copyright (C) 2014, 2015, 2016, 2021, 2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -117,6 +117,20 @@ TALER_JSON_pack_blinded_denom_sig (
|
||||
const struct TALER_BlindedDenominationSignature *sig);
|
||||
|
||||
|
||||
/**
|
||||
* Generate packer instruction for a JSON field of type
|
||||
* blinded planchet.
|
||||
*
|
||||
* @param name name of the field to add to the object
|
||||
* @param blinded_planchet blinded planchet
|
||||
* @return json pack specification
|
||||
*/
|
||||
struct GNUNET_JSON_PackSpec
|
||||
TALER_JSON_pack_blinded_planchet (
|
||||
const char *name,
|
||||
const struct TALER_BlindedPlanchet *blinded_planchet);
|
||||
|
||||
|
||||
/**
|
||||
* Generate packer instruction for a JSON field of type
|
||||
* amount.
|
||||
@ -238,7 +252,7 @@ TALER_JSON_spec_denom_pub (const char *field,
|
||||
* Generate line in parser specification for denomination signature.
|
||||
*
|
||||
* @param field name of the field
|
||||
* @param sig the signature to initialize
|
||||
* @param[out] sig the signature to initialize
|
||||
* @return corresponding field spec
|
||||
*/
|
||||
struct GNUNET_JSON_Specification
|
||||
@ -251,7 +265,7 @@ TALER_JSON_spec_denom_sig (const char *field,
|
||||
* blinded denomination signature.
|
||||
*
|
||||
* @param field name of the field
|
||||
* @param sig the blinded signature to initialize
|
||||
* @param[out] sig the blinded signature to initialize
|
||||
* @return corresponding field spec
|
||||
*/
|
||||
struct GNUNET_JSON_Specification
|
||||
@ -260,6 +274,19 @@ TALER_JSON_spec_blinded_denom_sig (
|
||||
struct TALER_BlindedDenominationSignature *sig);
|
||||
|
||||
|
||||
/**
|
||||
* Generate line in parser specification for a
|
||||
* blinded planchet.
|
||||
*
|
||||
* @param field name of the field
|
||||
* @param[out] blinded_planchet the blinded planchet to initialize
|
||||
* @return corresponding field spec
|
||||
*/
|
||||
struct GNUNET_JSON_Specification
|
||||
TALER_JSON_spec_blinded_planchet (const char *field,
|
||||
struct TALER_BlindedPlanchet *blinded_planchet);
|
||||
|
||||
|
||||
/**
|
||||
* The expected field stores a possibly internationalized string.
|
||||
* Internationalization means that there is another field "$name_i18n"
|
||||
@ -563,6 +590,12 @@ enum GNUNET_GenericReturnValue
|
||||
TALER_JSON_parse_agemask (const json_t *root,
|
||||
struct TALER_AgeMask *mask);
|
||||
|
||||
/**
|
||||
* Canonicalize a JSON input to a string according to RFC 8785.
|
||||
*/
|
||||
char *
|
||||
TALER_JSON_canonicalize (const json_t *input);
|
||||
|
||||
#endif /* TALER_JSON_LIB_H_ */
|
||||
|
||||
/* End of taler_json_lib.h */
|
||||
|
@ -77,6 +77,19 @@ TALER_PQ_query_param_denom_sig (
|
||||
const struct TALER_DenominationSignature *denom_sig);
|
||||
|
||||
|
||||
/**
|
||||
* Generate query parameter for a blinded planchet.
|
||||
* Internally, various attributes of the blinded
|
||||
* planchet will be serialized into on
|
||||
* variable-size BLOB.
|
||||
*
|
||||
* @param x pointer to the query parameter to pass
|
||||
*/
|
||||
struct GNUNET_PQ_QueryParam
|
||||
TALER_PQ_query_param_blinded_planchet (
|
||||
const struct TALER_BlindedPlanchet *bp);
|
||||
|
||||
|
||||
/**
|
||||
* Generate query parameter for a blinded denomination signature. Internally,
|
||||
* the various attributes of the signature will be serialized into on
|
||||
@ -166,6 +179,19 @@ TALER_PQ_result_spec_blinded_denom_sig (
|
||||
struct TALER_BlindedDenominationSignature *denom_sig);
|
||||
|
||||
|
||||
/**
|
||||
* Blinded planchet expected.
|
||||
*
|
||||
* @param name name of the field in the table
|
||||
* @param[out] bp where to store the blinded planchet
|
||||
* @return array entry for the result specification to use
|
||||
*/
|
||||
struct GNUNET_PQ_ResultSpec
|
||||
TALER_PQ_result_spec_blinded_planchet (
|
||||
const char *name,
|
||||
struct TALER_BlindedPlanchet *bp);
|
||||
|
||||
|
||||
/**
|
||||
* json_t expected.
|
||||
*
|
||||
|
@ -287,6 +287,11 @@
|
||||
*/
|
||||
#define TALER_SIGNATURE_SM_SIGNING_KEY 1251
|
||||
|
||||
/**
|
||||
* Signature on a denomination key announcement.
|
||||
*/
|
||||
#define TALER_SIGNATURE_SM_CS_DENOMINATION_KEY 1252
|
||||
|
||||
/*******************/
|
||||
/* Test signatures */
|
||||
/*******************/
|
||||
@ -341,7 +346,7 @@ struct TALER_DenominationKeyAnnouncementPS
|
||||
/**
|
||||
* Hash of the denomination public key.
|
||||
*/
|
||||
struct TALER_RsaPubHashP h_rsa;
|
||||
struct TALER_DenominationHash h_denom;
|
||||
|
||||
/**
|
||||
* Hash of the section name in the configuration of this denomination.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
(C) 2018 Taler Systems SA
|
||||
(C) 2018-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
@ -2443,6 +2443,7 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits,
|
||||
#define TALER_TESTING_SIMPLE_TRAITS(op) \
|
||||
op (bank_row, const uint64_t) \
|
||||
op (reserve_priv, const struct TALER_ReservePrivateKeyP) \
|
||||
op (planchet_secret, const struct TALER_PlanchetSecretsP) \
|
||||
op (reserve_pub, const struct TALER_ReservePublicKeyP) \
|
||||
op (merchant_priv, const struct TALER_MerchantPrivateKeyP) \
|
||||
op (merchant_pub, const struct TALER_MerchantPublicKeyP) \
|
||||
@ -2482,6 +2483,8 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits,
|
||||
#define TALER_TESTING_INDEXED_TRAITS(op) \
|
||||
op (denom_pub, const struct TALER_EXCHANGE_DenomPublicKey) \
|
||||
op (denom_sig, const struct TALER_DenominationSignature) \
|
||||
op (planchet_secrets, const struct TALER_PlanchetSecretsP) \
|
||||
op (exchange_wd_value, const struct TALER_ExchangeWithdrawValues) \
|
||||
op (coin_priv, const struct TALER_CoinSpendPrivateKeyP) \
|
||||
op (coin_pub, const struct TALER_CoinSpendPublicKeyP) \
|
||||
op (absolute_time, const struct GNUNET_TIME_Absolute) \
|
||||
|
@ -78,27 +78,27 @@ lowdump (struct GNUNET_Buffer *buf,
|
||||
{
|
||||
case 0x8:
|
||||
GNUNET_buffer_write (buf,
|
||||
"\b",
|
||||
"\\b",
|
||||
2);
|
||||
break;
|
||||
case 0x9:
|
||||
GNUNET_buffer_write (buf,
|
||||
"\t",
|
||||
"\\t",
|
||||
2);
|
||||
break;
|
||||
case 0xA:
|
||||
GNUNET_buffer_write (buf,
|
||||
"\n",
|
||||
"\\n",
|
||||
2);
|
||||
break;
|
||||
case 0xC:
|
||||
GNUNET_buffer_write (buf,
|
||||
"\f",
|
||||
"\\f",
|
||||
2);
|
||||
break;
|
||||
case 0xD:
|
||||
GNUNET_buffer_write (buf,
|
||||
"\r",
|
||||
"\\r",
|
||||
2);
|
||||
break;
|
||||
default:
|
||||
@ -144,6 +144,9 @@ rfc8785encode (char **inp)
|
||||
if ( (1 == mbl) &&
|
||||
(val <= 0x1F) )
|
||||
{
|
||||
/* Should not happen, as input is produced by
|
||||
* JSON stringification */
|
||||
GNUNET_break (0);
|
||||
lowdump (&buf,
|
||||
val);
|
||||
}
|
||||
@ -193,6 +196,12 @@ rfc8785encode (char **inp)
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
mbl = 2;
|
||||
GNUNET_buffer_write (&buf,
|
||||
pos,
|
||||
mbl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1009,6 +1018,24 @@ TALER_deposit_extension_hash (const json_t *extensions,
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
TALER_JSON_canonicalize (const json_t *input)
|
||||
{
|
||||
char *wire_enc;
|
||||
|
||||
if (NULL == (wire_enc = json_dumps (input,
|
||||
JSON_ENCODE_ANY
|
||||
| JSON_COMPACT
|
||||
| JSON_SORT_KEYS)))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return NULL;
|
||||
}
|
||||
rfc8785encode (&wire_enc);
|
||||
return wire_enc;
|
||||
}
|
||||
|
||||
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_JSON_extensions_config_hash (const json_t *config,
|
||||
struct TALER_ExtensionConfigHash *ech)
|
||||
|
@ -262,6 +262,26 @@ parse_denom_pub (void *cls,
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (root,
|
||||
ispec,
|
||||
&emsg,
|
||||
&eline))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
case TALER_DENOMINATION_CS:
|
||||
{
|
||||
struct GNUNET_JSON_Specification ispec[] = {
|
||||
GNUNET_JSON_spec_fixed ("cs_public_key",
|
||||
&denom_pub->details.cs_public_key,
|
||||
sizeof (denom_pub->details.cs_public_key)),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (root,
|
||||
ispec,
|
||||
@ -357,6 +377,27 @@ parse_denom_sig (void *cls,
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (root,
|
||||
ispec,
|
||||
&emsg,
|
||||
&eline))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
case TALER_DENOMINATION_CS:
|
||||
{
|
||||
struct GNUNET_JSON_Specification ispec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto ("cs_signature_r",
|
||||
&denom_sig->details.cs_signature.r_point),
|
||||
GNUNET_JSON_spec_fixed_auto ("cs_signature_s",
|
||||
&denom_sig->details.cs_signature.s_scalar),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (root,
|
||||
ispec,
|
||||
@ -463,6 +504,29 @@ parse_blinded_denom_sig (void *cls,
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
case TALER_DENOMINATION_CS:
|
||||
{
|
||||
struct GNUNET_JSON_Specification ispec[] = {
|
||||
GNUNET_JSON_spec_uint32 ("b",
|
||||
&denom_sig->details.blinded_cs_answer.b),
|
||||
GNUNET_JSON_spec_fixed_auto ("s",
|
||||
&denom_sig->details.blinded_cs_answer.
|
||||
s_scalar),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (root,
|
||||
ispec,
|
||||
&emsg,
|
||||
&eline))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
@ -503,6 +567,129 @@ TALER_JSON_spec_blinded_denom_sig (
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse given JSON object to blinded planchet.
|
||||
*
|
||||
* @param cls closure, NULL
|
||||
* @param root the json object representing data
|
||||
* @param[out] spec where to write the data
|
||||
* @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
parse_blinded_planchet (void *cls,
|
||||
json_t *root,
|
||||
struct GNUNET_JSON_Specification *spec)
|
||||
{
|
||||
struct TALER_BlindedPlanchet *blinded_planchet = spec->ptr;
|
||||
uint32_t cipher;
|
||||
struct GNUNET_JSON_Specification dspec[] = {
|
||||
GNUNET_JSON_spec_uint32 ("cipher",
|
||||
&cipher),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
const char *emsg;
|
||||
unsigned int eline;
|
||||
|
||||
(void) cls;
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (root,
|
||||
dspec,
|
||||
&emsg,
|
||||
&eline))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
blinded_planchet->cipher = (enum TALER_DenominationCipher) cipher;
|
||||
switch (blinded_planchet->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
{
|
||||
struct GNUNET_JSON_Specification ispec[] = {
|
||||
GNUNET_JSON_spec_varsize (
|
||||
"rsa_blinded_planchet",
|
||||
&blinded_planchet->details.rsa_blinded_planchet.blinded_msg,
|
||||
&blinded_planchet->details.rsa_blinded_planchet.blinded_msg_size),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (root,
|
||||
ispec,
|
||||
&emsg,
|
||||
&eline))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
case TALER_DENOMINATION_CS:
|
||||
{
|
||||
struct GNUNET_JSON_Specification ispec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto (
|
||||
"cs_nonce",
|
||||
&blinded_planchet->details.cs_blinded_planchet.nonce),
|
||||
GNUNET_JSON_spec_fixed_auto (
|
||||
"cs_blinded_c0",
|
||||
&blinded_planchet->details.cs_blinded_planchet.c[0]),
|
||||
GNUNET_JSON_spec_fixed_auto (
|
||||
"cs_blinded_c1",
|
||||
&blinded_planchet->details.cs_blinded_planchet.c[1]),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (root,
|
||||
ispec,
|
||||
&emsg,
|
||||
&eline))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cleanup data left from parsing blinded planchet.
|
||||
*
|
||||
* @param cls closure, NULL
|
||||
* @param[out] spec where to free the data
|
||||
*/
|
||||
static void
|
||||
clean_blinded_planchet (void *cls,
|
||||
struct GNUNET_JSON_Specification *spec)
|
||||
{
|
||||
struct TALER_BlindedPlanchet *blinded_planchet = spec->ptr;
|
||||
|
||||
(void) cls;
|
||||
TALER_blinded_planchet_free (blinded_planchet);
|
||||
}
|
||||
|
||||
|
||||
struct GNUNET_JSON_Specification
|
||||
TALER_JSON_spec_blinded_planchet (const char *field,
|
||||
struct TALER_BlindedPlanchet *blinded_planchet)
|
||||
{
|
||||
struct GNUNET_JSON_Specification ret = {
|
||||
.parser = &parse_blinded_planchet,
|
||||
.cleaner = &clean_blinded_planchet,
|
||||
.field = field,
|
||||
.ptr = blinded_planchet
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closure for #parse_i18n_string.
|
||||
*/
|
||||
@ -686,7 +873,6 @@ TALER_JSON_parse_agemask (const json_t *root,
|
||||
{
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
@ -68,6 +68,17 @@ TALER_JSON_pack_denom_pub (
|
||||
GNUNET_JSON_pack_rsa_public_key ("rsa_public_key",
|
||||
pk->details.rsa_public_key));
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
ps.object
|
||||
= GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_uint64 ("cipher",
|
||||
TALER_DENOMINATION_CS),
|
||||
GNUNET_JSON_pack_uint64 ("age_mask",
|
||||
pk->age_mask.mask),
|
||||
GNUNET_JSON_pack_data_varsize ("cs_public_key",
|
||||
&pk->details.cs_public_key,
|
||||
sizeof (pk->details.cs_public_key)));
|
||||
break;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -87,13 +98,21 @@ TALER_JSON_pack_denom_sig (
|
||||
switch (sig->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
ps.object
|
||||
= GNUNET_JSON_PACK (
|
||||
ps.object = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_uint64 ("cipher",
|
||||
TALER_DENOMINATION_RSA),
|
||||
GNUNET_JSON_pack_rsa_signature ("rsa_signature",
|
||||
sig->details.rsa_signature));
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
ps.object = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_uint64 ("cipher",
|
||||
TALER_DENOMINATION_CS),
|
||||
GNUNET_JSON_pack_data_auto ("cs_signature_r",
|
||||
&sig->details.cs_signature.r_point),
|
||||
GNUNET_JSON_pack_data_auto ("cs_signature_s",
|
||||
&sig->details.cs_signature.s_scalar));
|
||||
break;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -113,13 +132,62 @@ TALER_JSON_pack_blinded_denom_sig (
|
||||
switch (sig->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
ps.object
|
||||
= GNUNET_JSON_PACK (
|
||||
ps.object = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_uint64 ("cipher",
|
||||
TALER_DENOMINATION_RSA),
|
||||
GNUNET_JSON_pack_rsa_signature ("blinded_rsa_signature",
|
||||
sig->details.blinded_rsa_signature));
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
ps.object = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_uint64 ("cipher",
|
||||
TALER_DENOMINATION_CS),
|
||||
GNUNET_JSON_pack_uint64 ("b",
|
||||
sig->details.blinded_cs_answer.b),
|
||||
GNUNET_JSON_pack_data_auto ("s",
|
||||
&sig->details.blinded_cs_answer.s_scalar));
|
||||
break;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
return ps;
|
||||
}
|
||||
|
||||
|
||||
struct GNUNET_JSON_PackSpec
|
||||
TALER_JSON_pack_blinded_planchet (
|
||||
const char *name,
|
||||
const struct TALER_BlindedPlanchet *blinded_planchet)
|
||||
{
|
||||
struct GNUNET_JSON_PackSpec ps = {
|
||||
.field_name = name,
|
||||
};
|
||||
|
||||
switch (blinded_planchet->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
ps.object = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_uint64 ("cipher",
|
||||
TALER_DENOMINATION_RSA),
|
||||
GNUNET_JSON_pack_data_varsize (
|
||||
"rsa_blinded_planchet",
|
||||
blinded_planchet->details.rsa_blinded_planchet.blinded_msg,
|
||||
blinded_planchet->details.rsa_blinded_planchet.blinded_msg_size));
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
ps.object = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_uint64 ("cipher",
|
||||
TALER_DENOMINATION_CS),
|
||||
GNUNET_JSON_pack_data_auto (
|
||||
"cs_nonce",
|
||||
&blinded_planchet->details.cs_blinded_planchet.nonce),
|
||||
GNUNET_JSON_pack_data_auto (
|
||||
"cs_blinded_c0",
|
||||
&blinded_planchet->details.cs_blinded_planchet.c[0]),
|
||||
GNUNET_JSON_pack_data_auto (
|
||||
"cs_blinded_c1",
|
||||
&blinded_planchet->details.cs_blinded_planchet.c[1]));
|
||||
break;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ TALER_JSON_merchant_wire_signature_hash (const json_t *wire_s,
|
||||
struct TALER_MerchantWireHash *hc)
|
||||
{
|
||||
const char *payto_uri;
|
||||
struct TALER_WireSalt salt;
|
||||
struct TALER_WireSaltP salt;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_string ("payto_uri",
|
||||
&payto_uri),
|
||||
|
@ -160,7 +160,7 @@ test_contract (void)
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_JSON_contract_part_forget (c1,
|
||||
"k2"));
|
||||
json_dumpf (c1, stderr, JSON_INDENT (2));
|
||||
// json_dumpf (c1, stderr, JSON_INDENT (2));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_JSON_contract_hash (c1,
|
||||
&h2));
|
||||
@ -182,7 +182,7 @@ test_contract (void)
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_JSON_contract_hash (c1,
|
||||
&h1));
|
||||
json_dumpf (c1, stderr, JSON_INDENT (2));
|
||||
// json_dumpf (c1, stderr, JSON_INDENT (2));
|
||||
json_decref (c1);
|
||||
{
|
||||
char *s;
|
||||
@ -330,6 +330,57 @@ test_contract (void)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
test_json_canon (void)
|
||||
{
|
||||
{
|
||||
json_t *c1;
|
||||
char *canon;
|
||||
c1 = json_pack ("{s:s}",
|
||||
"k1", "Hello\nWorld");
|
||||
|
||||
canon = TALER_JSON_canonicalize (c1);
|
||||
GNUNET_assert (NULL != canon);
|
||||
|
||||
printf ("canon: '%s'\n", canon);
|
||||
|
||||
GNUNET_assert (0 == strcmp (canon,
|
||||
"{\"k1\":\"Hello\\nWorld\"}"));
|
||||
}
|
||||
{
|
||||
json_t *c1;
|
||||
char *canon;
|
||||
c1 = json_pack ("{s:s}",
|
||||
"k1", "Testing “unicode” characters");
|
||||
|
||||
canon = TALER_JSON_canonicalize (c1);
|
||||
GNUNET_assert (NULL != canon);
|
||||
|
||||
printf ("canon: '%s'\n", canon);
|
||||
|
||||
GNUNET_assert (0 == strcmp (canon,
|
||||
"{\"k1\":\"Testing “unicode” characters\"}"));
|
||||
}
|
||||
{
|
||||
json_t *c1;
|
||||
char *canon;
|
||||
c1 = json_pack ("{s:s}",
|
||||
"k1", "low range \x05 chars");
|
||||
|
||||
canon = TALER_JSON_canonicalize (c1);
|
||||
GNUNET_assert (NULL != canon);
|
||||
|
||||
printf ("canon: '%s'\n", canon);
|
||||
|
||||
GNUNET_assert (0 == strcmp (canon,
|
||||
"{\"k1\":\"low range \\u0005 chars\"}"));
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
test_rfc8785 (void)
|
||||
{
|
||||
@ -348,7 +399,7 @@ test_rfc8785 (void)
|
||||
sizeof (h1));
|
||||
if (0 !=
|
||||
strcmp (s,
|
||||
"J678K3PW9Y3DG63Z3T7ZYR2P7CEXMVZ2SFPQMABACK9TJRYREPP82542PCJ0P7Y7FAQAMWECDX50XH1RBTWHX6SSJHH6FXRV0JCS6R8"))
|
||||
"531S33T8ZRGW6548G7T67PMDNGS4Z1D8A2GMB87G3PNKYTW6KGF7Q99XVCGXBKVA2HX6PR5ENJ1PQ5ZTYMMXQB6RM7S82VP7ZG2X5G8"))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Invalid reference hash: %s\n",
|
||||
@ -377,6 +428,8 @@ main (int argc,
|
||||
return 1;
|
||||
if (0 != test_contract ())
|
||||
return 2;
|
||||
if (0 != test_json_canon ())
|
||||
return 2;
|
||||
if (0 != test_rfc8785 ())
|
||||
return 2;
|
||||
return 0;
|
||||
|
@ -24,6 +24,7 @@ libtalerexchange_la_SOURCES = \
|
||||
exchange_api_auditor_add_denomination.c \
|
||||
exchange_api_curl_defaults.c exchange_api_curl_defaults.h \
|
||||
exchange_api_common.c \
|
||||
exchange_api_csr.c \
|
||||
exchange_api_handle.c exchange_api_handle.h \
|
||||
exchange_api_deposit.c \
|
||||
exchange_api_deposits_get.c \
|
||||
|
327
src/lib/exchange_api_csr.c
Normal file
327
src/lib/exchange_api_csr.c
Normal file
@ -0,0 +1,327 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 3, or (at your option) any later version.
|
||||
|
||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
TALER; see the file COPYING. If not, see
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file lib/exchange_api_csr.c
|
||||
* @brief Implementation of /csr requests (get R in exchange used for Clause Schnorr withdraw and refresh)
|
||||
* @author Lucien Heuzeveldt
|
||||
* @author Gian Demarmels
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include <jansson.h>
|
||||
#include <microhttpd.h> /* just for HTTP status codes */
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include <gnunet/gnunet_json_lib.h>
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "taler_exchange_service.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_signatures.h"
|
||||
#include "exchange_api_curl_defaults.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief A Clause Schnorr R Handle
|
||||
*/
|
||||
struct TALER_EXCHANGE_CsRHandle
|
||||
{
|
||||
/**
|
||||
* The connection to exchange this request handle will use
|
||||
*/
|
||||
struct TALER_EXCHANGE_Handle *exchange;
|
||||
|
||||
/**
|
||||
* Function to call with the result.
|
||||
*/
|
||||
TALER_EXCHANGE_CsRCallback cb;
|
||||
|
||||
/**
|
||||
* Closure for @a cb.
|
||||
*/
|
||||
void *cb_cls;
|
||||
|
||||
/**
|
||||
* The url for this request.
|
||||
*/
|
||||
char *url;
|
||||
|
||||
/**
|
||||
* Handle for the request.
|
||||
*/
|
||||
struct GNUNET_CURL_Job *job;
|
||||
|
||||
/**
|
||||
* Context for #TEH_curl_easy_post(). Keeps the data that must
|
||||
* persist for Curl to make the upload.
|
||||
*/
|
||||
struct TALER_CURL_PostContext post_ctx;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* We got a 200 OK response for the /reserves/$RESERVE_PUB/withdraw operation.
|
||||
* Extract the coin's signature and return it to the caller. The signature we
|
||||
* get from the exchange is for the blinded value. Thus, we first must
|
||||
* unblind it and then should verify its validity against our coin's hash.
|
||||
*
|
||||
* If everything checks out, we return the unblinded signature
|
||||
* to the application via the callback.
|
||||
*
|
||||
* @param csrh operation handle
|
||||
* @param arr reply from the exchange
|
||||
* @param hr http response details
|
||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
csr_ok (struct TALER_EXCHANGE_CsRHandle *csrh,
|
||||
json_t *arr,
|
||||
struct TALER_EXCHANGE_HttpResponse *hr)
|
||||
{
|
||||
unsigned int alen = json_array_size (arr);
|
||||
struct TALER_ExchangeWithdrawValues alg_values[GNUNET_NZL (alen)];
|
||||
struct TALER_EXCHANGE_CsRResponse csrr = {
|
||||
.hr = *hr,
|
||||
.details.success.alg_values_len = alen,
|
||||
.details.success.alg_values = alg_values
|
||||
};
|
||||
|
||||
for (unsigned int i = 0; i<alen; i++)
|
||||
{
|
||||
json_t *av = json_array_get (arr,
|
||||
i);
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_fixed (
|
||||
"r_pub_0",
|
||||
&alg_values[i].details.cs_values.r_pub_pair.r_pub[0],
|
||||
sizeof (struct GNUNET_CRYPTO_CsRPublic)),
|
||||
GNUNET_JSON_spec_fixed (
|
||||
"r_pub_1",
|
||||
&alg_values[i].details.cs_values.r_pub_pair.r_pub[1],
|
||||
sizeof (struct GNUNET_CRYPTO_CsRPublic)),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (av,
|
||||
spec,
|
||||
NULL, NULL))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
}
|
||||
csrh->cb (csrh->cb_cls,
|
||||
&csrr);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called when we're done processing the HTTP /csr request.
|
||||
*
|
||||
* @param cls the `struct TALER_EXCHANGE_CsRHandle`
|
||||
* @param response_code HTTP response code, 0 on error
|
||||
* @param response parsed JSON result, NULL on error
|
||||
*/
|
||||
static void
|
||||
handle_csr_finished (void *cls,
|
||||
long response_code,
|
||||
const void *response)
|
||||
{
|
||||
struct TALER_EXCHANGE_CsRHandle *csrh = cls;
|
||||
const json_t *j = response;
|
||||
struct TALER_EXCHANGE_HttpResponse hr = {
|
||||
.reply = j,
|
||||
.http_status = (unsigned int) response_code
|
||||
};
|
||||
struct TALER_EXCHANGE_CsRResponse csrr = {
|
||||
.hr = hr
|
||||
};
|
||||
|
||||
csrh->job = NULL;
|
||||
switch (response_code)
|
||||
{
|
||||
case 0:
|
||||
csrr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
|
||||
break;
|
||||
case MHD_HTTP_OK:
|
||||
{
|
||||
json_t *arr;
|
||||
|
||||
arr = json_object_get (j,
|
||||
"ewvs");
|
||||
if ( (NULL == arr) ||
|
||||
(0 == json_array_size (arr)) ||
|
||||
(GNUNET_OK !=
|
||||
csr_ok (csrh,
|
||||
arr,
|
||||
&hr)) )
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
csrr.hr.http_status = 0;
|
||||
csrr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
TALER_EXCHANGE_csr_cancel (csrh);
|
||||
return;
|
||||
case MHD_HTTP_BAD_REQUEST:
|
||||
/* This should never happen, either us or the exchange is buggy
|
||||
(or API version conflict); just pass JSON reply to the application */
|
||||
csrr.hr.ec = TALER_JSON_get_error_code (j);
|
||||
csrr.hr.hint = TALER_JSON_get_error_hint (j);
|
||||
break;
|
||||
case MHD_HTTP_NOT_FOUND:
|
||||
/* Nothing really to verify, the exchange basically just says
|
||||
that it doesn't know the /csr endpoint or denomination.
|
||||
Can happen if the exchange doesn't support Clause Schnorr.
|
||||
We should simply pass the JSON reply to the application. */
|
||||
csrr.hr.ec = TALER_JSON_get_error_code (j);
|
||||
csrr.hr.hint = TALER_JSON_get_error_hint (j);
|
||||
break;
|
||||
case MHD_HTTP_GONE:
|
||||
/* could happen if denomination was revoked */
|
||||
/* Note: one might want to check /keys for revocation
|
||||
signature here, alas tricky in case our /keys
|
||||
is outdated => left to clients */
|
||||
csrr.hr.ec = TALER_JSON_get_error_code (j);
|
||||
csrr.hr.hint = TALER_JSON_get_error_hint (j);
|
||||
break;
|
||||
case MHD_HTTP_INTERNAL_SERVER_ERROR:
|
||||
/* Server had an internal issue; we should retry, but this API
|
||||
leaves this to the application */
|
||||
csrr.hr.ec = TALER_JSON_get_error_code (j);
|
||||
csrr.hr.hint = TALER_JSON_get_error_hint (j);
|
||||
break;
|
||||
default:
|
||||
/* unexpected response code */
|
||||
GNUNET_break_op (0);
|
||||
csrr.hr.ec = TALER_JSON_get_error_code (j);
|
||||
csrr.hr.hint = TALER_JSON_get_error_hint (j);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unexpected response code %u/%d for CS R request\n",
|
||||
(unsigned int) response_code,
|
||||
(int) hr.ec);
|
||||
break;
|
||||
}
|
||||
csrh->cb (csrh->cb_cls,
|
||||
&csrr);
|
||||
csrh->cb = NULL;
|
||||
TALER_EXCHANGE_csr_cancel (csrh);
|
||||
}
|
||||
|
||||
|
||||
struct TALER_EXCHANGE_CsRHandle *
|
||||
TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange,
|
||||
unsigned int nks_len,
|
||||
struct TALER_EXCHANGE_NonceKey *nks,
|
||||
TALER_EXCHANGE_CsRCallback res_cb,
|
||||
void *res_cb_cls)
|
||||
{
|
||||
struct TALER_EXCHANGE_CsRHandle *csrh;
|
||||
json_t *csr_arr;
|
||||
|
||||
if (0 == nks_len)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return NULL;
|
||||
}
|
||||
for (unsigned int i = 0; i<nks_len; i++)
|
||||
if (TALER_DENOMINATION_CS != nks[i].pk->key.cipher)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
csrh = GNUNET_new (struct TALER_EXCHANGE_CsRHandle);
|
||||
csrh->exchange = exchange;
|
||||
csrh->cb = res_cb;
|
||||
csrh->cb_cls = res_cb_cls;
|
||||
|
||||
csr_arr = json_array ();
|
||||
GNUNET_assert (NULL != csr_arr);
|
||||
for (unsigned int i = 0; i<nks_len; i++)
|
||||
{
|
||||
const struct TALER_EXCHANGE_NonceKey *nk = &nks[i];
|
||||
json_t *csr_obj;
|
||||
|
||||
csr_obj = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_varsize ("nonce",
|
||||
&nk->nonce,
|
||||
sizeof(struct TALER_CsNonce)),
|
||||
GNUNET_JSON_pack_data_varsize ("denom_pub_hash",
|
||||
&nk->pk->h_key,
|
||||
sizeof(struct TALER_DenominationHash)));
|
||||
GNUNET_assert (NULL != csr_obj);
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (csr_arr,
|
||||
csr_obj));
|
||||
}
|
||||
csrh->url = TEAH_path_to_url (exchange,
|
||||
"/csr");
|
||||
if (NULL == csrh->url)
|
||||
{
|
||||
json_decref (csr_arr);
|
||||
GNUNET_free (csrh);
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
CURL *eh;
|
||||
struct GNUNET_CURL_Context *ctx;
|
||||
json_t *req;
|
||||
|
||||
req = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_array_steal ("nks",
|
||||
csr_arr));
|
||||
ctx = TEAH_handle_to_context (exchange);
|
||||
eh = TALER_EXCHANGE_curl_easy_get_ (csrh->url);
|
||||
if ( (NULL == eh) ||
|
||||
(GNUNET_OK !=
|
||||
TALER_curl_easy_post (&csrh->post_ctx,
|
||||
eh,
|
||||
req)) )
|
||||
{
|
||||
GNUNET_break (0);
|
||||
if (NULL != eh)
|
||||
curl_easy_cleanup (eh);
|
||||
json_decref (req);
|
||||
GNUNET_free (csrh->url);
|
||||
GNUNET_free (csrh);
|
||||
return NULL;
|
||||
}
|
||||
json_decref (req);
|
||||
csrh->job = GNUNET_CURL_job_add2 (ctx,
|
||||
eh,
|
||||
csrh->post_ctx.headers,
|
||||
&handle_csr_finished,
|
||||
csrh);
|
||||
}
|
||||
return csrh;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_EXCHANGE_csr_cancel (struct TALER_EXCHANGE_CsRHandle *csrh)
|
||||
{
|
||||
if (NULL != csrh->job)
|
||||
{
|
||||
GNUNET_CURL_job_cancel (csrh->job);
|
||||
csrh->job = NULL;
|
||||
}
|
||||
GNUNET_free (csrh->url);
|
||||
TALER_curl_easy_post_finished (&csrh->post_ctx);
|
||||
GNUNET_free (csrh);
|
||||
}
|
@ -545,7 +545,7 @@ TALER_EXCHANGE_deposit (
|
||||
const struct TALER_Amount *amount,
|
||||
struct GNUNET_TIME_Timestamp wire_deadline,
|
||||
const char *merchant_payto_uri,
|
||||
const struct TALER_WireSalt *wire_salt,
|
||||
const struct TALER_WireSaltP *wire_salt,
|
||||
const struct TALER_PrivateContractHash *h_contract_terms,
|
||||
const json_t *extension_details,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
|
@ -94,6 +94,7 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
|
||||
struct TALER_BlindedDenominationSignature bsig;
|
||||
struct TALER_DenominationPublicKey rpub;
|
||||
struct TALER_CoinSpendSignatureP link_sig;
|
||||
union TALER_DenominationBlindingKeyP bks;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
TALER_JSON_spec_denom_pub ("denom_pub",
|
||||
&rpub),
|
||||
@ -104,7 +105,8 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
struct TALER_TransferSecretP secret;
|
||||
struct TALER_PlanchetSecretsP fc;
|
||||
struct TALER_PlanchetSecretsP ps;
|
||||
struct TALER_ExchangeWithdrawValues alg_values;
|
||||
|
||||
/* parse reply */
|
||||
if (GNUNET_OK !=
|
||||
@ -118,23 +120,31 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
|
||||
TALER_link_recover_transfer_secret (trans_pub,
|
||||
&lh->coin_priv,
|
||||
&secret);
|
||||
TALER_planchet_setup_refresh (&secret,
|
||||
TALER_transfer_secret_to_planchet_secret (&secret,
|
||||
coin_num,
|
||||
&fc);
|
||||
&ps);
|
||||
|
||||
// TODO: implement cipher handling
|
||||
alg_values.cipher = TALER_DENOMINATION_RSA;
|
||||
TALER_planchet_setup_coin_priv (&ps,
|
||||
&alg_values,
|
||||
coin_priv);
|
||||
TALER_planchet_blinding_secret_create (&ps,
|
||||
&alg_values,
|
||||
&bks);
|
||||
/* extract coin and signature */
|
||||
if (GNUNET_OK !=
|
||||
TALER_denom_sig_unblind (sig,
|
||||
&bsig,
|
||||
&fc.blinding_key,
|
||||
&bks,
|
||||
&rpub))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
*coin_priv = fc.coin_priv;
|
||||
/* verify link_sig */
|
||||
{
|
||||
struct TALER_ExchangeWithdrawValues alg_values;
|
||||
struct TALER_PlanchetDetail pd;
|
||||
struct TALER_CoinPubHash c_hash;
|
||||
struct TALER_CoinSpendPublicKeyP old_coin_pub;
|
||||
@ -142,9 +152,13 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
|
||||
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&lh->coin_priv.eddsa_priv,
|
||||
&old_coin_pub.eddsa_pub);
|
||||
// TODO: implement cipher handling
|
||||
alg_values.cipher = TALER_DENOMINATION_RSA;
|
||||
if (GNUNET_OK !=
|
||||
TALER_planchet_prepare (&rpub,
|
||||
&fc,
|
||||
&alg_values,
|
||||
&bks,
|
||||
coin_priv,
|
||||
&c_hash,
|
||||
&pd))
|
||||
{
|
||||
@ -152,10 +166,9 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
GNUNET_CRYPTO_hash (pd.coin_ev,
|
||||
pd.coin_ev_size,
|
||||
&coin_envelope_hash.hash);
|
||||
|
||||
TALER_coin_ev_hash (&pd.blinded_planchet,
|
||||
&pd.denom_pub_hash,
|
||||
&coin_envelope_hash);
|
||||
if (GNUNET_OK !=
|
||||
TALER_wallet_link_verify (&pd.denom_pub_hash,
|
||||
trans_pub,
|
||||
@ -164,11 +177,11 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
|
||||
&link_sig))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_free (pd.coin_ev);
|
||||
TALER_blinded_planchet_free (&pd.blinded_planchet);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
GNUNET_free (pd.coin_ev);
|
||||
TALER_blinded_planchet_free (&pd.blinded_planchet);
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
|
@ -92,6 +92,8 @@ handle_ok (struct TALER_EXCHANGE_ManagementGetKeysHandle *gh,
|
||||
&fk.master_pub),
|
||||
GNUNET_JSON_spec_fixed_auto ("denom_secmod_public_key",
|
||||
&fk.denom_secmod_public_key),
|
||||
GNUNET_JSON_spec_fixed_auto ("denom_secmod_cs_public_key",
|
||||
&fk.denom_secmod_cs_public_key),
|
||||
GNUNET_JSON_spec_fixed_auto ("signkey_secmod_public_key",
|
||||
&fk.signkey_secmod_public_key),
|
||||
GNUNET_JSON_spec_end ()
|
||||
@ -243,6 +245,26 @@ handle_ok (struct TALER_EXCHANGE_ManagementGetKeysHandle *gh,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
{
|
||||
struct TALER_CsPubHashP h_cs;
|
||||
|
||||
TALER_cs_pub_hash (&denom_key->key.details.cs_public_key,
|
||||
&h_cs);
|
||||
if (GNUNET_OK !=
|
||||
TALER_exchange_secmod_cs_verify (&h_cs,
|
||||
section_name,
|
||||
denom_key->valid_from,
|
||||
duration,
|
||||
&fk.denom_secmod_cs_public_key,
|
||||
&denom_key->denom_secmod_sig))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
GNUNET_break_op (0);
|
||||
ok = false;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2015-2021 Taler Systems SA
|
||||
Copyright (C) 2015-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -73,7 +73,34 @@ struct TALER_EXCHANGE_MeltHandle
|
||||
/**
|
||||
* Actual information about the melt operation.
|
||||
*/
|
||||
struct MeltData *md;
|
||||
struct MeltData md;
|
||||
|
||||
/**
|
||||
* The secret the entire melt operation is seeded from.
|
||||
*/
|
||||
const struct TALER_PlanchetSecretsP *ps;
|
||||
|
||||
/**
|
||||
* Details about the characteristics of the requested melt operation.
|
||||
*/
|
||||
const struct TALER_EXCHANGE_RefreshData *rd;
|
||||
|
||||
/**
|
||||
* Array of `num_fresh_coins` contributory values of
|
||||
* the exchange to the melt operation.
|
||||
*/
|
||||
struct TALER_ExchangeWithdrawValues *alg_values;
|
||||
|
||||
/**
|
||||
* Array of `num_fresh_coins` blinding secrets
|
||||
* used for blinding the coins.
|
||||
*/
|
||||
union TALER_DenominationBlindingKeyP *bks;
|
||||
|
||||
/**
|
||||
* Handle for the preflight request, or NULL.
|
||||
*/
|
||||
struct TALER_EXCHANGE_CsRHandle *csr;
|
||||
|
||||
/**
|
||||
* Public key of the coin being melted.
|
||||
@ -83,7 +110,7 @@ struct TALER_EXCHANGE_MeltHandle
|
||||
/**
|
||||
* @brief Public information about the coin's denomination key
|
||||
*/
|
||||
struct TALER_EXCHANGE_DenomPublicKey dki;
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *dki;
|
||||
};
|
||||
|
||||
|
||||
@ -106,12 +133,14 @@ verify_melt_signature_ok (struct TALER_EXCHANGE_MeltHandle *mh,
|
||||
struct TALER_ExchangeSignatureP exchange_sig;
|
||||
const struct TALER_EXCHANGE_Keys *key_state;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto ("exchange_sig", &exchange_sig),
|
||||
GNUNET_JSON_spec_fixed_auto ("exchange_pub", exchange_pub),
|
||||
GNUNET_JSON_spec_uint32 ("noreveal_index", noreveal_index),
|
||||
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
|
||||
&exchange_sig),
|
||||
GNUNET_JSON_spec_fixed_auto ("exchange_pub",
|
||||
exchange_pub),
|
||||
GNUNET_JSON_spec_uint32 ("noreveal_index",
|
||||
noreveal_index),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
struct TALER_RefreshMeltConfirmationPS confirm;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (json,
|
||||
@ -121,7 +150,6 @@ verify_melt_signature_ok (struct TALER_EXCHANGE_MeltHandle *mh,
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
/* check that exchange signing key is permitted */
|
||||
key_state = TALER_EXCHANGE_get_keys (mh->exchange);
|
||||
if (GNUNET_OK !=
|
||||
@ -139,12 +167,15 @@ verify_melt_signature_ok (struct TALER_EXCHANGE_MeltHandle *mh,
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
/* verify signature by exchange */
|
||||
confirm.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT);
|
||||
confirm.purpose.size
|
||||
= htonl (sizeof (struct TALER_RefreshMeltConfirmationPS));
|
||||
confirm.rc = mh->md->rc;
|
||||
confirm.noreveal_index = htonl (*noreveal_index);
|
||||
/* verify signature by exchange -- FIXME: move to util! */
|
||||
{
|
||||
struct TALER_RefreshMeltConfirmationPS confirm = {
|
||||
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT),
|
||||
.purpose.size = htonl (sizeof (confirm)),
|
||||
.rc = mh->md.rc,
|
||||
.noreveal_index = htonl (*noreveal_index)
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT,
|
||||
&confirm,
|
||||
@ -154,6 +185,7 @@ verify_melt_signature_ok (struct TALER_EXCHANGE_MeltHandle *mh,
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
@ -182,8 +214,8 @@ verify_melt_signature_denom_conflict (struct TALER_EXCHANGE_MeltHandle *mh,
|
||||
history = json_object_get (json,
|
||||
"history");
|
||||
if (GNUNET_OK !=
|
||||
TALER_EXCHANGE_verify_coin_history (&mh->dki,
|
||||
mh->dki.value.currency,
|
||||
TALER_EXCHANGE_verify_coin_history (mh->dki,
|
||||
mh->dki->value.currency,
|
||||
&mh->coin_pub,
|
||||
history,
|
||||
&h_denom_pub,
|
||||
@ -192,7 +224,7 @@ verify_melt_signature_denom_conflict (struct TALER_EXCHANGE_MeltHandle *mh,
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (0 != GNUNET_memcmp (&mh->dki.h_key,
|
||||
if (0 != GNUNET_memcmp (&mh->dki->h_key,
|
||||
&h_denom_pub))
|
||||
return GNUNET_OK; /* indeed, proof with different denomination key provided */
|
||||
/* invalid proof provided */
|
||||
@ -234,7 +266,7 @@ verify_melt_signature_spend_conflict (struct TALER_EXCHANGE_MeltHandle *mh,
|
||||
}
|
||||
|
||||
/* Find out which coin was deemed problematic by the exchange */
|
||||
mc = &mh->md->melted_coin;
|
||||
mc = &mh->md.melted_coin;
|
||||
/* verify coin history */
|
||||
memset (&h_denom_pub,
|
||||
0,
|
||||
@ -242,7 +274,7 @@ verify_melt_signature_spend_conflict (struct TALER_EXCHANGE_MeltHandle *mh,
|
||||
history = json_object_get (json,
|
||||
"history");
|
||||
if (GNUNET_OK !=
|
||||
TALER_EXCHANGE_verify_coin_history (&mh->dki,
|
||||
TALER_EXCHANGE_verify_coin_history (mh->dki,
|
||||
mc->original_value.currency,
|
||||
&mh->coin_pub,
|
||||
history,
|
||||
@ -281,7 +313,7 @@ verify_melt_signature_spend_conflict (struct TALER_EXCHANGE_MeltHandle *mh,
|
||||
/* everything OK, valid proof of double-spending was provided */
|
||||
return GNUNET_OK;
|
||||
case TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY:
|
||||
if (0 != GNUNET_memcmp (&mh->dki.h_key,
|
||||
if (0 != GNUNET_memcmp (&mh->dki->h_key,
|
||||
&h_denom_pub))
|
||||
return GNUNET_OK; /* indeed, proof with different denomination key provided */
|
||||
/* invalid proof provided */
|
||||
@ -338,6 +370,15 @@ handle_melt_finished (void *cls,
|
||||
{
|
||||
mh->melt_cb (mh->melt_cb_cls,
|
||||
&hr,
|
||||
(0 == hr.http_status)
|
||||
? 0
|
||||
: mh->rd->fresh_pks_len,
|
||||
(0 == hr.http_status)
|
||||
? NULL
|
||||
: mh->alg_values,
|
||||
(0 == hr.http_status)
|
||||
? NULL
|
||||
: mh->bks,
|
||||
noreveal_index,
|
||||
(0 == hr.http_status)
|
||||
? NULL
|
||||
@ -419,66 +460,62 @@ handle_melt_finished (void *cls,
|
||||
if (NULL != mh->melt_cb)
|
||||
mh->melt_cb (mh->melt_cb_cls,
|
||||
&hr,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
UINT32_MAX,
|
||||
NULL);
|
||||
TALER_EXCHANGE_melt_cancel (mh);
|
||||
}
|
||||
|
||||
|
||||
struct TALER_EXCHANGE_MeltHandle *
|
||||
TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
|
||||
const json_t *refresh_data,
|
||||
TALER_EXCHANGE_MeltCallback melt_cb,
|
||||
void *melt_cb_cls)
|
||||
static enum GNUNET_GenericReturnValue
|
||||
start_melt (struct TALER_EXCHANGE_MeltHandle *mh)
|
||||
{
|
||||
const struct TALER_EXCHANGE_Keys *key_state;
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *dki;
|
||||
json_t *melt_obj;
|
||||
struct TALER_EXCHANGE_MeltHandle *mh;
|
||||
CURL *eh;
|
||||
struct GNUNET_CURL_Context *ctx;
|
||||
struct MeltData *md;
|
||||
struct TALER_CoinSpendSignatureP confirm_sig;
|
||||
char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32];
|
||||
struct TALER_DenominationHash h_denom_pub;
|
||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
TEAH_handle_is_ready (exchange));
|
||||
md = TALER_EXCHANGE_deserialize_melt_data_ (refresh_data,
|
||||
exchange->key_data.currency);
|
||||
if (NULL == md)
|
||||
if (GNUNET_OK !=
|
||||
TALER_EXCHANGE_get_melt_data_ (mh->ps,
|
||||
mh->rd,
|
||||
mh->alg_values,
|
||||
&mh->md))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return NULL;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
TALER_denom_pub_hash (&md->melted_coin.pub_key,
|
||||
TALER_denom_pub_hash (&mh->md.melted_coin.pub_key,
|
||||
&h_denom_pub);
|
||||
TALER_wallet_melt_sign (&md->melted_coin.melt_amount_with_fee,
|
||||
&md->melted_coin.fee_melt,
|
||||
&md->rc,
|
||||
TALER_wallet_melt_sign (&mh->md.melted_coin.melt_amount_with_fee,
|
||||
&mh->md.melted_coin.fee_melt,
|
||||
&mh->md.rc,
|
||||
&h_denom_pub,
|
||||
&md->melted_coin.coin_priv,
|
||||
&mh->md.melted_coin.coin_priv,
|
||||
&confirm_sig);
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&md->melted_coin.coin_priv.eddsa_priv,
|
||||
&coin_pub.eddsa_pub);
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&mh->md.melted_coin.coin_priv.eddsa_priv,
|
||||
&mh->coin_pub.eddsa_pub);
|
||||
melt_obj = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto ("denom_pub_hash",
|
||||
&h_denom_pub),
|
||||
TALER_JSON_pack_denom_sig ("denom_sig",
|
||||
&md->melted_coin.sig),
|
||||
&mh->md.melted_coin.sig),
|
||||
GNUNET_JSON_pack_data_auto ("confirm_sig",
|
||||
&confirm_sig),
|
||||
TALER_JSON_pack_amount ("value_with_fee",
|
||||
&md->melted_coin.melt_amount_with_fee),
|
||||
&mh->md.melted_coin.melt_amount_with_fee),
|
||||
GNUNET_JSON_pack_data_auto ("rc",
|
||||
&md->rc));
|
||||
&mh->md.rc));
|
||||
{
|
||||
char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2];
|
||||
char *end;
|
||||
|
||||
end = GNUNET_STRINGS_data_to_string (
|
||||
&coin_pub,
|
||||
&mh->coin_pub,
|
||||
sizeof (struct TALER_CoinSpendPublicKeyP),
|
||||
pub_str,
|
||||
sizeof (pub_str));
|
||||
@ -489,29 +526,19 @@ TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
|
||||
pub_str);
|
||||
}
|
||||
|
||||
key_state = TALER_EXCHANGE_get_keys (exchange);
|
||||
dki = TALER_EXCHANGE_get_denomination_key (key_state,
|
||||
&md->melted_coin.pub_key);
|
||||
ctx = TEAH_handle_to_context (mh->exchange);
|
||||
key_state = TALER_EXCHANGE_get_keys (mh->exchange);
|
||||
mh->dki = TALER_EXCHANGE_get_denomination_key (key_state,
|
||||
&mh->md.melted_coin.pub_key);
|
||||
|
||||
/* and now we can at last begin the actual request handling */
|
||||
mh = GNUNET_new (struct TALER_EXCHANGE_MeltHandle);
|
||||
mh->exchange = exchange;
|
||||
mh->coin_pub = coin_pub;
|
||||
mh->dki = *dki;
|
||||
memset (&mh->dki.key,
|
||||
0,
|
||||
sizeof (mh->dki.key)); /* lifetime not warranted, so better
|
||||
not copy the pointers */
|
||||
mh->melt_cb = melt_cb;
|
||||
mh->melt_cb_cls = melt_cb_cls;
|
||||
mh->md = md;
|
||||
mh->url = TEAH_path_to_url (exchange,
|
||||
|
||||
mh->url = TEAH_path_to_url (mh->exchange,
|
||||
arg_str);
|
||||
if (NULL == mh->url)
|
||||
{
|
||||
json_decref (melt_obj);
|
||||
GNUNET_free (mh);
|
||||
return NULL;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
eh = TALER_EXCHANGE_curl_easy_get_ (mh->url);
|
||||
if ( (NULL == eh) ||
|
||||
@ -524,17 +551,156 @@ TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
|
||||
if (NULL != eh)
|
||||
curl_easy_cleanup (eh);
|
||||
json_decref (melt_obj);
|
||||
GNUNET_free (mh->url);
|
||||
GNUNET_free (mh);
|
||||
return NULL;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
json_decref (melt_obj);
|
||||
ctx = TEAH_handle_to_context (exchange);
|
||||
mh->job = GNUNET_CURL_job_add2 (ctx,
|
||||
eh,
|
||||
mh->ctx.headers,
|
||||
&handle_melt_finished,
|
||||
mh);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fail_mh (struct TALER_EXCHANGE_MeltHandle *mh)
|
||||
{
|
||||
// FIXME: do return more than NULLs if
|
||||
// the /csr failed!
|
||||
mh->melt_cb (mh->melt_cb_cls,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
UINT32_MAX,
|
||||
NULL);
|
||||
TALER_EXCHANGE_melt_cancel (mh);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callbacks of this type are used to serve the result of submitting a
|
||||
* CS R request to a exchange.
|
||||
*
|
||||
* @param cls closure with our `struct TALER_EXCHANGE_MeltHandle *`
|
||||
* @param csrr response details
|
||||
*/
|
||||
static void
|
||||
csr_cb (void *cls,
|
||||
const struct TALER_EXCHANGE_CsRResponse *csrr)
|
||||
{
|
||||
struct TALER_EXCHANGE_MeltHandle *mh = cls;
|
||||
unsigned int nks_off = 0;
|
||||
|
||||
for (unsigned int i = 0; i<mh->rd->fresh_pks_len; i++)
|
||||
{
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk =
|
||||
&mh->rd->fresh_pks[i];
|
||||
struct TALER_ExchangeWithdrawValues *wv = &mh->alg_values[i];
|
||||
|
||||
switch (fresh_pk->key.cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_INVALID:
|
||||
GNUNET_break (0);
|
||||
fail_mh (mh);
|
||||
return;
|
||||
case TALER_DENOMINATION_RSA:
|
||||
GNUNET_assert (TALER_DENOMINATION_RSA == wv->cipher);
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
GNUNET_assert (TALER_DENOMINATION_CS == wv->cipher);
|
||||
*wv = csrr->details.success.alg_values[nks_off];
|
||||
nks_off++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
start_melt (mh))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
fail_mh (mh);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct TALER_EXCHANGE_MeltHandle *
|
||||
TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
const struct TALER_EXCHANGE_RefreshData *rd,
|
||||
TALER_EXCHANGE_MeltCallback melt_cb,
|
||||
void *melt_cb_cls)
|
||||
{
|
||||
struct TALER_EXCHANGE_NonceKey nks[GNUNET_NZL (rd->fresh_pks_len)];
|
||||
unsigned int nks_off = 0;
|
||||
struct TALER_EXCHANGE_MeltHandle *mh;
|
||||
|
||||
if (0 == rd->fresh_pks_len)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return NULL;
|
||||
}
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
TEAH_handle_is_ready (exchange));
|
||||
mh = GNUNET_new (struct TALER_EXCHANGE_MeltHandle);
|
||||
mh->exchange = exchange;
|
||||
mh->rd = rd;
|
||||
mh->ps = ps;
|
||||
mh->melt_cb = melt_cb;
|
||||
mh->melt_cb_cls = melt_cb_cls;
|
||||
mh->alg_values = GNUNET_new_array (rd->fresh_pks_len,
|
||||
struct TALER_ExchangeWithdrawValues);
|
||||
mh->bks = GNUNET_new_array (rd->fresh_pks_len,
|
||||
union TALER_DenominationBlindingKeyP);
|
||||
for (unsigned int i = 0; i<rd->fresh_pks_len; i++)
|
||||
{
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk = &rd->fresh_pks[i];
|
||||
struct TALER_ExchangeWithdrawValues *wv = &mh->alg_values[i];
|
||||
|
||||
switch (fresh_pk->key.cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_INVALID:
|
||||
GNUNET_break (0);
|
||||
GNUNET_free (mh->alg_values);
|
||||
GNUNET_free (mh->bks);
|
||||
GNUNET_free (mh);
|
||||
return NULL;
|
||||
case TALER_DENOMINATION_RSA:
|
||||
wv->cipher = TALER_DENOMINATION_RSA;
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
wv->cipher = TALER_DENOMINATION_CS;
|
||||
nks[nks_off].pk = fresh_pk;
|
||||
TALER_cs_refresh_nonce_derive (ps,
|
||||
i,
|
||||
&nks[nks_off].nonce);
|
||||
nks_off++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (0 != nks_off)
|
||||
{
|
||||
mh->csr = TALER_EXCHANGE_csr (exchange,
|
||||
nks_off,
|
||||
nks,
|
||||
&csr_cb,
|
||||
mh);
|
||||
if (NULL == mh->csr)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_EXCHANGE_melt_cancel (mh);
|
||||
return NULL;
|
||||
}
|
||||
return mh;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
start_melt (mh))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_EXCHANGE_melt_cancel (mh);
|
||||
return NULL;
|
||||
}
|
||||
return mh;
|
||||
}
|
||||
|
||||
@ -547,8 +713,14 @@ TALER_EXCHANGE_melt_cancel (struct TALER_EXCHANGE_MeltHandle *mh)
|
||||
GNUNET_CURL_job_cancel (mh->job);
|
||||
mh->job = NULL;
|
||||
}
|
||||
TALER_EXCHANGE_free_melt_data_ (mh->md); /* does not free 'md' itself */
|
||||
GNUNET_free (mh->md);
|
||||
if (NULL != mh->csr)
|
||||
{
|
||||
TALER_EXCHANGE_csr_cancel (mh->csr);
|
||||
mh->csr = NULL;
|
||||
}
|
||||
TALER_EXCHANGE_free_melt_data_ (&mh->md); /* does not free 'md' itself */
|
||||
GNUNET_free (mh->alg_values);
|
||||
GNUNET_free (mh->bks);
|
||||
GNUNET_free (mh->url);
|
||||
TALER_curl_easy_post_finished (&mh->ctx);
|
||||
GNUNET_free (mh);
|
||||
|
@ -284,6 +284,7 @@ struct TALER_EXCHANGE_RecoupHandle *
|
||||
TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange,
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *pk,
|
||||
const struct TALER_DenominationSignature *denom_sig,
|
||||
const struct TALER_ExchangeWithdrawValues *exchange_vals,
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
TALER_EXCHANGE_RecoupResultCallback recoup_cb,
|
||||
void *recoup_cb_cls)
|
||||
@ -296,16 +297,25 @@ TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange,
|
||||
json_t *recoup_obj;
|
||||
CURL *eh;
|
||||
char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32];
|
||||
struct TALER_CoinSpendPrivateKeyP coin_priv;
|
||||
union TALER_DenominationBlindingKeyP bks;
|
||||
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
TEAH_handle_is_ready (exchange));
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&ps->coin_priv.eddsa_priv,
|
||||
|
||||
TALER_planchet_setup_coin_priv (ps,
|
||||
exchange_vals,
|
||||
&coin_priv);
|
||||
TALER_planchet_blinding_secret_create (ps,
|
||||
exchange_vals,
|
||||
&bks);
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv.eddsa_priv,
|
||||
&coin_pub.eddsa_pub);
|
||||
TALER_denom_pub_hash (&pk->key,
|
||||
&h_denom_pub);
|
||||
TALER_wallet_recoup_sign (&h_denom_pub,
|
||||
&ps->blinding_key,
|
||||
&ps->coin_priv,
|
||||
&bks,
|
||||
&coin_priv,
|
||||
&coin_sig);
|
||||
recoup_obj = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto ("denom_pub_hash",
|
||||
@ -315,7 +325,7 @@ TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange,
|
||||
GNUNET_JSON_pack_data_auto ("coin_sig",
|
||||
&coin_sig),
|
||||
GNUNET_JSON_pack_data_auto ("coin_blind_key_secret",
|
||||
&ps->blinding_key));
|
||||
&bks));
|
||||
|
||||
{
|
||||
char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2];
|
||||
|
@ -286,6 +286,7 @@ TALER_EXCHANGE_recoup_refresh (
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *pk,
|
||||
const struct TALER_DenominationSignature *denom_sig,
|
||||
const struct TALER_ExchangeWithdrawValues *exchange_vals,
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
TALER_EXCHANGE_RecoupRefreshResultCallback recoup_cb,
|
||||
void *recoup_cb_cls)
|
||||
@ -298,16 +299,24 @@ TALER_EXCHANGE_recoup_refresh (
|
||||
json_t *recoup_obj;
|
||||
CURL *eh;
|
||||
char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32];
|
||||
struct TALER_CoinSpendPrivateKeyP coin_priv;
|
||||
union TALER_DenominationBlindingKeyP bks;
|
||||
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
TEAH_handle_is_ready (exchange));
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&ps->coin_priv.eddsa_priv,
|
||||
TALER_planchet_setup_coin_priv (ps,
|
||||
exchange_vals,
|
||||
&coin_priv);
|
||||
TALER_planchet_blinding_secret_create (ps,
|
||||
exchange_vals,
|
||||
&bks);
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv.eddsa_priv,
|
||||
&coin_pub.eddsa_pub);
|
||||
TALER_denom_pub_hash (&pk->key,
|
||||
&h_denom_pub);
|
||||
TALER_wallet_recoup_refresh_sign (&h_denom_pub,
|
||||
&ps->blinding_key,
|
||||
&ps->coin_priv,
|
||||
&bks,
|
||||
&coin_priv,
|
||||
&coin_sig);
|
||||
recoup_obj = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto ("denom_pub_hash",
|
||||
@ -317,7 +326,7 @@ TALER_EXCHANGE_recoup_refresh (
|
||||
GNUNET_JSON_pack_data_auto ("coin_sig",
|
||||
&coin_sig),
|
||||
GNUNET_JSON_pack_data_auto ("coin_blind_key_secret",
|
||||
&ps->blinding_key));
|
||||
&bks));
|
||||
|
||||
{
|
||||
char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2];
|
||||
|
@ -23,24 +23,11 @@
|
||||
#include "exchange_api_refresh_common.h"
|
||||
|
||||
|
||||
/**
|
||||
* Free all information associated with a melted coin session.
|
||||
*
|
||||
* @param mc melted coin to release, the pointer itself is NOT
|
||||
* freed (as it is typically not allocated by itself)
|
||||
*/
|
||||
static void
|
||||
free_melted_coin (struct MeltedCoin *mc)
|
||||
{
|
||||
TALER_denom_pub_free (&mc->pub_key);
|
||||
TALER_denom_sig_free (&mc->sig);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_EXCHANGE_free_melt_data_ (struct MeltData *md)
|
||||
{
|
||||
free_melted_coin (&md->melted_coin);
|
||||
TALER_denom_pub_free (&md->melted_coin.pub_key);
|
||||
TALER_denom_sig_free (&md->melted_coin.sig);
|
||||
if (NULL != md->fresh_pks)
|
||||
{
|
||||
for (unsigned int i = 0; i<md->num_fresh_coins; i++)
|
||||
@ -55,412 +42,142 @@ TALER_EXCHANGE_free_melt_data_ (struct MeltData *md)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serialize information about a coin we are melting.
|
||||
*
|
||||
* @param mc information to serialize
|
||||
* @return NULL on error
|
||||
*/
|
||||
static json_t *
|
||||
serialize_melted_coin (const struct MeltedCoin *mc)
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_EXCHANGE_get_melt_data_ (
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
const struct TALER_EXCHANGE_RefreshData *rd,
|
||||
const struct TALER_ExchangeWithdrawValues *alg_values,
|
||||
struct MeltData *md)
|
||||
{
|
||||
json_t *tprivs;
|
||||
|
||||
tprivs = json_array ();
|
||||
GNUNET_assert (NULL != tprivs);
|
||||
for (unsigned int i = 0; i<TALER_CNC_KAPPA; i++)
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (
|
||||
tprivs,
|
||||
GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto (
|
||||
"transfer_priv",
|
||||
&mc->transfer_priv[i]))));
|
||||
return GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto ("coin_priv",
|
||||
&mc->coin_priv),
|
||||
TALER_JSON_pack_denom_sig ("denom_sig",
|
||||
&mc->sig),
|
||||
TALER_JSON_pack_denom_pub ("denom_pub",
|
||||
&mc->pub_key),
|
||||
TALER_JSON_pack_amount ("melt_amount_with_fee",
|
||||
&mc->melt_amount_with_fee),
|
||||
TALER_JSON_pack_amount ("original_value",
|
||||
&mc->original_value),
|
||||
TALER_JSON_pack_amount ("melt_fee",
|
||||
&mc->fee_melt),
|
||||
GNUNET_JSON_pack_timestamp ("expire_deposit",
|
||||
mc->expire_deposit),
|
||||
GNUNET_JSON_pack_array_steal ("transfer_privs",
|
||||
tprivs));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserialize information about a coin we are melting.
|
||||
*
|
||||
* @param[out] mc information to deserialize
|
||||
* @param currency expected currency
|
||||
* @param in JSON object to read data from
|
||||
* @return #GNUNET_NO to report errors
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
deserialize_melted_coin (struct MeltedCoin *mc,
|
||||
const char *currency,
|
||||
const json_t *in)
|
||||
{
|
||||
json_t *trans_privs;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto ("coin_priv",
|
||||
&mc->coin_priv),
|
||||
TALER_JSON_spec_denom_sig ("denom_sig",
|
||||
&mc->sig),
|
||||
TALER_JSON_spec_denom_pub ("denom_pub",
|
||||
&mc->pub_key),
|
||||
TALER_JSON_spec_amount ("melt_amount_with_fee",
|
||||
currency,
|
||||
&mc->melt_amount_with_fee),
|
||||
TALER_JSON_spec_amount ("original_value",
|
||||
currency,
|
||||
&mc->original_value),
|
||||
TALER_JSON_spec_amount ("melt_fee",
|
||||
currency,
|
||||
&mc->fee_melt),
|
||||
GNUNET_JSON_spec_timestamp ("expire_deposit",
|
||||
&mc->expire_deposit),
|
||||
GNUNET_JSON_spec_json ("transfer_privs",
|
||||
&trans_privs),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (in,
|
||||
spec,
|
||||
NULL, NULL))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
if (TALER_CNC_KAPPA != json_array_size (trans_privs))
|
||||
{
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
for (unsigned int i = 0; i<TALER_CNC_KAPPA; i++)
|
||||
{
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto ("transfer_priv",
|
||||
&mc->transfer_priv[i]),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (json_array_get (trans_privs,
|
||||
i),
|
||||
spec,
|
||||
NULL, NULL))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
}
|
||||
json_decref (trans_privs);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serialize melt data.
|
||||
*
|
||||
* @param md data to serialize
|
||||
* @return serialized melt data
|
||||
*/
|
||||
static json_t *
|
||||
serialize_melt_data (const struct MeltData *md)
|
||||
{
|
||||
json_t *fresh_coins;
|
||||
|
||||
fresh_coins = json_array ();
|
||||
GNUNET_assert (NULL != fresh_coins);
|
||||
for (int i = 0; i<md->num_fresh_coins; i++)
|
||||
{
|
||||
json_t *planchet_secrets;
|
||||
|
||||
planchet_secrets = json_array ();
|
||||
GNUNET_assert (NULL != planchet_secrets);
|
||||
for (unsigned int j = 0; j<TALER_CNC_KAPPA; j++)
|
||||
{
|
||||
json_t *ps;
|
||||
|
||||
ps = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto ("ps",
|
||||
&md->fresh_coins[j][i]));
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (planchet_secrets,
|
||||
ps));
|
||||
}
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (
|
||||
fresh_coins,
|
||||
GNUNET_JSON_PACK (
|
||||
TALER_JSON_pack_denom_pub ("denom_pub",
|
||||
&md->fresh_pks[i]),
|
||||
GNUNET_JSON_pack_array_steal ("planchet_secrets",
|
||||
planchet_secrets)))
|
||||
);
|
||||
}
|
||||
return GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_array_steal ("fresh_coins",
|
||||
fresh_coins),
|
||||
GNUNET_JSON_pack_object_steal ("melted_coin",
|
||||
serialize_melted_coin (&md->melted_coin)),
|
||||
GNUNET_JSON_pack_data_auto ("rc",
|
||||
&md->rc));
|
||||
}
|
||||
|
||||
|
||||
struct MeltData *
|
||||
TALER_EXCHANGE_deserialize_melt_data_ (const json_t *melt_data,
|
||||
const char *currency)
|
||||
{
|
||||
struct MeltData *md = GNUNET_new (struct MeltData);
|
||||
json_t *fresh_coins;
|
||||
json_t *melted_coin;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto ("rc",
|
||||
&md->rc),
|
||||
GNUNET_JSON_spec_json ("melted_coin",
|
||||
&melted_coin),
|
||||
GNUNET_JSON_spec_json ("fresh_coins",
|
||||
&fresh_coins),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
bool ok;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (melt_data,
|
||||
spec,
|
||||
NULL, NULL))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
GNUNET_free (md);
|
||||
return NULL;
|
||||
}
|
||||
if (! (json_is_array (fresh_coins) &&
|
||||
json_is_object (melted_coin)) )
|
||||
{
|
||||
GNUNET_break (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return NULL;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
deserialize_melted_coin (&md->melted_coin,
|
||||
currency,
|
||||
melted_coin))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return NULL;
|
||||
}
|
||||
md->num_fresh_coins = json_array_size (fresh_coins);
|
||||
md->fresh_pks = GNUNET_new_array (md->num_fresh_coins,
|
||||
struct TALER_DenominationPublicKey);
|
||||
for (unsigned int i = 0; i<TALER_CNC_KAPPA; i++)
|
||||
md->fresh_coins[i] = GNUNET_new_array (md->num_fresh_coins,
|
||||
struct TALER_PlanchetSecretsP);
|
||||
ok = true;
|
||||
for (unsigned int i = 0; i<md->num_fresh_coins; i++)
|
||||
{
|
||||
const json_t *ji = json_array_get (fresh_coins,
|
||||
i);
|
||||
json_t *planchet_secrets;
|
||||
struct GNUNET_JSON_Specification ispec[] = {
|
||||
GNUNET_JSON_spec_json ("planchet_secrets",
|
||||
&planchet_secrets),
|
||||
TALER_JSON_spec_denom_pub ("denom_pub",
|
||||
&md->fresh_pks[i]),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (ji,
|
||||
ispec,
|
||||
NULL, NULL))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
if ( (! json_is_array (planchet_secrets)) ||
|
||||
(TALER_CNC_KAPPA != json_array_size (planchet_secrets)) )
|
||||
{
|
||||
GNUNET_break (0);
|
||||
ok = false;
|
||||
GNUNET_JSON_parse_free (ispec);
|
||||
break;
|
||||
}
|
||||
for (unsigned int j = 0; j<TALER_CNC_KAPPA; j++)
|
||||
{
|
||||
struct GNUNET_JSON_Specification jspec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto ("ps",
|
||||
&md->fresh_coins[j][i]),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (json_array_get (planchet_secrets,
|
||||
j),
|
||||
jspec,
|
||||
NULL, NULL))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
json_decref (planchet_secrets);
|
||||
if (! ok)
|
||||
break;
|
||||
}
|
||||
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
if (! ok)
|
||||
{
|
||||
TALER_EXCHANGE_free_melt_data_ (md);
|
||||
GNUNET_free (md);
|
||||
return NULL;
|
||||
}
|
||||
return md;
|
||||
}
|
||||
|
||||
|
||||
json_t *
|
||||
TALER_EXCHANGE_refresh_prepare (
|
||||
const struct TALER_CoinSpendPrivateKeyP *melt_priv,
|
||||
const struct TALER_Amount *melt_amount,
|
||||
const struct TALER_DenominationSignature *melt_sig,
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *melt_pk,
|
||||
unsigned int fresh_pks_len,
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks)
|
||||
{
|
||||
struct MeltData md;
|
||||
json_t *ret;
|
||||
struct TALER_Amount total;
|
||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||
struct TALER_TransferSecretP trans_sec[TALER_CNC_KAPPA];
|
||||
struct TALER_RefreshCommitmentEntry rce[TALER_CNC_KAPPA];
|
||||
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&melt_priv->eddsa_priv,
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&rd->melt_priv.eddsa_priv,
|
||||
&coin_pub.eddsa_pub);
|
||||
/* build up melt data structure */
|
||||
memset (&md,
|
||||
memset (md,
|
||||
0,
|
||||
sizeof (md));
|
||||
md.num_fresh_coins = fresh_pks_len;
|
||||
md.melted_coin.coin_priv = *melt_priv;
|
||||
md.melted_coin.melt_amount_with_fee = *melt_amount;
|
||||
md.melted_coin.fee_melt = melt_pk->fee_refresh;
|
||||
md.melted_coin.original_value = melt_pk->value;
|
||||
md.melted_coin.expire_deposit
|
||||
= melt_pk->expire_deposit;
|
||||
sizeof (*md));
|
||||
md->num_fresh_coins = rd->fresh_pks_len;
|
||||
md->melted_coin.coin_priv = rd->melt_priv;
|
||||
md->melted_coin.melt_amount_with_fee = rd->melt_amount;
|
||||
md->melted_coin.fee_melt = rd->melt_pk.fee_refresh;
|
||||
md->melted_coin.original_value = rd->melt_pk.value;
|
||||
md->melted_coin.expire_deposit = rd->melt_pk.expire_deposit;
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_set_zero (melt_amount->currency,
|
||||
TALER_amount_set_zero (rd->melt_amount.currency,
|
||||
&total));
|
||||
TALER_denom_pub_deep_copy (&md.melted_coin.pub_key,
|
||||
&melt_pk->key);
|
||||
TALER_denom_sig_deep_copy (&md.melted_coin.sig,
|
||||
melt_sig);
|
||||
md.fresh_pks = GNUNET_new_array (fresh_pks_len,
|
||||
TALER_denom_pub_deep_copy (&md->melted_coin.pub_key,
|
||||
&rd->melt_pk.key);
|
||||
TALER_denom_sig_deep_copy (&md->melted_coin.sig,
|
||||
&rd->melt_sig);
|
||||
md->fresh_pks = GNUNET_new_array (rd->fresh_pks_len,
|
||||
struct TALER_DenominationPublicKey);
|
||||
for (unsigned int i = 0; i<fresh_pks_len; i++)
|
||||
for (unsigned int i = 0; i<rd->fresh_pks_len; i++)
|
||||
{
|
||||
TALER_denom_pub_deep_copy (&md.fresh_pks[i],
|
||||
&fresh_pks[i].key);
|
||||
TALER_denom_pub_deep_copy (&md->fresh_pks[i],
|
||||
&rd->fresh_pks[i].key);
|
||||
if ( (0 >
|
||||
TALER_amount_add (&total,
|
||||
&total,
|
||||
&fresh_pks[i].value)) ||
|
||||
&rd->fresh_pks[i].value)) ||
|
||||
(0 >
|
||||
TALER_amount_add (&total,
|
||||
&total,
|
||||
&fresh_pks[i].fee_withdraw)) )
|
||||
&rd->fresh_pks[i].fee_withdraw)) )
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_EXCHANGE_free_melt_data_ (&md);
|
||||
return NULL;
|
||||
TALER_EXCHANGE_free_melt_data_ (md);
|
||||
memset (md,
|
||||
0,
|
||||
sizeof (*md));
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
}
|
||||
/* verify that melt_amount is above total cost */
|
||||
if (1 ==
|
||||
TALER_amount_cmp (&total,
|
||||
melt_amount) )
|
||||
&rd->melt_amount) )
|
||||
{
|
||||
/* Eh, this operation is more expensive than the
|
||||
@a melt_amount. This is not OK. */
|
||||
GNUNET_break (0);
|
||||
TALER_EXCHANGE_free_melt_data_ (&md);
|
||||
return NULL;
|
||||
TALER_EXCHANGE_free_melt_data_ (md);
|
||||
memset (md,
|
||||
0,
|
||||
sizeof (*md));
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
/* build up coins */
|
||||
for (unsigned int i = 0; i<TALER_CNC_KAPPA; i++)
|
||||
{
|
||||
GNUNET_CRYPTO_ecdhe_key_create (
|
||||
&md.melted_coin.transfer_priv[i].ecdhe_priv);
|
||||
TALER_planchet_secret_to_transfer_priv (
|
||||
ps,
|
||||
i,
|
||||
&md->melted_coin.transfer_priv[i]);
|
||||
GNUNET_CRYPTO_ecdhe_key_get_public (
|
||||
&md.melted_coin.transfer_priv[i].ecdhe_priv,
|
||||
&md->melted_coin.transfer_priv[i].ecdhe_priv,
|
||||
&rce[i].transfer_pub.ecdhe_pub);
|
||||
TALER_link_derive_transfer_secret (melt_priv,
|
||||
&md.melted_coin.transfer_priv[i],
|
||||
TALER_link_derive_transfer_secret (&rd->melt_priv,
|
||||
&md->melted_coin.transfer_priv[i],
|
||||
&trans_sec[i]);
|
||||
md.fresh_coins[i] = GNUNET_new_array (fresh_pks_len,
|
||||
md->fresh_coins[i] = GNUNET_new_array (rd->fresh_pks_len,
|
||||
struct TALER_PlanchetSecretsP);
|
||||
rce[i].new_coins = GNUNET_new_array (fresh_pks_len,
|
||||
rce[i].new_coins = GNUNET_new_array (rd->fresh_pks_len,
|
||||
struct TALER_RefreshCoinData);
|
||||
for (unsigned int j = 0; j<fresh_pks_len; j++)
|
||||
for (unsigned int j = 0; j<rd->fresh_pks_len; j++)
|
||||
{
|
||||
struct TALER_PlanchetSecretsP *fc = &md.fresh_coins[i][j];
|
||||
struct TALER_PlanchetSecretsP *fc = &md->fresh_coins[i][j];
|
||||
struct TALER_RefreshCoinData *rcd = &rce[i].new_coins[j];
|
||||
struct TALER_PlanchetDetail pd;
|
||||
struct TALER_CoinPubHash c_hash;
|
||||
struct TALER_CoinSpendPrivateKeyP coin_priv;
|
||||
union TALER_DenominationBlindingKeyP bks;
|
||||
|
||||
TALER_planchet_setup_refresh (&trans_sec[i],
|
||||
TALER_transfer_secret_to_planchet_secret (&trans_sec[i],
|
||||
j,
|
||||
fc);
|
||||
TALER_planchet_setup_coin_priv (fc,
|
||||
&alg_values[j],
|
||||
&coin_priv);
|
||||
TALER_planchet_blinding_secret_create (fc,
|
||||
&alg_values[j],
|
||||
&bks);
|
||||
if (GNUNET_OK !=
|
||||
TALER_planchet_prepare (&md.fresh_pks[j],
|
||||
fc,
|
||||
TALER_planchet_prepare (&md->fresh_pks[j],
|
||||
&alg_values[j],
|
||||
&bks,
|
||||
&coin_priv,
|
||||
&c_hash,
|
||||
&pd))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
TALER_EXCHANGE_free_melt_data_ (&md);
|
||||
return NULL;
|
||||
TALER_EXCHANGE_free_melt_data_ (md);
|
||||
memset (md,
|
||||
0,
|
||||
sizeof (*md));
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
rcd->dk = &md.fresh_pks[j];
|
||||
rcd->coin_ev = pd.coin_ev;
|
||||
rcd->coin_ev_size = pd.coin_ev_size;
|
||||
rcd->dk = &md->fresh_pks[j];
|
||||
rcd->blinded_planchet = pd.blinded_planchet;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute refresh commitment */
|
||||
TALER_refresh_get_commitment (&md.rc,
|
||||
TALER_refresh_get_commitment (&md->rc,
|
||||
TALER_CNC_KAPPA,
|
||||
fresh_pks_len,
|
||||
rd->fresh_pks_len,
|
||||
rce,
|
||||
&coin_pub,
|
||||
melt_amount);
|
||||
/* finally, serialize everything */
|
||||
ret = serialize_melt_data (&md);
|
||||
&rd->melt_amount);
|
||||
for (unsigned int i = 0; i < TALER_CNC_KAPPA; i++)
|
||||
{
|
||||
for (unsigned int j = 0; j < fresh_pks_len; j++)
|
||||
GNUNET_free (rce[i].new_coins[j].coin_ev);
|
||||
for (unsigned int j = 0; j < rd->fresh_pks_len; j++)
|
||||
TALER_blinded_planchet_free (&rce[i].new_coins[j].blinded_planchet);
|
||||
GNUNET_free (rce[i].new_coins);
|
||||
}
|
||||
TALER_EXCHANGE_free_melt_data_ (&md);
|
||||
return ret;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2015-2020 Taler Systems SA
|
||||
Copyright (C) 2015-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -102,6 +102,12 @@ struct MeltData
|
||||
*/
|
||||
struct TALER_DenominationPublicKey *fresh_pks;
|
||||
|
||||
/**
|
||||
* Array of @e num_fresh_coins with exchange contributions
|
||||
* made during the refresh.
|
||||
*/
|
||||
struct TALER_ExchangeWithdrawValues *exchange_vals;
|
||||
|
||||
/**
|
||||
* Arrays of @e num_fresh_coins with information about the fresh
|
||||
* coins to be created, for each cut-and-choose dimension.
|
||||
@ -111,15 +117,19 @@ struct MeltData
|
||||
|
||||
|
||||
/**
|
||||
* Deserialize melt data.
|
||||
* Compute the melt data from the refresh data and secret.
|
||||
*
|
||||
* @param data json data to deserialize
|
||||
* @param currency expected currency for the coins
|
||||
* @return deserialized melt data, NULL on error
|
||||
* @param ps secret internals of the refresh-reveal operation
|
||||
* @param rd refresh data with the characteristics of the operation
|
||||
* @param alg_values contributions from the exchange into the melt
|
||||
* @param[out] rd where to write the derived melt data
|
||||
*/
|
||||
struct MeltData *
|
||||
TALER_EXCHANGE_deserialize_melt_data_ (const json_t *data,
|
||||
const char *currency);
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_EXCHANGE_get_melt_data_ (
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
const struct TALER_EXCHANGE_RefreshData *rd,
|
||||
const struct TALER_ExchangeWithdrawValues *alg_values,
|
||||
struct MeltData *md);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2015-2021 Taler Systems SA
|
||||
Copyright (C) 2015-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -73,7 +73,7 @@ struct TALER_EXCHANGE_RefreshesRevealHandle
|
||||
/**
|
||||
* Actual information about the melt operation.
|
||||
*/
|
||||
struct MeltData *md;
|
||||
struct MeltData md;
|
||||
|
||||
/**
|
||||
* The index selected by the exchange in cut-and-choose to not be revealed.
|
||||
@ -95,12 +95,14 @@ struct TALER_EXCHANGE_RefreshesRevealHandle
|
||||
*
|
||||
* @param rrh operation handle
|
||||
* @param json reply from the exchange
|
||||
* @param[out] sigs array of length `num_fresh_coins`, initialized to contain RSA signatures
|
||||
* @param[out] sigs array of length `num_fresh_coins`, initialized to contain the coin private keys
|
||||
* @param[out] sigs array of length `num_fresh_coins`, initialized to contain signatures
|
||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
|
||||
const json_t *json,
|
||||
struct TALER_CoinSpendPrivateKeyP *coin_privs,
|
||||
struct TALER_DenominationSignature *sigs)
|
||||
{
|
||||
json_t *jsona;
|
||||
@ -125,19 +127,20 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
|
||||
GNUNET_JSON_parse_free (outer_spec);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (rrh->md->num_fresh_coins != json_array_size (jsona))
|
||||
if (rrh->md.num_fresh_coins != json_array_size (jsona))
|
||||
{
|
||||
/* Number of coins generated does not match our expectation */
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_JSON_parse_free (outer_spec);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
for (unsigned int i = 0; i<rrh->md->num_fresh_coins; i++)
|
||||
for (unsigned int i = 0; i<rrh->md.num_fresh_coins; i++)
|
||||
{
|
||||
const struct TALER_PlanchetSecretsP *fc;
|
||||
struct TALER_DenominationPublicKey *pk;
|
||||
json_t *jsonai;
|
||||
struct TALER_BlindedDenominationSignature blind_sig;
|
||||
struct TALER_ExchangeWithdrawValues alg_values;
|
||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||
struct TALER_CoinPubHash coin_hash;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
@ -146,9 +149,10 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
struct TALER_FreshCoin coin;
|
||||
union TALER_DenominationBlindingKeyP bks;
|
||||
|
||||
fc = &rrh->md->fresh_coins[rrh->noreveal_index][i];
|
||||
pk = &rrh->md->fresh_pks[i];
|
||||
fc = &rrh->md.fresh_coins[rrh->noreveal_index][i];
|
||||
pk = &rrh->md.fresh_pks[i];
|
||||
jsonai = json_array_get (jsona, i);
|
||||
GNUNET_assert (NULL != jsonai);
|
||||
|
||||
@ -162,9 +166,17 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
// TODO: implement cipher handling
|
||||
alg_values.cipher = TALER_DENOMINATION_RSA;
|
||||
TALER_planchet_setup_coin_priv (fc,
|
||||
&alg_values,
|
||||
&coin_privs[i]);
|
||||
TALER_planchet_blinding_secret_create (fc,
|
||||
&alg_values,
|
||||
&bks);
|
||||
/* needed to verify the signature, and we didn't store it earlier,
|
||||
hence recomputing it here... */
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&fc->coin_priv.eddsa_priv,
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&coin_privs[i].eddsa_priv,
|
||||
&coin_pub.eddsa_pub);
|
||||
/* FIXME-Oec: Age commitment hash. */
|
||||
TALER_coin_pub_hash (&coin_pub,
|
||||
@ -173,8 +185,10 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
|
||||
if (GNUNET_OK !=
|
||||
TALER_planchet_to_coin (pk,
|
||||
&blind_sig,
|
||||
fc,
|
||||
&bks,
|
||||
&coin_privs[i],
|
||||
&coin_hash,
|
||||
&alg_values,
|
||||
&coin))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
@ -218,14 +232,16 @@ handle_refresh_reveal_finished (void *cls,
|
||||
break;
|
||||
case MHD_HTTP_OK:
|
||||
{
|
||||
struct TALER_DenominationSignature sigs[rrh->md->num_fresh_coins];
|
||||
int ret;
|
||||
struct TALER_DenominationSignature sigs[rrh->md.num_fresh_coins];
|
||||
struct TALER_CoinSpendPrivateKeyP coin_privs[rrh->md.num_fresh_coins];
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
|
||||
memset (sigs,
|
||||
0,
|
||||
sizeof (sigs));
|
||||
ret = refresh_reveal_ok (rrh,
|
||||
j,
|
||||
coin_privs,
|
||||
sigs);
|
||||
if (GNUNET_OK != ret)
|
||||
{
|
||||
@ -236,12 +252,12 @@ handle_refresh_reveal_finished (void *cls,
|
||||
{
|
||||
rrh->reveal_cb (rrh->reveal_cb_cls,
|
||||
&hr,
|
||||
rrh->md->num_fresh_coins,
|
||||
rrh->md->fresh_coins[rrh->noreveal_index],
|
||||
rrh->md.num_fresh_coins,
|
||||
coin_privs,
|
||||
sigs);
|
||||
rrh->reveal_cb = NULL;
|
||||
}
|
||||
for (unsigned int i = 0; i<rrh->md->num_fresh_coins; i++)
|
||||
for (unsigned int i = 0; i<rrh->md.num_fresh_coins; i++)
|
||||
TALER_denom_sig_free (&sigs[i]);
|
||||
TALER_EXCHANGE_refreshes_reveal_cancel (rrh);
|
||||
return;
|
||||
@ -294,7 +310,10 @@ handle_refresh_reveal_finished (void *cls,
|
||||
struct TALER_EXCHANGE_RefreshesRevealHandle *
|
||||
TALER_EXCHANGE_refreshes_reveal (
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
const json_t *refresh_data,
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
const struct TALER_EXCHANGE_RefreshData *rd,
|
||||
unsigned int num_coins,
|
||||
const struct TALER_ExchangeWithdrawValues *alg_values,
|
||||
uint32_t noreveal_index,
|
||||
TALER_EXCHANGE_RefreshesRevealCallback reveal_cb,
|
||||
void *reveal_cb_cls)
|
||||
@ -307,10 +326,12 @@ TALER_EXCHANGE_refreshes_reveal (
|
||||
json_t *link_sigs;
|
||||
CURL *eh;
|
||||
struct GNUNET_CURL_Context *ctx;
|
||||
struct MeltData *md;
|
||||
struct MeltData md;
|
||||
struct TALER_TransferPublicKeyP transfer_pub;
|
||||
char arg_str[sizeof (struct TALER_RefreshCommitmentP) * 2 + 32];
|
||||
struct TALER_TransferSecretP ts;
|
||||
|
||||
GNUNET_assert (num_coins == rd->fresh_pks_len);
|
||||
if (noreveal_index >= TALER_CNC_KAPPA)
|
||||
{
|
||||
/* We check this here, as it would be really bad to below just
|
||||
@ -326,9 +347,11 @@ TALER_EXCHANGE_refreshes_reveal (
|
||||
GNUNET_break (0);
|
||||
return NULL;
|
||||
}
|
||||
md = TALER_EXCHANGE_deserialize_melt_data_ (refresh_data,
|
||||
exchange->key_data.currency);
|
||||
if (NULL == md)
|
||||
if (GNUNET_OK !=
|
||||
TALER_EXCHANGE_get_melt_data_ (ps,
|
||||
rd,
|
||||
alg_values,
|
||||
&md))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return NULL;
|
||||
@ -336,29 +359,45 @@ TALER_EXCHANGE_refreshes_reveal (
|
||||
|
||||
/* now transfer_pub */
|
||||
GNUNET_CRYPTO_ecdhe_key_get_public (
|
||||
&md->melted_coin.transfer_priv[noreveal_index].ecdhe_priv,
|
||||
&md.melted_coin.transfer_priv[noreveal_index].ecdhe_priv,
|
||||
&transfer_pub.ecdhe_pub);
|
||||
TALER_link_recover_transfer_secret (&transfer_pub,
|
||||
&rd->melt_priv,
|
||||
&ts);
|
||||
|
||||
/* now new_denoms */
|
||||
GNUNET_assert (NULL != (new_denoms_h = json_array ()));
|
||||
GNUNET_assert (NULL != (coin_evs = json_array ()));
|
||||
GNUNET_assert (NULL != (link_sigs = json_array ()));
|
||||
for (unsigned int i = 0; i<md->num_fresh_coins; i++)
|
||||
for (unsigned int i = 0; i<md.num_fresh_coins; i++)
|
||||
{
|
||||
struct TALER_DenominationHash denom_hash;
|
||||
struct TALER_PlanchetDetail pd;
|
||||
struct TALER_CoinPubHash c_hash;
|
||||
struct TALER_PlanchetSecretsP ps;
|
||||
union TALER_DenominationBlindingKeyP bks;
|
||||
struct TALER_CoinSpendPrivateKeyP coin_priv;
|
||||
|
||||
TALER_denom_pub_hash (&md->fresh_pks[i],
|
||||
TALER_denom_pub_hash (&md.fresh_pks[i],
|
||||
&denom_hash);
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (new_denoms_h,
|
||||
GNUNET_JSON_from_data_auto (
|
||||
&denom_hash)));
|
||||
|
||||
TALER_transfer_secret_to_planchet_secret (&ts,
|
||||
i,
|
||||
&ps);
|
||||
TALER_planchet_setup_coin_priv (&ps,
|
||||
&alg_values[i],
|
||||
&coin_priv);
|
||||
TALER_planchet_blinding_secret_create (&ps,
|
||||
&alg_values[i],
|
||||
&bks);
|
||||
if (GNUNET_OK !=
|
||||
TALER_planchet_prepare (&md->fresh_pks[i],
|
||||
&md->fresh_coins[noreveal_index][i],
|
||||
TALER_planchet_prepare (&md.fresh_pks[i],
|
||||
&alg_values[i],
|
||||
&bks,
|
||||
&coin_priv,
|
||||
&c_hash,
|
||||
&pd))
|
||||
{
|
||||
@ -366,27 +405,36 @@ TALER_EXCHANGE_refreshes_reveal (
|
||||
GNUNET_break (0);
|
||||
json_decref (new_denoms_h);
|
||||
json_decref (coin_evs);
|
||||
TALER_EXCHANGE_free_melt_data_ (&md);
|
||||
return NULL;
|
||||
}
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (coin_evs,
|
||||
GNUNET_JSON_from_data (pd.coin_ev,
|
||||
pd.coin_ev_size)));
|
||||
GNUNET_assert (
|
||||
0 ==
|
||||
json_array_append_new (
|
||||
coin_evs,
|
||||
GNUNET_JSON_PACK (
|
||||
TALER_JSON_pack_blinded_planchet (
|
||||
NULL,
|
||||
&pd.blinded_planchet))));
|
||||
{
|
||||
struct TALER_CoinSpendSignatureP link_sig;
|
||||
struct TALER_BlindedCoinHash bch;
|
||||
|
||||
TALER_wallet_link_sign (&denom_hash,
|
||||
TALER_coin_ev_hash (&pd.blinded_planchet,
|
||||
&denom_hash,
|
||||
&bch);
|
||||
TALER_wallet_link_sign (
|
||||
&denom_hash,
|
||||
&transfer_pub,
|
||||
pd.coin_ev,
|
||||
pd.coin_ev_size,
|
||||
&md->melted_coin.coin_priv,
|
||||
&bch,
|
||||
&md.melted_coin.coin_priv,
|
||||
&link_sig);
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (
|
||||
link_sigs,
|
||||
GNUNET_JSON_from_data_auto (&link_sig)));
|
||||
}
|
||||
GNUNET_free (pd.coin_ev);
|
||||
TALER_blinded_planchet_free (&pd.blinded_planchet);
|
||||
}
|
||||
|
||||
/* build array of transfer private keys */
|
||||
@ -402,7 +450,7 @@ TALER_EXCHANGE_refreshes_reveal (
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (transfer_privs,
|
||||
GNUNET_JSON_from_data_auto (
|
||||
&md->melted_coin.transfer_priv[j])));
|
||||
&md.melted_coin.transfer_priv[j])));
|
||||
}
|
||||
|
||||
/* build main JSON request */
|
||||
@ -421,9 +469,8 @@ TALER_EXCHANGE_refreshes_reveal (
|
||||
char pub_str[sizeof (struct TALER_RefreshCommitmentP) * 2];
|
||||
char *end;
|
||||
|
||||
end = GNUNET_STRINGS_data_to_string (&md->rc,
|
||||
sizeof (struct
|
||||
TALER_RefreshCommitmentP),
|
||||
end = GNUNET_STRINGS_data_to_string (&md.rc,
|
||||
sizeof (md.rc),
|
||||
pub_str,
|
||||
sizeof (pub_str));
|
||||
*end = '\0';
|
||||
@ -444,6 +491,7 @@ TALER_EXCHANGE_refreshes_reveal (
|
||||
if (NULL == rrh->url)
|
||||
{
|
||||
json_decref (reveal_obj);
|
||||
TALER_EXCHANGE_free_melt_data_ (&md);
|
||||
GNUNET_free (rrh);
|
||||
return NULL;
|
||||
}
|
||||
@ -458,6 +506,7 @@ TALER_EXCHANGE_refreshes_reveal (
|
||||
if (NULL != eh)
|
||||
curl_easy_cleanup (eh);
|
||||
json_decref (reveal_obj);
|
||||
TALER_EXCHANGE_free_melt_data_ (&md);
|
||||
GNUNET_free (rrh->url);
|
||||
GNUNET_free (rrh);
|
||||
return NULL;
|
||||
@ -484,8 +533,7 @@ TALER_EXCHANGE_refreshes_reveal_cancel (
|
||||
}
|
||||
GNUNET_free (rrh->url);
|
||||
TALER_curl_easy_post_finished (&rrh->ctx);
|
||||
TALER_EXCHANGE_free_melt_data_ (rrh->md); /* does not free 'md' itself */
|
||||
GNUNET_free (rrh->md);
|
||||
TALER_EXCHANGE_free_melt_data_ (&rrh->md);
|
||||
GNUNET_free (rrh);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2021 Taler Systems SA
|
||||
Copyright (C) 2014-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -59,10 +59,35 @@ struct TALER_EXCHANGE_WithdrawHandle
|
||||
void *cb_cls;
|
||||
|
||||
/**
|
||||
* Secrets of the planchet.
|
||||
* Reserve private key.
|
||||
*/
|
||||
const struct TALER_ReservePrivateKeyP *reserve_priv;
|
||||
|
||||
/**
|
||||
* Seed of the planchet.
|
||||
*/
|
||||
struct TALER_PlanchetSecretsP ps;
|
||||
|
||||
/**
|
||||
* blinding secret
|
||||
*/
|
||||
union TALER_DenominationBlindingKeyP bks;
|
||||
|
||||
/**
|
||||
* Private key of the coin we are withdrawing.
|
||||
*/
|
||||
struct TALER_CoinSpendPrivateKeyP priv;
|
||||
|
||||
/**
|
||||
* Details of the planchet.
|
||||
*/
|
||||
struct TALER_PlanchetDetail pd;
|
||||
|
||||
/**
|
||||
* Values of the @cipher selected
|
||||
*/
|
||||
struct TALER_ExchangeWithdrawValues alg_values;
|
||||
|
||||
/**
|
||||
* Denomination key we are withdrawing.
|
||||
*/
|
||||
@ -73,6 +98,11 @@ struct TALER_EXCHANGE_WithdrawHandle
|
||||
*/
|
||||
struct TALER_CoinPubHash c_hash;
|
||||
|
||||
/**
|
||||
* Handler for the CS R request (only used for TALER_DENOMINATION_CS denominations)
|
||||
*/
|
||||
struct TALER_EXCHANGE_CsRHandle *csrh;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -105,15 +135,20 @@ handle_reserve_withdraw_finished (
|
||||
if (GNUNET_OK !=
|
||||
TALER_planchet_to_coin (&wh->pk.key,
|
||||
blind_sig,
|
||||
&wh->ps,
|
||||
&wh->bks,
|
||||
&wh->priv,
|
||||
&wh->c_hash,
|
||||
&wh->alg_values,
|
||||
&fc))
|
||||
{
|
||||
wr.hr.http_status = 0;
|
||||
wr.hr.ec = TALER_EC_EXCHANGE_WITHDRAW_UNBLIND_FAILURE;
|
||||
break;
|
||||
}
|
||||
wr.details.success.coin_priv = wh->priv;
|
||||
wr.details.success.bks = wh->bks;
|
||||
wr.details.success.sig = fc.sig;
|
||||
wr.details.success.exchange_vals = wh->alg_values;
|
||||
break;
|
||||
}
|
||||
case MHD_HTTP_ACCEPTED:
|
||||
@ -148,23 +183,63 @@ handle_reserve_withdraw_finished (
|
||||
|
||||
|
||||
/**
|
||||
* Withdraw a coin from the exchange using a /reserve/withdraw request. Note
|
||||
* that to ensure that no money is lost in case of hardware failures,
|
||||
* the caller must have committed (most of) the arguments to disk
|
||||
* before calling, and be ready to repeat the request with the same
|
||||
* arguments in case of failures.
|
||||
* Function called when stage 1 of CS withdraw is finished (request r_pub's)
|
||||
*
|
||||
* @param exchange the exchange handle; the exchange must be ready to operate
|
||||
* @param pk kind of coin to create
|
||||
* @param reserve_priv private key of the reserve to withdraw from
|
||||
* @param ps secrets of the planchet
|
||||
* caller must have committed this value to disk before the call (with @a pk)
|
||||
* @param res_cb the callback to call when the final result for this request is available
|
||||
* @param res_cb_cls closure for the above callback
|
||||
* @return handle for the operation on success, NULL on error, i.e.
|
||||
* if the inputs are invalid (i.e. denomination key not with this exchange).
|
||||
* In this case, the callback is not called.
|
||||
* @param cls
|
||||
*/
|
||||
static void
|
||||
withdraw_cs_stage_two_callback (void *cls,
|
||||
const struct TALER_EXCHANGE_CsRResponse *csrr)
|
||||
{
|
||||
struct TALER_EXCHANGE_WithdrawHandle *wh = cls;
|
||||
struct TALER_EXCHANGE_WithdrawResponse wr = {
|
||||
.hr = csrr->hr
|
||||
};
|
||||
|
||||
wh->csrh = NULL;
|
||||
GNUNET_assert (TALER_DENOMINATION_CS == wh->pk.key.cipher);
|
||||
switch (csrr->hr.http_status)
|
||||
{
|
||||
case MHD_HTTP_OK:
|
||||
if (1 != csrr->details.success.alg_values_len)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
wr.hr.http_status = 0;
|
||||
break;
|
||||
}
|
||||
wh->alg_values = csrr->details.success.alg_values[0];
|
||||
TALER_planchet_setup_coin_priv (&wh->ps,
|
||||
&wh->alg_values,
|
||||
&wh->priv);
|
||||
TALER_planchet_blinding_secret_create (&wh->ps,
|
||||
&wh->alg_values,
|
||||
&wh->bks);
|
||||
if (GNUNET_OK !=
|
||||
TALER_planchet_prepare (&wh->pk.key,
|
||||
&wh->alg_values,
|
||||
&wh->bks,
|
||||
&wh->priv,
|
||||
&wh->c_hash,
|
||||
&wh->pd))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
GNUNET_free (wh);
|
||||
}
|
||||
wh->wh2 = TALER_EXCHANGE_withdraw2 (wh->exchange,
|
||||
&wh->pd,
|
||||
wh->reserve_priv,
|
||||
&handle_reserve_withdraw_finished,
|
||||
wh);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
wh->cb (wh->cb_cls,
|
||||
&wr);
|
||||
TALER_EXCHANGE_withdraw_cancel (wh);
|
||||
}
|
||||
|
||||
|
||||
struct TALER_EXCHANGE_WithdrawHandle *
|
||||
TALER_EXCHANGE_withdraw (
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
@ -174,33 +249,70 @@ TALER_EXCHANGE_withdraw (
|
||||
TALER_EXCHANGE_WithdrawCallback res_cb,
|
||||
void *res_cb_cls)
|
||||
{
|
||||
struct TALER_PlanchetDetail pd;
|
||||
struct TALER_EXCHANGE_WithdrawHandle *wh;
|
||||
|
||||
wh = GNUNET_new (struct TALER_EXCHANGE_WithdrawHandle);
|
||||
wh->exchange = exchange;
|
||||
wh->cb = res_cb;
|
||||
wh->cb_cls = res_cb_cls;
|
||||
wh->pk = *pk;
|
||||
wh->reserve_priv = reserve_priv;
|
||||
wh->ps = *ps;
|
||||
wh->pk = *pk;
|
||||
TALER_denom_pub_deep_copy (&wh->pk.key,
|
||||
&pk->key);
|
||||
|
||||
switch (pk->key.cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
{
|
||||
wh->alg_values.cipher = TALER_DENOMINATION_RSA;
|
||||
TALER_planchet_setup_coin_priv (ps,
|
||||
&wh->alg_values,
|
||||
&wh->priv);
|
||||
TALER_planchet_blinding_secret_create (ps,
|
||||
&wh->alg_values,
|
||||
&wh->bks);
|
||||
if (GNUNET_OK !=
|
||||
TALER_planchet_prepare (&pk->key,
|
||||
ps,
|
||||
&wh->alg_values,
|
||||
&wh->bks,
|
||||
&wh->priv,
|
||||
&wh->c_hash,
|
||||
&pd))
|
||||
&wh->pd))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
GNUNET_free (wh);
|
||||
return NULL;
|
||||
}
|
||||
TALER_denom_pub_deep_copy (&wh->pk.key,
|
||||
&pk->key);
|
||||
wh->wh2 = TALER_EXCHANGE_withdraw2 (exchange,
|
||||
&pd,
|
||||
reserve_priv,
|
||||
&wh->pd,
|
||||
wh->reserve_priv,
|
||||
&handle_reserve_withdraw_finished,
|
||||
wh);
|
||||
GNUNET_free (pd.coin_ev);
|
||||
break;
|
||||
}
|
||||
case TALER_DENOMINATION_CS:
|
||||
{
|
||||
struct TALER_EXCHANGE_NonceKey nk = {
|
||||
.pk = pk,
|
||||
};
|
||||
|
||||
wh->pd.blinded_planchet.cipher = TALER_DENOMINATION_CS;
|
||||
TALER_cs_withdraw_nonce_derive (ps,
|
||||
&nk.nonce);
|
||||
wh->csrh = TALER_EXCHANGE_csr (exchange,
|
||||
1, /* "array" length */
|
||||
&nk,
|
||||
&withdraw_cs_stage_two_callback,
|
||||
wh);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
GNUNET_free (wh);
|
||||
return NULL;
|
||||
}
|
||||
TALER_blinded_planchet_free (&wh->pd.blinded_planchet);
|
||||
return wh;
|
||||
}
|
||||
|
||||
@ -208,6 +320,11 @@ TALER_EXCHANGE_withdraw (
|
||||
void
|
||||
TALER_EXCHANGE_withdraw_cancel (struct TALER_EXCHANGE_WithdrawHandle *wh)
|
||||
{
|
||||
if (NULL != wh->csrh)
|
||||
{
|
||||
TALER_EXCHANGE_csr_cancel (wh->csrh);
|
||||
wh->csrh = NULL;
|
||||
}
|
||||
if (NULL != wh->wh2)
|
||||
{
|
||||
TALER_EXCHANGE_withdraw2_cancel (wh->wh2);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2021 Taler Systems SA
|
||||
Copyright (C) 2014-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -152,7 +152,8 @@ reserve_withdraw_payment_required (
|
||||
json_t *history;
|
||||
size_t len;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
TALER_JSON_spec_amount_any ("balance", &balance),
|
||||
TALER_JSON_spec_amount_any ("balance",
|
||||
&balance),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
@ -182,8 +183,8 @@ reserve_withdraw_payment_required (
|
||||
not fit on the stack. Use "GNUNET_malloc_large" as a malicious
|
||||
exchange may theoretically try to crash us by giving a history
|
||||
that does not fit into our memory. */
|
||||
rhistory = GNUNET_malloc_large (sizeof (struct
|
||||
TALER_EXCHANGE_ReserveHistory)
|
||||
rhistory = GNUNET_malloc_large (
|
||||
sizeof (struct TALER_EXCHANGE_ReserveHistory)
|
||||
* len);
|
||||
if (NULL == rhistory)
|
||||
{
|
||||
@ -437,23 +438,25 @@ TALER_EXCHANGE_withdraw2 (
|
||||
|
||||
TALER_amount_hton (&req.amount_with_fee,
|
||||
&wh->requested_amount);
|
||||
TALER_coin_ev_hash (pd->coin_ev,
|
||||
pd->coin_ev_size,
|
||||
&req.h_coin_envelope);
|
||||
if (GNUNET_OK != TALER_coin_ev_hash (&pd->blinded_planchet,
|
||||
&pd->denom_pub_hash,
|
||||
&req.h_coin_envelope))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
GNUNET_free (wh);
|
||||
return NULL;
|
||||
}
|
||||
GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv,
|
||||
&req,
|
||||
&reserve_sig.eddsa_signature);
|
||||
}
|
||||
|
||||
{
|
||||
json_t *withdraw_obj;
|
||||
|
||||
withdraw_obj = GNUNET_JSON_PACK (
|
||||
json_t *withdraw_obj = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto ("denom_pub_hash",
|
||||
&pd->denom_pub_hash),
|
||||
GNUNET_JSON_pack_data_varsize ("coin_ev",
|
||||
pd->coin_ev,
|
||||
pd->coin_ev_size),
|
||||
TALER_JSON_pack_blinded_planchet ("coin_ev",
|
||||
&pd->blinded_planchet),
|
||||
GNUNET_JSON_pack_data_auto ("reserve_sig",
|
||||
&reserve_sig));
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014, 2015, 2016, 2021 Taler Systems SA
|
||||
Copyright (C) 2014, 2015, 2016, 2021, 2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -194,7 +194,9 @@ qconv_denom_pub (void *cls,
|
||||
denom_pub->details.rsa_public_key,
|
||||
&tbuf);
|
||||
break;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
tlen = sizeof (denom_pub->details.cs_public_key);
|
||||
break;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -211,7 +213,11 @@ qconv_denom_pub (void *cls,
|
||||
tlen);
|
||||
GNUNET_free (tbuf);
|
||||
break;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
memcpy (&buf[sizeof (be)],
|
||||
&denom_pub->details.cs_public_key,
|
||||
tlen);
|
||||
break;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -284,7 +290,9 @@ qconv_denom_sig (void *cls,
|
||||
denom_sig->details.rsa_signature,
|
||||
&tbuf);
|
||||
break;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
tlen = sizeof (denom_sig->details.cs_signature);
|
||||
break;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -301,7 +309,11 @@ qconv_denom_sig (void *cls,
|
||||
tlen);
|
||||
GNUNET_free (tbuf);
|
||||
break;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
memcpy (&buf[sizeof (be)],
|
||||
&denom_sig->details.cs_signature,
|
||||
tlen);
|
||||
break;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -374,7 +386,9 @@ qconv_blinded_denom_sig (void *cls,
|
||||
denom_sig->details.blinded_rsa_signature,
|
||||
&tbuf);
|
||||
break;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
tlen = sizeof (denom_sig->details.blinded_cs_answer);
|
||||
break;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -391,7 +405,11 @@ qconv_blinded_denom_sig (void *cls,
|
||||
tlen);
|
||||
GNUNET_free (tbuf);
|
||||
break;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
memcpy (&buf[sizeof (be)],
|
||||
&denom_sig->details.blinded_cs_answer,
|
||||
tlen);
|
||||
break;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -418,6 +436,97 @@ TALER_PQ_query_param_blinded_denom_sig (
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called to convert input argument into SQL parameters.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param data pointer to input argument
|
||||
* @param data_len number of bytes in @a data (if applicable)
|
||||
* @param[out] param_values SQL data to set
|
||||
* @param[out] param_lengths SQL length data to set
|
||||
* @param[out] param_formats SQL format data to set
|
||||
* @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
|
||||
* @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
|
||||
* @param scratch_length number of entries left in @a scratch
|
||||
* @return -1 on error, number of offsets used in @a scratch otherwise
|
||||
*/
|
||||
static int
|
||||
qconv_blinded_planchet (void *cls,
|
||||
const void *data,
|
||||
size_t data_len,
|
||||
void *param_values[],
|
||||
int param_lengths[],
|
||||
int param_formats[],
|
||||
unsigned int param_length,
|
||||
void *scratch[],
|
||||
unsigned int scratch_length)
|
||||
{
|
||||
const struct TALER_BlindedPlanchet *bp = data;
|
||||
size_t tlen;
|
||||
size_t len;
|
||||
uint32_t be[2];
|
||||
char *buf;
|
||||
|
||||
(void) cls;
|
||||
(void) data_len;
|
||||
GNUNET_assert (1 == param_length);
|
||||
GNUNET_assert (scratch_length > 0);
|
||||
GNUNET_break (NULL == cls);
|
||||
be[0] = htonl ((uint32_t) bp->cipher);
|
||||
be[1] = htonl (0x0100); /* magic marker: blinded */
|
||||
switch (bp->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
tlen = bp->details.rsa_blinded_planchet.blinded_msg_size;
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
tlen = sizeof (bp->details.cs_blinded_planchet);
|
||||
break;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
len = tlen + sizeof (be);
|
||||
buf = GNUNET_malloc (len);
|
||||
memcpy (buf,
|
||||
&be,
|
||||
sizeof (be));
|
||||
switch (bp->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
memcpy (&buf[sizeof (be)],
|
||||
bp->details.rsa_blinded_planchet.blinded_msg,
|
||||
tlen);
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
memcpy (&buf[sizeof (be)],
|
||||
&bp->details.cs_blinded_planchet,
|
||||
tlen);
|
||||
break;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
scratch[0] = buf;
|
||||
param_values[0] = (void *) buf;
|
||||
param_lengths[0] = len;
|
||||
param_formats[0] = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
struct GNUNET_PQ_QueryParam
|
||||
TALER_PQ_query_param_blinded_planchet (
|
||||
const struct TALER_BlindedPlanchet *bp)
|
||||
{
|
||||
struct GNUNET_PQ_QueryParam res = {
|
||||
.conv = &qconv_blinded_planchet,
|
||||
.data = bp,
|
||||
.num_params = 1
|
||||
};
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called to convert input argument into SQL parameters.
|
||||
*
|
||||
|
@ -425,7 +425,16 @@ extract_denom_pub (void *cls,
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
// FIXME: add CS case!
|
||||
case TALER_DENOMINATION_CS:
|
||||
if (sizeof (pk->details.cs_public_key) != len)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
memcpy (&pk->details.cs_public_key,
|
||||
res,
|
||||
len);
|
||||
return GNUNET_OK;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
}
|
||||
@ -543,7 +552,16 @@ extract_denom_sig (void *cls,
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
// FIXME: add CS case!
|
||||
case TALER_DENOMINATION_CS:
|
||||
if (sizeof (sig->details.cs_signature) != len)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
memcpy (&sig->details.cs_signature,
|
||||
res,
|
||||
len);
|
||||
return GNUNET_OK;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
}
|
||||
@ -661,7 +679,16 @@ extract_blinded_denom_sig (void *cls,
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
// FIXME: add CS case!
|
||||
case TALER_DENOMINATION_CS:
|
||||
if (sizeof (sig->details.blinded_cs_answer) != len)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
memcpy (&sig->details.blinded_cs_answer,
|
||||
res,
|
||||
len);
|
||||
return GNUNET_OK;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
}
|
||||
@ -703,4 +730,129 @@ TALER_PQ_result_spec_blinded_denom_sig (
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract data from a Postgres database @a result at row @a row.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param result where to extract data from
|
||||
* @param int row to extract data from
|
||||
* @param fname name (or prefix) of the fields to extract from
|
||||
* @param[in,out] dst_size where to store size of result, may be NULL
|
||||
* @param[out] dst where to store the result
|
||||
* @return
|
||||
* #GNUNET_YES if all results could be extracted
|
||||
* #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
extract_blinded_planchet (void *cls,
|
||||
PGresult *result,
|
||||
int row,
|
||||
const char *fname,
|
||||
size_t *dst_size,
|
||||
void *dst)
|
||||
{
|
||||
struct TALER_BlindedPlanchet *bp = dst;
|
||||
size_t len;
|
||||
const char *res;
|
||||
int fnum;
|
||||
uint32_t be[2];
|
||||
|
||||
(void) cls;
|
||||
(void) dst_size;
|
||||
fnum = PQfnumber (result,
|
||||
fname);
|
||||
if (fnum < 0)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (PQgetisnull (result,
|
||||
row,
|
||||
fnum))
|
||||
return GNUNET_NO;
|
||||
|
||||
/* if a field is null, continue but
|
||||
* remember that we now return a different result */
|
||||
len = PQgetlength (result,
|
||||
row,
|
||||
fnum);
|
||||
res = PQgetvalue (result,
|
||||
row,
|
||||
fnum);
|
||||
if (len < sizeof (be))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
memcpy (&be,
|
||||
res,
|
||||
sizeof (be));
|
||||
if (0x0100 != ntohl (be[1])) /* magic marker: blinded */
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
res += sizeof (be);
|
||||
len -= sizeof (be);
|
||||
bp->cipher = ntohl (be[0]);
|
||||
switch (bp->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
bp->details.rsa_blinded_planchet.blinded_msg_size
|
||||
= len;
|
||||
bp->details.rsa_blinded_planchet.blinded_msg
|
||||
= GNUNET_memdup (res,
|
||||
len);
|
||||
return GNUNET_OK;
|
||||
case TALER_DENOMINATION_CS:
|
||||
if (sizeof (bp->details.cs_blinded_planchet) != len)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
memcpy (&bp->details.cs_blinded_planchet,
|
||||
res,
|
||||
len);
|
||||
return GNUNET_OK;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
}
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called to clean up memory allocated
|
||||
* by a #GNUNET_PQ_ResultConverter.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param rd result data to clean up
|
||||
*/
|
||||
static void
|
||||
clean_blinded_planchet (void *cls,
|
||||
void *rd)
|
||||
{
|
||||
struct TALER_BlindedPlanchet *bp = rd;
|
||||
|
||||
(void) cls;
|
||||
TALER_blinded_planchet_free (bp);
|
||||
}
|
||||
|
||||
|
||||
struct GNUNET_PQ_ResultSpec
|
||||
TALER_PQ_result_spec_blinded_planchet (
|
||||
const char *name,
|
||||
struct TALER_BlindedPlanchet *bp)
|
||||
{
|
||||
struct GNUNET_PQ_ResultSpec res = {
|
||||
.conv = &extract_blinded_planchet,
|
||||
.cleaner = &clean_blinded_planchet,
|
||||
.dst = (void *) bp,
|
||||
.fname = name
|
||||
};
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* end of pq_result_helper.c */
|
||||
|
14
src/testing/.gitignore
vendored
14
src/testing/.gitignore
vendored
@ -1,13 +1,16 @@
|
||||
test_auditor_api_version
|
||||
test_auditor_api_version_cs
|
||||
test_auditor_api_version_rsa
|
||||
test_bank_api_with_fakebank
|
||||
test_bank_api_with_fakebank_twisted
|
||||
test_bank_api_with_pybank
|
||||
test_bank_api_with_pybank_twisted
|
||||
test_taler_exchange_aggregator-postgres
|
||||
test_taler_exchange_wirewatch-postgres
|
||||
test_exchange_api_revocation
|
||||
test_exchange_api_revocation_cs
|
||||
test_exchange_api_revocation_rsa
|
||||
report*
|
||||
test_exchange_management_api
|
||||
test_exchange_management_api_cs
|
||||
test_exchange_management_api_rsa
|
||||
test_exchange_api_home/.local/share/taler/crypto-eddsa/
|
||||
test_exchange_api_home/.local/share/taler/crypto-rsa/
|
||||
test_exchange_api_home/.local/share/taler/exchange/offline-keys/secm_tofus.priv
|
||||
@ -24,12 +27,17 @@ test_taler_exchange_httpd_home/.local/share/taler/taler-exchange-secmod-eddsa/
|
||||
test_taler_exchange_httpd_home/.local/share/taler/taler-exchange-secmod-rsa/
|
||||
test_exchange_api_keys_cherry_picking_home/.local/share/taler/crypto-rsa/
|
||||
test_exchange_api_home/.local/share/taler/exchange-offline/secm_tofus.pub
|
||||
test_exchange_api_home/.local/share/taler/exchange-secmod-cs/
|
||||
test_exchange_api_home/.local/share/taler/exchange-secmod-eddsa/
|
||||
test_exchange_api_home/.local/share/taler/exchange-secmod-rsa/
|
||||
test_exchange_api_keys_cherry_picking_home/.local/share/taler/exchange-offline/secm_tofus.pub
|
||||
test_exchange_api_keys_cherry_picking_home/.local/share/taler/exchange-secmod-cs/
|
||||
test_exchange_api_keys_cherry_picking_home/.local/share/taler/exchange-secmod-eddsa/
|
||||
test_exchange_api_keys_cherry_picking_home/.local/share/taler/exchange-secmod-rsa/
|
||||
test_taler_exchange_httpd_home/.local/share/taler/exchange-offline/secm_tofus.pub
|
||||
test_taler_exchange_httpd_home/.local/share/taler/exchange-secmod-cs/
|
||||
test_taler_exchange_httpd_home/.local/share/taler/exchange-secmod-eddsa/
|
||||
test_taler_exchange_httpd_home/.local/share/taler/exchange-secmod-rsa/
|
||||
test_kyc_api
|
||||
test_helper_cs_home/
|
||||
test_helper_rsa_home/
|
@ -114,16 +114,23 @@ AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export PATH=
|
||||
|
||||
.NOTPARALLEL:
|
||||
check_PROGRAMS = \
|
||||
test_auditor_api \
|
||||
test_auditor_api_version \
|
||||
test_auditor_api_cs \
|
||||
test_auditor_api_rsa \
|
||||
test_auditor_api_version_rsa \
|
||||
test_auditor_api_version_cs \
|
||||
test_bank_api_with_fakebank \
|
||||
test_bank_api_with_pybank \
|
||||
test_bank_api_with_nexus \
|
||||
test_exchange_api \
|
||||
test_exchange_api_keys_cherry_picking \
|
||||
test_exchange_api_revocation \
|
||||
test_exchange_api_overlapping_keys_bug \
|
||||
test_exchange_management_api \
|
||||
test_exchange_api_cs \
|
||||
test_exchange_api_rsa \
|
||||
test_exchange_api_keys_cherry_picking_cs \
|
||||
test_exchange_api_keys_cherry_picking_rsa \
|
||||
test_exchange_api_revocation_cs \
|
||||
test_exchange_api_revocation_rsa \
|
||||
test_exchange_api_overlapping_keys_bug_cs \
|
||||
test_exchange_api_overlapping_keys_bug_rsa \
|
||||
test_exchange_management_api_cs \
|
||||
test_exchange_management_api_rsa \
|
||||
test_kyc_api \
|
||||
test_taler_exchange_aggregator-postgres \
|
||||
test_taler_exchange_wirewatch-postgres
|
||||
@ -139,9 +146,9 @@ endif
|
||||
TESTS = \
|
||||
$(check_PROGRAMS)
|
||||
|
||||
test_auditor_api_SOURCES = \
|
||||
test_auditor_api_cs_SOURCES = \
|
||||
test_auditor_api.c
|
||||
test_auditor_api_LDADD = \
|
||||
test_auditor_api_cs_LDADD = \
|
||||
$(top_builddir)/src/lib/libtalerauditor.la \
|
||||
libtalertesting.la \
|
||||
$(top_builddir)/src/lib/libtalerexchange.la \
|
||||
@ -150,19 +157,51 @@ test_auditor_api_LDADD = \
|
||||
$(top_builddir)/src/bank-lib/libtalerbank.la \
|
||||
$(top_builddir)/src/json/libtalerjson.la \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
-lgnunettesting \
|
||||
-lgnunetcurl \
|
||||
-lgnunetutil \
|
||||
-ljansson \
|
||||
$(XLIB)
|
||||
|
||||
test_auditor_api_rsa_SOURCES = \
|
||||
test_auditor_api.c
|
||||
test_auditor_api_rsa_LDADD = \
|
||||
$(top_builddir)/src/lib/libtalerauditor.la \
|
||||
libtalertesting.la \
|
||||
$(top_builddir)/src/lib/libtalerexchange.la \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
$(top_builddir)/src/bank-lib/libtalerfakebank.la \
|
||||
$(top_builddir)/src/bank-lib/libtalerbank.la \
|
||||
$(top_builddir)/src/json/libtalerjson.la \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
-lgnunettesting \
|
||||
-lgnunetcurl \
|
||||
-lgnunetutil \
|
||||
-ljansson \
|
||||
$(XLIB)
|
||||
|
||||
|
||||
test_auditor_api_version_SOURCES = \
|
||||
test_auditor_api_version_cs_SOURCES = \
|
||||
test_auditor_api_version.c
|
||||
test_auditor_api_version_LDADD = \
|
||||
test_auditor_api_version_cs_LDADD = \
|
||||
libtalertesting.la \
|
||||
$(top_builddir)/src/lib/libtalerauditor.la \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
-lgnunettesting \
|
||||
-lgnunetcurl \
|
||||
-lgnunetutil \
|
||||
-ljansson \
|
||||
$(XLIB)
|
||||
|
||||
test_auditor_api_version_rsa_SOURCES = \
|
||||
test_auditor_api_version.c
|
||||
test_auditor_api_version_rsa_LDADD = \
|
||||
libtalertesting.la \
|
||||
$(top_builddir)/src/lib/libtalerauditor.la \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
-lgnunettesting \
|
||||
-lgnunetcurl \
|
||||
-lgnunetutil \
|
||||
-ljansson \
|
||||
@ -195,9 +234,9 @@ test_bank_api_with_pybank_LDADD = \
|
||||
$(top_builddir)/src/bank-lib/libtalerbank.la \
|
||||
$(XLIB)
|
||||
|
||||
test_exchange_api_SOURCES = \
|
||||
test_exchange_api_cs_SOURCES = \
|
||||
test_exchange_api.c
|
||||
test_exchange_api_LDADD = \
|
||||
test_exchange_api_cs_LDADD = \
|
||||
libtalertesting.la \
|
||||
$(top_builddir)/src/lib/libtalerexchange.la \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
@ -205,23 +244,15 @@ test_exchange_api_LDADD = \
|
||||
$(top_builddir)/src/bank-lib/libtalerbank.la \
|
||||
$(top_builddir)/src/json/libtalerjson.la \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
-lgnunettesting \
|
||||
-lgnunetcurl \
|
||||
-lgnunetutil \
|
||||
-ljansson \
|
||||
$(XLIB)
|
||||
|
||||
test_exchange_management_api_SOURCES = \
|
||||
test_exchange_management_api.c
|
||||
test_exchange_management_api_LDADD = \
|
||||
libtalertesting.la \
|
||||
$(top_builddir)/src/lib/libtalerexchange.la \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
-lgnunetutil \
|
||||
$(XLIB)
|
||||
|
||||
test_exchange_api_revocation_SOURCES = \
|
||||
test_exchange_api_revocation.c
|
||||
test_exchange_api_revocation_LDADD = \
|
||||
test_exchange_api_rsa_SOURCES = \
|
||||
test_exchange_api.c
|
||||
test_exchange_api_rsa_LDADD = \
|
||||
libtalertesting.la \
|
||||
$(top_builddir)/src/lib/libtalerexchange.la \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
@ -229,39 +260,126 @@ test_exchange_api_revocation_LDADD = \
|
||||
$(top_builddir)/src/bank-lib/libtalerbank.la \
|
||||
$(top_builddir)/src/json/libtalerjson.la \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
-lgnunettesting \
|
||||
-lgnunetcurl \
|
||||
-lgnunetutil \
|
||||
-ljansson \
|
||||
$(XLIB)
|
||||
|
||||
test_exchange_api_keys_cherry_picking_SOURCES = \
|
||||
test_exchange_api_keys_cherry_picking_cs_SOURCES = \
|
||||
test_exchange_api_keys_cherry_picking.c
|
||||
test_exchange_api_keys_cherry_picking_LDADD = \
|
||||
test_exchange_api_keys_cherry_picking_cs_LDADD = \
|
||||
libtalertesting.la \
|
||||
$(top_builddir)/src/lib/libtalerexchange.la \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
$(top_builddir)/src/json/libtalerjson.la \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
$(top_builddir)/src/bank-lib/libtalerbank.la \
|
||||
-lgnunettesting \
|
||||
-lgnunetcurl \
|
||||
-lgnunetutil \
|
||||
-ljansson \
|
||||
$(XLIB)
|
||||
|
||||
test_exchange_api_overlapping_keys_bug_SOURCES = \
|
||||
test_exchange_api_overlapping_keys_bug.c
|
||||
test_exchange_api_overlapping_keys_bug_LDADD = \
|
||||
test_exchange_api_keys_cherry_picking_rsa_SOURCES = \
|
||||
test_exchange_api_keys_cherry_picking.c
|
||||
test_exchange_api_keys_cherry_picking_rsa_LDADD = \
|
||||
libtalertesting.la \
|
||||
$(top_builddir)/src/lib/libtalerexchange.la \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
$(top_builddir)/src/json/libtalerjson.la \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
$(top_builddir)/src/bank-lib/libtalerbank.la \
|
||||
-lgnunettesting \
|
||||
-lgnunetcurl \
|
||||
-lgnunetutil \
|
||||
-ljansson \
|
||||
$(XLIB)
|
||||
|
||||
test_exchange_api_revocation_cs_SOURCES = \
|
||||
test_exchange_api_revocation.c
|
||||
test_exchange_api_revocation_cs_LDADD = \
|
||||
libtalertesting.la \
|
||||
$(top_builddir)/src/lib/libtalerexchange.la \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
$(top_builddir)/src/bank-lib/libtalerfakebank.la \
|
||||
$(top_builddir)/src/bank-lib/libtalerbank.la \
|
||||
$(top_builddir)/src/json/libtalerjson.la \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
-lgnunettesting \
|
||||
-lgnunetcurl \
|
||||
-lgnunetutil \
|
||||
-ljansson \
|
||||
$(XLIB)
|
||||
|
||||
test_exchange_api_revocation_rsa_SOURCES = \
|
||||
test_exchange_api_revocation.c
|
||||
test_exchange_api_revocation_rsa_LDADD = \
|
||||
libtalertesting.la \
|
||||
$(top_builddir)/src/lib/libtalerexchange.la \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
$(top_builddir)/src/bank-lib/libtalerfakebank.la \
|
||||
$(top_builddir)/src/bank-lib/libtalerbank.la \
|
||||
$(top_builddir)/src/json/libtalerjson.la \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
-lgnunettesting \
|
||||
-lgnunetcurl \
|
||||
-lgnunetutil \
|
||||
-ljansson \
|
||||
$(XLIB)
|
||||
|
||||
|
||||
test_exchange_api_overlapping_keys_bug_cs_SOURCES = \
|
||||
test_exchange_api_overlapping_keys_bug.c
|
||||
test_exchange_api_overlapping_keys_bug_cs_LDADD = \
|
||||
libtalertesting.la \
|
||||
$(top_builddir)/src/lib/libtalerexchange.la \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
$(top_builddir)/src/json/libtalerjson.la \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
$(top_builddir)/src/bank-lib/libtalerbank.la \
|
||||
-lgnunettesting \
|
||||
-lgnunetcurl \
|
||||
-lgnunetutil \
|
||||
-ljansson \
|
||||
$(XLIB)
|
||||
|
||||
test_exchange_api_overlapping_keys_bug_rsa_SOURCES = \
|
||||
test_exchange_api_overlapping_keys_bug.c
|
||||
test_exchange_api_overlapping_keys_bug_rsa_LDADD = \
|
||||
libtalertesting.la \
|
||||
$(top_builddir)/src/lib/libtalerexchange.la \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
$(top_builddir)/src/json/libtalerjson.la \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
$(top_builddir)/src/bank-lib/libtalerbank.la \
|
||||
-lgnunettesting \
|
||||
-lgnunetcurl \
|
||||
-lgnunetutil \
|
||||
-ljansson \
|
||||
$(XLIB)
|
||||
|
||||
test_exchange_management_api_cs_SOURCES = \
|
||||
test_exchange_management_api.c
|
||||
test_exchange_management_api_cs_LDADD = \
|
||||
libtalertesting.la \
|
||||
$(top_builddir)/src/lib/libtalerexchange.la \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
-lgnunettesting \
|
||||
-lgnunetutil \
|
||||
$(XLIB)
|
||||
|
||||
test_exchange_management_api_rsa_SOURCES = \
|
||||
test_exchange_management_api.c
|
||||
test_exchange_management_api_rsa_LDADD = \
|
||||
libtalertesting.la \
|
||||
$(top_builddir)/src/lib/libtalerexchange.la \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
-lgnunettesting \
|
||||
-lgnunetutil \
|
||||
$(XLIB)
|
||||
|
||||
|
||||
test_taler_exchange_aggregator_postgres_SOURCES = \
|
||||
test_taler_exchange_aggregator.c
|
||||
test_taler_exchange_aggregator_postgres_LDADD = \
|
||||
@ -306,6 +424,7 @@ test_exchange_api_twisted_LDADD = \
|
||||
$(top_builddir)/src/bank-lib/libtalerbank.la \
|
||||
$(top_builddir)/src/json/libtalerjson.la \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
-lgnunettesting \
|
||||
-lgnunetjson \
|
||||
-lgnunetcurl \
|
||||
-lgnunetutil \
|
||||
@ -321,6 +440,7 @@ test_bank_api_with_fakebank_twisted_LDADD = \
|
||||
$(top_builddir)/src/lib/libtalerexchange.la \
|
||||
$(top_builddir)/src/json/libtalerjson.la \
|
||||
libtalertwistertesting.la \
|
||||
-lgnunettesting \
|
||||
-lgnunetjson \
|
||||
-lgnunetcurl \
|
||||
-lgnunetutil \
|
||||
@ -336,6 +456,7 @@ test_bank_api_with_pybank_twisted_LDADD = \
|
||||
$(top_builddir)/src/lib/libtalerexchange.la \
|
||||
$(top_builddir)/src/json/libtalerjson.la \
|
||||
libtalertwistertesting.la \
|
||||
-lgnunettesting \
|
||||
-lgnunetjson \
|
||||
-lgnunetcurl \
|
||||
-lgnunetutil \
|
||||
@ -363,7 +484,8 @@ test_kyc_api_LDADD = \
|
||||
|
||||
EXTRA_DIST = \
|
||||
test_auditor_api.conf \
|
||||
test_auditor_api_expire_reserve_now.conf \
|
||||
test_auditor_api_expire_reserve_now-cs.conf \
|
||||
test_auditor_api_expire_reserve_now-rsa.conf \
|
||||
test_bank_api_fakebank.conf \
|
||||
test_bank_api_fakebank_twisted.conf \
|
||||
test_bank_api_pybank.conf \
|
||||
@ -376,9 +498,11 @@ EXTRA_DIST = \
|
||||
test_exchange_api_keys_cherry_picking_home/.local/share/taler/exchange-offline/master.priv \
|
||||
test_exchange_api_keys_cherry_picking_home/.local/share/taler/exchange/offline-keys/master.priv \
|
||||
test_exchange_api_keys_cherry_picking_home/.local/share/taler/exchange/wirefees/x-taler-bank.fee \
|
||||
test_exchange_api.conf \
|
||||
test_exchange_api-cs.conf \
|
||||
test_exchange_api-rsa.conf \
|
||||
test_exchange_api_twisted.conf \
|
||||
test_exchange_api_keys_cherry_picking.conf \
|
||||
test_exchange_api_keys_cherry_picking-cs.conf \
|
||||
test_exchange_api_keys_cherry_picking-rsa.conf \
|
||||
test_exchange_api_expire_reserve_now.conf \
|
||||
test_taler_exchange_httpd_home/.config/taler/account-1.json \
|
||||
test_taler_exchange_httpd_home/.local/share/taler/exchange-offline/master.priv \
|
||||
|
@ -92,4 +92,5 @@ fee_withdraw = EUR:0.00
|
||||
fee_deposit = EUR:0.00
|
||||
fee_refresh = EUR:0.01
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
@ -81,4 +81,5 @@ fee_withdraw = EUR:0.00
|
||||
fee_deposit = EUR:0.00
|
||||
fee_refresh = EUR:0.01
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
140
src/testing/test_auditor_api-cs.conf
Normal file
140
src/testing/test_auditor_api-cs.conf
Normal file
@ -0,0 +1,140 @@
|
||||
|
||||
# This file is in the public domain.
|
||||
#
|
||||
[PATHS]
|
||||
# Persistent data storage for the testcase
|
||||
TALER_TEST_HOME = test_exchange_api_home/
|
||||
TALER_RUNTIME_DIR = ${TMPDIR:-${TMP:-/tmp}}/${USER:-}/taler-system-runtime/
|
||||
|
||||
[taler-exchange-secmod-cs]
|
||||
# Reduce from 1 year to speed up test
|
||||
LOOKAHEAD_SIGN = 24 days
|
||||
|
||||
[taler-exchange-secmod-eddsa]
|
||||
# Reduce from 1 year to speed up test
|
||||
LOOKAHEAD_SIGN = 24 days
|
||||
# Reduce from 12 weeks to ensure we have multiple
|
||||
DURATION = 14 days
|
||||
|
||||
|
||||
[taler]
|
||||
# Currency supported by the exchange (can only be one)
|
||||
CURRENCY = EUR
|
||||
CURRENCY_ROUND_UNIT = EUR:0.01
|
||||
|
||||
[auditor]
|
||||
BASE_URL = "http://localhost:8083/"
|
||||
|
||||
# HTTP port the auditor listens to
|
||||
PORT = 8083
|
||||
|
||||
TINY_AMOUNT = EUR:0.01
|
||||
|
||||
[exchange]
|
||||
|
||||
# HTTP port the exchange listens to
|
||||
PORT = 8081
|
||||
|
||||
# Master public key used to sign the exchange's various keys
|
||||
MASTER_PUBLIC_KEY = 98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG
|
||||
|
||||
# How to access our database
|
||||
DB = postgres
|
||||
|
||||
# Base URL of the exchange. Must be set to a URL where the
|
||||
# exchange (or the twister) is actually listening.
|
||||
BASE_URL = "http://localhost:8081/"
|
||||
|
||||
[exchangedb-postgres]
|
||||
CONFIG = "postgres:///talercheck"
|
||||
|
||||
[auditordb-postgres]
|
||||
CONFIG = "postgres:///talercheck"
|
||||
|
||||
# Sections starting with "exchange-account-" configure the bank accounts
|
||||
# of the exchange. The "URL" specifies the account in
|
||||
# payto://-format.
|
||||
[exchange-account-1]
|
||||
# What is the URL of our account?
|
||||
PAYTO_URI = "payto://x-taler-bank/localhost/42"
|
||||
|
||||
[exchange-accountcredentials-1]
|
||||
WIRE_GATEWAY_URL = "http://localhost:8082/42/"
|
||||
|
||||
[bank]
|
||||
HTTP_PORT = 8082
|
||||
|
||||
# ENABLE_CREDIT = YES
|
||||
|
||||
[exchange-account-2]
|
||||
# What is the bank account (with the "Taler Bank" demo system)?
|
||||
PAYTO_URI = "payto://x-taler-bank/localhost/2"
|
||||
ENABLE_DEBIT = YES
|
||||
ENABLE_CREDIT = YES
|
||||
|
||||
# Authentication information for basic authentication
|
||||
[exchange-accountcredentials-2]
|
||||
WIRE_GATEWAY_URL = "http://localhost:8082/2/"
|
||||
WIRE_GATEWAY_AUTH_METHOD = "basic"
|
||||
USERNAME = user
|
||||
PASSWORD = pass
|
||||
|
||||
|
||||
|
||||
|
||||
# Sections starting with "coin_" specify which denominations
|
||||
# the exchange should support (and their respective fee structure)
|
||||
[coin_eur_ct_1]
|
||||
value = EUR:0.01
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.00
|
||||
fee_deposit = EUR:0.00
|
||||
fee_refresh = EUR:0.01
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_ct_10]
|
||||
value = EUR:0.10
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_1]
|
||||
value = EUR:1
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_5]
|
||||
value = EUR:5
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_10]
|
||||
value = EUR:10
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
@ -93,6 +93,7 @@ fee_withdraw = EUR:0.00
|
||||
fee_deposit = EUR:0.00
|
||||
fee_refresh = EUR:0.01
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_eur_ct_10]
|
||||
@ -104,6 +105,7 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_eur_1]
|
||||
@ -115,6 +117,7 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_eur_5]
|
||||
@ -126,6 +129,7 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_eur_10]
|
||||
@ -137,4 +141,5 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
@ -29,6 +29,7 @@
|
||||
#include "taler_auditor_service.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include <gnunet/gnunet_testing_lib.h>
|
||||
#include <microhttpd.h>
|
||||
#include "taler_bank_service.h"
|
||||
#include "taler_fakebank_lib.h"
|
||||
@ -39,10 +40,9 @@
|
||||
* Configuration file we use. One (big) configuration is used
|
||||
* for the various components for this test.
|
||||
*/
|
||||
#define CONFIG_FILE "test_auditor_api.conf"
|
||||
static char *config_file;
|
||||
|
||||
#define CONFIG_FILE_EXPIRE_RESERVE_NOW \
|
||||
"test_auditor_api_expire_reserve_now.conf"
|
||||
static char *config_file_expire_reserve_now;
|
||||
|
||||
/**
|
||||
* Exchange configuration data.
|
||||
@ -61,7 +61,7 @@ static struct TALER_TESTING_BankConfiguration bc;
|
||||
* @param label label to use for the command.
|
||||
*/
|
||||
#define CMD_EXEC_WIREWATCH(label) \
|
||||
TALER_TESTING_cmd_exec_wirewatch (label, CONFIG_FILE)
|
||||
TALER_TESTING_cmd_exec_wirewatch (label, config_file)
|
||||
|
||||
/**
|
||||
* Execute the taler-exchange-aggregator, closer and transfer commands with
|
||||
@ -71,8 +71,8 @@ static struct TALER_TESTING_BankConfiguration bc;
|
||||
*/
|
||||
#define CMD_EXEC_AGGREGATOR(label) \
|
||||
TALER_TESTING_cmd_sleep (label "-sleep", 1), \
|
||||
TALER_TESTING_cmd_exec_aggregator (label, CONFIG_FILE), \
|
||||
TALER_TESTING_cmd_exec_transfer (label, CONFIG_FILE)
|
||||
TALER_TESTING_cmd_exec_aggregator (label, config_file), \
|
||||
TALER_TESTING_cmd_exec_transfer (label, config_file)
|
||||
|
||||
/**
|
||||
* Run wire transfer of funds from some user's account to the
|
||||
@ -92,7 +92,7 @@ static struct TALER_TESTING_BankConfiguration bc;
|
||||
* @param label label to use for the command.
|
||||
*/
|
||||
#define CMD_RUN_AUDITOR(label) \
|
||||
TALER_TESTING_cmd_exec_auditor (label, CONFIG_FILE)
|
||||
TALER_TESTING_cmd_exec_auditor (label, config_file)
|
||||
|
||||
|
||||
/**
|
||||
@ -406,7 +406,7 @@ run (void *cls,
|
||||
TALER_TESTING_cmd_revoke ("revoke-1",
|
||||
MHD_HTTP_OK,
|
||||
"recoup-withdraw-coin-1",
|
||||
CONFIG_FILE),
|
||||
config_file),
|
||||
TALER_TESTING_cmd_recoup ("recoup-1",
|
||||
MHD_HTTP_OK,
|
||||
"recoup-withdraw-coin-1",
|
||||
@ -426,9 +426,9 @@ run (void *cls,
|
||||
CMD_TRANSFER_TO_EXCHANGE ("short-lived-reserve",
|
||||
"EUR:5.01"),
|
||||
TALER_TESTING_cmd_exec_wirewatch ("short-lived-aggregation",
|
||||
CONFIG_FILE_EXPIRE_RESERVE_NOW),
|
||||
config_file_expire_reserve_now),
|
||||
TALER_TESTING_cmd_exec_aggregator ("close-reserves",
|
||||
CONFIG_FILE_EXPIRE_RESERVE_NOW),
|
||||
config_file_expire_reserve_now),
|
||||
/**
|
||||
* Fill reserve with EUR:2.02, as withdraw fee is 1 ct per
|
||||
* config, then withdraw two coin, partially spend one, and
|
||||
@ -466,7 +466,7 @@ run (void *cls,
|
||||
TALER_TESTING_cmd_revoke ("revoke-2",
|
||||
MHD_HTTP_OK,
|
||||
"recoup-withdraw-coin-2a",
|
||||
CONFIG_FILE),
|
||||
config_file),
|
||||
TALER_TESTING_cmd_recoup ("recoup-2",
|
||||
MHD_HTTP_OK,
|
||||
"recoup-withdraw-coin-2a",
|
||||
@ -631,7 +631,7 @@ run (void *cls,
|
||||
|
||||
struct TALER_TESTING_Command commands[] = {
|
||||
TALER_TESTING_cmd_exec_offline_sign_fees ("offline-sign-fees",
|
||||
CONFIG_FILE,
|
||||
config_file,
|
||||
"EUR:0.01",
|
||||
"EUR:0.01"),
|
||||
TALER_TESTING_cmd_auditor_add ("add-auditor-OK",
|
||||
@ -642,11 +642,11 @@ run (void *cls,
|
||||
MHD_HTTP_NO_CONTENT,
|
||||
false),
|
||||
TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys",
|
||||
CONFIG_FILE),
|
||||
config_file),
|
||||
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys",
|
||||
2),
|
||||
TALER_TESTING_cmd_exec_auditor_offline ("auditor-offline",
|
||||
CONFIG_FILE),
|
||||
config_file),
|
||||
CMD_RUN_AUDITOR ("virgin-auditor"),
|
||||
TALER_TESTING_cmd_exchanges_with_url ("check-exchange",
|
||||
MHD_HTTP_OK,
|
||||
@ -682,25 +682,35 @@ int
|
||||
main (int argc,
|
||||
char *const *argv)
|
||||
{
|
||||
const char *cipher;
|
||||
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
/* These environment variables get in the way... */
|
||||
unsetenv ("XDG_DATA_HOME");
|
||||
unsetenv ("XDG_CONFIG_HOME");
|
||||
GNUNET_log_setup ("test-auditor-api",
|
||||
GNUNET_log_setup (argv[0],
|
||||
"INFO",
|
||||
NULL);
|
||||
|
||||
cipher = GNUNET_TESTING_get_testname_from_underscore (argv[0]);
|
||||
GNUNET_assert (NULL != cipher);
|
||||
GNUNET_asprintf (&config_file,
|
||||
"test_auditor_api-%s.conf",
|
||||
cipher);
|
||||
GNUNET_asprintf (&config_file_expire_reserve_now,
|
||||
"test_auditor_api_expire_reserve_now-%s.conf",
|
||||
cipher);
|
||||
/* Check fakebank port is available and get configuration data. */
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_prepare_fakebank (CONFIG_FILE,
|
||||
TALER_TESTING_prepare_fakebank (config_file,
|
||||
"exchange-account-2",
|
||||
&bc))
|
||||
return 77;
|
||||
TALER_TESTING_cleanup_files (CONFIG_FILE);
|
||||
TALER_TESTING_cleanup_files (config_file);
|
||||
/* @helpers. Run keyup, create tables, ... Note: it
|
||||
* fetches the port number from config in order to see
|
||||
* if it's available. */
|
||||
switch (TALER_TESTING_prepare_exchange (CONFIG_FILE,
|
||||
switch (TALER_TESTING_prepare_exchange (config_file,
|
||||
GNUNET_YES,
|
||||
&ec))
|
||||
{
|
||||
@ -717,7 +727,7 @@ main (int argc,
|
||||
*/
|
||||
TALER_TESTING_auditor_setup (&run,
|
||||
NULL,
|
||||
CONFIG_FILE))
|
||||
config_file))
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
|
@ -1,4 +1,4 @@
|
||||
@INLINE@ test_auditor_api.conf
|
||||
@INLINE@ test_auditor_api-cs.conf
|
||||
|
||||
[exchangedb]
|
||||
IDLE_RESERVE_EXPIRATION_TIME = 0 s
|
4
src/testing/test_auditor_api_expire_reserve_now-rsa.conf
Normal file
4
src/testing/test_auditor_api_expire_reserve_now-rsa.conf
Normal file
@ -0,0 +1,4 @@
|
||||
@INLINE@ test_auditor_api-rsa.conf
|
||||
|
||||
[exchangedb]
|
||||
IDLE_RESERVE_EXPIRATION_TIME = 0 s
|
201
src/testing/test_exchange_api-cs.conf
Normal file
201
src/testing/test_exchange_api-cs.conf
Normal file
@ -0,0 +1,201 @@
|
||||
# This file is in the public domain.
|
||||
#
|
||||
|
||||
[PATHS]
|
||||
# Persistent data storage for the testcase
|
||||
TALER_TEST_HOME = test_exchange_api_home/
|
||||
TALER_RUNTIME_DIR = ${TMPDIR:-${TMP:-/tmp}}/${USER:-}/taler-system-runtime/
|
||||
|
||||
[taler-exchange-secmod-rsa]
|
||||
# Reduce from 1 year to speed up test
|
||||
LOOKAHEAD_SIGN = 24 days
|
||||
|
||||
[taler-exchange-secmod-eddsa]
|
||||
# Reduce from 1 year to speed up test
|
||||
LOOKAHEAD_SIGN = 24 days
|
||||
# Reduce from 12 weeks to ensure we have multiple
|
||||
DURATION = 14 days
|
||||
|
||||
[taler]
|
||||
# Currency supported by the exchange (can only be one)
|
||||
CURRENCY = EUR
|
||||
CURRENCY_ROUND_UNIT = EUR:0.01
|
||||
|
||||
[auditor]
|
||||
BASE_URL = "http://localhost:8083/"
|
||||
|
||||
# HTTP port the auditor listens to
|
||||
PORT = 8083
|
||||
|
||||
[exchange]
|
||||
|
||||
TERMS_ETAG = 0
|
||||
PRIVACY_ETAG = 0
|
||||
|
||||
# HTTP port the exchange listens to
|
||||
PORT = 8081
|
||||
|
||||
# Master public key used to sign the exchange's various keys
|
||||
MASTER_PUBLIC_KEY = 98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG
|
||||
|
||||
# How to access our database
|
||||
DB = postgres
|
||||
|
||||
# Base URL of the exchange. Must be set to a URL where the
|
||||
# exchange (or the twister) is actually listening.
|
||||
BASE_URL = "http://localhost:8081/"
|
||||
|
||||
[exchangedb-postgres]
|
||||
CONFIG = "postgres:///talercheck"
|
||||
|
||||
[auditordb-postgres]
|
||||
CONFIG = "postgres:///talercheck"
|
||||
|
||||
# Sections starting with "exchange-account-" configure the bank accounts
|
||||
# of the exchange. The "URL" specifies the account in
|
||||
# payto://-format.
|
||||
[exchange-account-1]
|
||||
# What is the URL of our account?
|
||||
PAYTO_URI = "payto://x-taler-bank/localhost/42"
|
||||
# ENABLE_CREDIT = YES
|
||||
|
||||
[exchange-accountcredentials-1]
|
||||
WIRE_GATEWAY_URL = "http://localhost:9081/42/"
|
||||
|
||||
[exchange-account-2]
|
||||
# What is the bank account (with the "Taler Bank" demo system)?
|
||||
PAYTO_URI = "payto://x-taler-bank/localhost/2"
|
||||
ENABLE_DEBIT = YES
|
||||
ENABLE_CREDIT = YES
|
||||
|
||||
[exchange-accountcredentials-2]
|
||||
WIRE_GATEWAY_AUTH_METHOD = basic
|
||||
USERNAME = Exchange
|
||||
PASSWORD = x
|
||||
WIRE_GATEWAY_URL = "http://localhost:9081/2/"
|
||||
|
||||
[bank]
|
||||
HTTP_PORT = 9081
|
||||
|
||||
# Enabled extensions
|
||||
[exchange-extension-age_restriction]
|
||||
ENABLED = YES
|
||||
# default age groups:
|
||||
#AGE_GROUPS = "8:10:12:14:16:18:21"
|
||||
|
||||
# Sections starting with "coin_" specify which denominations
|
||||
# the exchange should support (and their respective fee structure)
|
||||
[coin_eur_ct_1]
|
||||
value = EUR:0.01
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.00
|
||||
fee_deposit = EUR:0.00
|
||||
fee_refresh = EUR:0.01
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_ct_10]
|
||||
value = EUR:0.10
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_1]
|
||||
value = EUR:1
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_5]
|
||||
value = EUR:5
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_10]
|
||||
value = EUR:10
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_ct_1_age_restricted]
|
||||
value = EUR:0.01
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.00
|
||||
fee_deposit = EUR:0.00
|
||||
fee_refresh = EUR:0.01
|
||||
fee_refund = EUR:0.01
|
||||
age_restricted = true
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_ct_10_age_restricted]
|
||||
value = EUR:0.10
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
age_restricted = true
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_1_age_restricted]
|
||||
value = EUR:1
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
age_restricted = true
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_5_age_restricted]
|
||||
value = EUR:5
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
age_restricted = true
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_10_age_restricted]
|
||||
value = EUR:10
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
age_restricted = true
|
||||
CIPHER = CS
|
@ -94,6 +94,7 @@ fee_withdraw = EUR:0.00
|
||||
fee_deposit = EUR:0.00
|
||||
fee_refresh = EUR:0.01
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_eur_ct_10]
|
||||
@ -105,6 +106,7 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_eur_1]
|
||||
@ -116,6 +118,7 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_eur_5]
|
||||
@ -127,6 +130,7 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_eur_10]
|
||||
@ -138,6 +142,7 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_eur_ct_1_age_restricted]
|
||||
@ -151,6 +156,7 @@ fee_refresh = EUR:0.01
|
||||
fee_refund = EUR:0.01
|
||||
rsa_keysize = 1024
|
||||
age_restricted = true
|
||||
CIPHER = RSA
|
||||
|
||||
[coin_eur_ct_10_age_restricted]
|
||||
value = EUR:0.10
|
||||
@ -163,6 +169,7 @@ fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
rsa_keysize = 1024
|
||||
age_restricted = true
|
||||
CIPHER = RSA
|
||||
|
||||
[coin_eur_1_age_restricted]
|
||||
value = EUR:1
|
||||
@ -175,6 +182,7 @@ fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
rsa_keysize = 1024
|
||||
age_restricted = true
|
||||
CIPHER = RSA
|
||||
|
||||
[coin_eur_5_age_restricted]
|
||||
value = EUR:5
|
||||
@ -187,6 +195,7 @@ fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
rsa_keysize = 1024
|
||||
age_restricted = true
|
||||
CIPHER = RSA
|
||||
|
||||
[coin_eur_10_age_restricted]
|
||||
value = EUR:10
|
||||
@ -199,3 +208,4 @@ fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
rsa_keysize = 1024
|
||||
age_restricted = true
|
||||
CIPHER = RSA
|
@ -29,6 +29,7 @@
|
||||
#include "taler_exchange_service.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include <gnunet/gnunet_testing_lib.h>
|
||||
#include <microhttpd.h>
|
||||
#include "taler_bank_service.h"
|
||||
#include "taler_fakebank_lib.h"
|
||||
@ -38,10 +39,9 @@
|
||||
* Configuration file we use. One (big) configuration is used
|
||||
* for the various components for this test.
|
||||
*/
|
||||
#define CONFIG_FILE "test_exchange_api.conf"
|
||||
static char *config_file;
|
||||
|
||||
#define CONFIG_FILE_EXPIRE_RESERVE_NOW \
|
||||
"test_exchange_api_expire_reserve_now.conf"
|
||||
static char *config_file_expire_reserve_now;
|
||||
|
||||
|
||||
/**
|
||||
@ -62,7 +62,7 @@ static struct TALER_TESTING_BankConfiguration bc;
|
||||
* @param label label to use for the command.
|
||||
*/
|
||||
#define CMD_EXEC_WIREWATCH(label) \
|
||||
TALER_TESTING_cmd_exec_wirewatch (label, CONFIG_FILE)
|
||||
TALER_TESTING_cmd_exec_wirewatch (label, config_file)
|
||||
|
||||
/**
|
||||
* Execute the taler-exchange-aggregator, closer and transfer commands with
|
||||
@ -71,8 +71,8 @@ static struct TALER_TESTING_BankConfiguration bc;
|
||||
* @param label label to use for the command.
|
||||
*/
|
||||
#define CMD_EXEC_AGGREGATOR(label) \
|
||||
TALER_TESTING_cmd_exec_aggregator (label "-aggregator", CONFIG_FILE), \
|
||||
TALER_TESTING_cmd_exec_transfer (label "-transfer", CONFIG_FILE)
|
||||
TALER_TESTING_cmd_exec_aggregator (label "-aggregator", config_file), \
|
||||
TALER_TESTING_cmd_exec_transfer (label "-transfer", config_file)
|
||||
|
||||
|
||||
/**
|
||||
@ -406,7 +406,6 @@ run (void *cls,
|
||||
TALER_TESTING_cmd_end ()
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This block checks whether a wire deadline
|
||||
* very far in the future does NOT get aggregated now.
|
||||
@ -680,7 +679,7 @@ run (void *cls,
|
||||
TALER_TESTING_cmd_revoke ("revoke-0-EUR:5",
|
||||
MHD_HTTP_OK,
|
||||
"recoup-withdraw-coin-1",
|
||||
CONFIG_FILE),
|
||||
config_file),
|
||||
/* Recoup coin to reserve */
|
||||
TALER_TESTING_cmd_recoup ("recoup-1",
|
||||
MHD_HTTP_OK,
|
||||
@ -780,14 +779,14 @@ run (void *cls,
|
||||
bc.exchange_payto,
|
||||
"short-lived-reserve"),
|
||||
TALER_TESTING_cmd_exec_wirewatch ("short-lived-aggregation",
|
||||
CONFIG_FILE_EXPIRE_RESERVE_NOW),
|
||||
config_file_expire_reserve_now),
|
||||
TALER_TESTING_cmd_exec_closer ("close-reserves",
|
||||
CONFIG_FILE_EXPIRE_RESERVE_NOW,
|
||||
config_file_expire_reserve_now,
|
||||
"EUR:5",
|
||||
"EUR:0.01",
|
||||
"short-lived-reserve"),
|
||||
TALER_TESTING_cmd_exec_transfer ("close-reserves-transfer",
|
||||
CONFIG_FILE_EXPIRE_RESERVE_NOW),
|
||||
config_file_expire_reserve_now),
|
||||
|
||||
TALER_TESTING_cmd_status ("short-lived-status",
|
||||
"short-lived-reserve",
|
||||
@ -837,7 +836,7 @@ run (void *cls,
|
||||
TALER_TESTING_cmd_revoke ("revoke-1-EUR:1",
|
||||
MHD_HTTP_OK,
|
||||
"recoup-withdraw-coin-2a",
|
||||
CONFIG_FILE),
|
||||
config_file),
|
||||
/* Check recoup is failing for the coin with the reused coin key */
|
||||
TALER_TESTING_cmd_recoup ("recoup-2x",
|
||||
MHD_HTTP_CONFLICT,
|
||||
@ -909,10 +908,10 @@ run (void *cls,
|
||||
"EUR:20");
|
||||
reserve_open_close[(i * RESERVE_OPEN_CLOSE_CHUNK) + 1]
|
||||
= TALER_TESTING_cmd_exec_wirewatch ("reserve-open-close-wirewatch",
|
||||
CONFIG_FILE_EXPIRE_RESERVE_NOW);
|
||||
config_file_expire_reserve_now);
|
||||
reserve_open_close[(i * RESERVE_OPEN_CLOSE_CHUNK) + 2]
|
||||
= TALER_TESTING_cmd_exec_closer ("reserve-open-close-aggregation",
|
||||
CONFIG_FILE_EXPIRE_RESERVE_NOW,
|
||||
config_file_expire_reserve_now,
|
||||
"EUR:19.99",
|
||||
"EUR:0.01",
|
||||
"reserve-open-close-key");
|
||||
@ -936,9 +935,9 @@ run (void *cls,
|
||||
MHD_HTTP_NO_CONTENT,
|
||||
false),
|
||||
TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys",
|
||||
CONFIG_FILE),
|
||||
config_file),
|
||||
TALER_TESTING_cmd_exec_offline_sign_fees ("offline-sign-fees",
|
||||
CONFIG_FILE,
|
||||
config_file,
|
||||
"EUR:0.01",
|
||||
"EUR:0.01"),
|
||||
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys",
|
||||
@ -978,25 +977,34 @@ int
|
||||
main (int argc,
|
||||
char *const *argv)
|
||||
{
|
||||
const char *cipher;
|
||||
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
/* These environment variables get in the way... */
|
||||
unsetenv ("XDG_DATA_HOME");
|
||||
unsetenv ("XDG_CONFIG_HOME");
|
||||
GNUNET_log_setup ("test-exchange-api",
|
||||
GNUNET_log_setup (argv[0],
|
||||
"INFO",
|
||||
NULL);
|
||||
cipher = GNUNET_TESTING_get_testname_from_underscore (argv[0]);
|
||||
GNUNET_assert (NULL != cipher);
|
||||
GNUNET_asprintf (&config_file,
|
||||
"test_exchange_api-%s.conf",
|
||||
cipher);
|
||||
GNUNET_asprintf (&config_file_expire_reserve_now,
|
||||
"test_exchange_api_expire_reserve_now-%s.conf",
|
||||
cipher);
|
||||
/* Check fakebank port is available and get config */
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_prepare_fakebank (CONFIG_FILE,
|
||||
TALER_TESTING_prepare_fakebank (config_file,
|
||||
"exchange-account-2",
|
||||
&bc))
|
||||
return 77;
|
||||
TALER_TESTING_cleanup_files (CONFIG_FILE);
|
||||
TALER_TESTING_cleanup_files (config_file);
|
||||
/* @helpers. Run keyup, create tables, ... Note: it
|
||||
* fetches the port number from config in order to see
|
||||
* if it's available. */
|
||||
switch (TALER_TESTING_prepare_exchange (CONFIG_FILE,
|
||||
switch (TALER_TESTING_prepare_exchange (config_file,
|
||||
GNUNET_YES,
|
||||
&ec))
|
||||
{
|
||||
@ -1013,7 +1021,7 @@ main (int argc,
|
||||
*/
|
||||
TALER_TESTING_setup_with_exchange (&run,
|
||||
NULL,
|
||||
CONFIG_FILE))
|
||||
config_file))
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
|
98
src/testing/test_exchange_api_keys_cherry_picking-cs.conf
Normal file
98
src/testing/test_exchange_api_keys_cherry_picking-cs.conf
Normal file
@ -0,0 +1,98 @@
|
||||
# This file is in the public domain.
|
||||
#
|
||||
[PATHS]
|
||||
# Persistent data storage for the testcase
|
||||
TALER_TEST_HOME = test_exchange_api_keys_cherry_picking_home/
|
||||
TALER_RUNTIME_DIR = ${TMPDIR:-${TMP:-/tmp}}/${USER:-}/taler-system-runtime/
|
||||
|
||||
# Persistent data storage
|
||||
TALER_DATA_HOME = $TALER_HOME/.local/share/taler/
|
||||
|
||||
# Configuration files
|
||||
TALER_CONFIG_HOME = $TALER_HOME/.config/taler/
|
||||
|
||||
# Cached data, no big deal if lost
|
||||
TALER_CACHE_HOME = $TALER_HOME/.cache/taler/
|
||||
|
||||
[taler]
|
||||
# Currency supported by the exchange (can only be one)
|
||||
CURRENCY = EUR
|
||||
|
||||
[taler-exchange-secmod-cs]
|
||||
# Reduce from 1 year to speed up test
|
||||
LOOKAHEAD_SIGN = 24 days
|
||||
|
||||
[taler-exchange-secmod-eddsa]
|
||||
# Reduce from 1 year to speed up test
|
||||
LOOKAHEAD_SIGN = 24 days
|
||||
# Reduce from 12 weeks to ensure we have multiple
|
||||
DURATION = 14 days
|
||||
|
||||
[auditor]
|
||||
BASE_URL = "http://localhost:8083/"
|
||||
|
||||
# HTTP port the auditor listens to
|
||||
PORT = 8083
|
||||
|
||||
[exchange]
|
||||
# HTTP port the exchange listens to
|
||||
PORT = 8081
|
||||
|
||||
# Master public key used to sign the exchange's various keys
|
||||
MASTER_PUBLIC_KEY = 98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG
|
||||
|
||||
# How to access our database
|
||||
DB = postgres
|
||||
|
||||
# Base URL of the exchange. Must be set to a URL where the
|
||||
# exchange (or the twister) is actually listening.
|
||||
BASE_URL = "http://localhost:8081/"
|
||||
|
||||
|
||||
[exchangedb-postgres]
|
||||
CONFIG = "postgres:///talercheck"
|
||||
|
||||
[auditordb-postgres]
|
||||
CONFIG = "postgres:///talercheck"
|
||||
|
||||
[exchange-account-1]
|
||||
PAYTO_URI = payto://x-taler-bank/localhost/42
|
||||
|
||||
[exchange-accountcredentials-1]
|
||||
WIRE_GATEWAY_URL = "http://localhost:9082/42/"
|
||||
|
||||
[exchange-account-2]
|
||||
PAYTO_URI = payto://x-taler-bank/localhost/2
|
||||
ENABLE_DEBIT = YES
|
||||
ENABLE_CREDIT = YES
|
||||
|
||||
[exchange-accountcredentials-2]
|
||||
WIRE_GATEWAY_URL = "http://localhost:9082/2/"
|
||||
|
||||
# Authentication information for basic authentication
|
||||
TALER_BANK_AUTH_METHOD = "basic"
|
||||
USERNAME = user
|
||||
PASSWORD = pass
|
||||
|
||||
[bank]
|
||||
HTTP_PORT=8082
|
||||
|
||||
[taler-exchange-secmod-cs]
|
||||
OVERLAP_DURATION = 1 s
|
||||
LOOKAHEAD_SIGN = 20 s
|
||||
|
||||
[taler-exchange-secmod-eddsa]
|
||||
OVERLAP_DURATION = 1 s
|
||||
DURATION = 30 s
|
||||
LOOKAHEAD_SIGN = 20 s
|
||||
|
||||
[coin_eur_1]
|
||||
value = EUR:1
|
||||
duration_withdraw = 5 s
|
||||
duration_spend = 6 s
|
||||
duration_legal = 7 s
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
@ -95,4 +95,5 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
@ -29,6 +29,7 @@ lished
|
||||
#include "taler_exchange_service.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include <gnunet/gnunet_testing_lib.h>
|
||||
#include <microhttpd.h>
|
||||
#include "taler_bank_service.h"
|
||||
#include "taler_fakebank_lib.h"
|
||||
@ -39,7 +40,7 @@ lished
|
||||
* Configuration file we use. One (big) configuration is used
|
||||
* for the various components for this test.
|
||||
*/
|
||||
#define CONFIG_FILE "test_exchange_api_keys_cherry_picking.conf"
|
||||
static char *config_file;
|
||||
|
||||
/**
|
||||
* Exchange configuration data.
|
||||
@ -66,11 +67,11 @@ run (void *cls,
|
||||
MHD_HTTP_NO_CONTENT,
|
||||
false),
|
||||
TALER_TESTING_cmd_exec_offline_sign_fees ("offline-sign-fees",
|
||||
CONFIG_FILE,
|
||||
config_file,
|
||||
"EUR:0.01",
|
||||
"EUR:0.01"),
|
||||
TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys",
|
||||
CONFIG_FILE),
|
||||
config_file),
|
||||
TALER_TESTING_cmd_check_keys_pull_all_keys ("initial-/keys",
|
||||
1),
|
||||
TALER_TESTING_cmd_sleep ("sleep",
|
||||
@ -109,19 +110,25 @@ int
|
||||
main (int argc,
|
||||
char *const *argv)
|
||||
{
|
||||
const char *cipher;
|
||||
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
/* These environment variables get in the way... */
|
||||
unsetenv ("XDG_DATA_HOME");
|
||||
unsetenv ("XDG_CONFIG_HOME");
|
||||
GNUNET_log_setup ("test-exchange-api-cherry-picking",
|
||||
GNUNET_log_setup (argv[0],
|
||||
"DEBUG",
|
||||
NULL);
|
||||
TALER_TESTING_cleanup_files (CONFIG_FILE);
|
||||
cipher = GNUNET_TESTING_get_testname_from_underscore (argv[0]);
|
||||
GNUNET_assert (NULL != cipher);
|
||||
GNUNET_asprintf (&config_file,
|
||||
"test_exchange_api_keys_cherry_picking-%s.conf",
|
||||
cipher);
|
||||
TALER_TESTING_cleanup_files (config_file);
|
||||
/* @helpers. Run keyup, create tables, ... Note: it
|
||||
* fetches the port number from config in order to see
|
||||
* if it's available. */
|
||||
switch (TALER_TESTING_prepare_exchange (CONFIG_FILE,
|
||||
switch (TALER_TESTING_prepare_exchange (config_file,
|
||||
GNUNET_YES,
|
||||
&ec))
|
||||
{
|
||||
@ -138,7 +145,7 @@ main (int argc,
|
||||
*/
|
||||
TALER_TESTING_setup_with_exchange (&run,
|
||||
NULL,
|
||||
CONFIG_FILE))
|
||||
config_file))
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "taler_exchange_service.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include <gnunet/gnunet_testing_lib.h>
|
||||
#include <microhttpd.h>
|
||||
#include "taler_bank_service.h"
|
||||
#include "taler_fakebank_lib.h"
|
||||
@ -40,7 +41,7 @@
|
||||
* Configuration file we use. One (big) configuration is used
|
||||
* for the various components for this test.
|
||||
*/
|
||||
#define CONFIG_FILE "test_exchange_api_keys_cherry_picking.conf"
|
||||
static char *config_file;
|
||||
|
||||
/**
|
||||
* Exchange configuration data.
|
||||
@ -67,7 +68,7 @@ run (void *cls,
|
||||
MHD_HTTP_NO_CONTENT,
|
||||
false),
|
||||
TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys",
|
||||
CONFIG_FILE),
|
||||
config_file),
|
||||
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys",
|
||||
1),
|
||||
TALER_TESTING_cmd_check_keys ("first-download",
|
||||
@ -89,18 +90,25 @@ int
|
||||
main (int argc,
|
||||
char *const *argv)
|
||||
{
|
||||
const char *cipher;
|
||||
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
/* These environment variables get in the way... */
|
||||
unsetenv ("XDG_DATA_HOME");
|
||||
unsetenv ("XDG_CONFIG_HOME");
|
||||
GNUNET_log_setup ("test-exchange-api-overlapping-keys-bug",
|
||||
"DEBUG", NULL);
|
||||
TALER_TESTING_cleanup_files (CONFIG_FILE);
|
||||
GNUNET_log_setup (argv[0],
|
||||
"DEBUG",
|
||||
NULL);
|
||||
cipher = GNUNET_TESTING_get_testname_from_underscore (argv[0]);
|
||||
GNUNET_assert (NULL != cipher);
|
||||
GNUNET_asprintf (&config_file,
|
||||
"test_exchange_api_keys_cherry_picking-%s.conf",
|
||||
cipher);
|
||||
TALER_TESTING_cleanup_files (config_file);
|
||||
/* @helpers. Run keyup, create tables, ... Note: it
|
||||
* fetches the port number from config in order to see
|
||||
* if it's available. */
|
||||
switch (TALER_TESTING_prepare_exchange (CONFIG_FILE,
|
||||
switch (TALER_TESTING_prepare_exchange (config_file,
|
||||
GNUNET_YES,
|
||||
&ec))
|
||||
{
|
||||
@ -117,7 +125,7 @@ main (int argc,
|
||||
*/
|
||||
TALER_TESTING_setup_with_exchange (&run,
|
||||
NULL,
|
||||
CONFIG_FILE))
|
||||
config_file))
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "taler_exchange_service.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include <gnunet/gnunet_testing_lib.h>
|
||||
#include <microhttpd.h>
|
||||
#include "taler_bank_service.h"
|
||||
#include "taler_fakebank_lib.h"
|
||||
@ -38,7 +39,7 @@
|
||||
* Configuration file we use. One (big) configuration is used
|
||||
* for the various components for this test.
|
||||
*/
|
||||
#define CONFIG_FILE "test_exchange_api.conf"
|
||||
static char *config_file;
|
||||
|
||||
/**
|
||||
* Exchange configuration data.
|
||||
@ -70,7 +71,7 @@ run (void *cls,
|
||||
MHD_HTTP_NO_CONTENT,
|
||||
false),
|
||||
TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys",
|
||||
CONFIG_FILE),
|
||||
config_file),
|
||||
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys",
|
||||
1),
|
||||
/**
|
||||
@ -90,7 +91,7 @@ run (void *cls,
|
||||
* Run wire-watch to trigger the reserve creation.
|
||||
*/
|
||||
TALER_TESTING_cmd_exec_wirewatch ("wirewatch-4",
|
||||
CONFIG_FILE),
|
||||
config_file),
|
||||
/* Withdraw a 5 EUR coin, at fee of 1 ct */
|
||||
TALER_TESTING_cmd_withdraw_amount ("withdraw-revocation-coin-1",
|
||||
"create-reserve-1",
|
||||
@ -144,12 +145,12 @@ run (void *cls,
|
||||
TALER_TESTING_cmd_revoke ("revoke-2-EUR:5",
|
||||
MHD_HTTP_OK,
|
||||
"refresh-melt-1",
|
||||
CONFIG_FILE),
|
||||
config_file),
|
||||
/* Also make fully spent coin invalid (should be same denom) */
|
||||
TALER_TESTING_cmd_revoke ("revoke-2-EUR:5",
|
||||
MHD_HTTP_OK,
|
||||
"withdraw-revocation-coin-2",
|
||||
CONFIG_FILE),
|
||||
config_file),
|
||||
/* Refund fully spent coin (which should fail) */
|
||||
TALER_TESTING_cmd_recoup ("recoup-fully-spent",
|
||||
MHD_HTTP_CONFLICT,
|
||||
@ -211,12 +212,12 @@ run (void *cls,
|
||||
TALER_TESTING_cmd_revoke ("revoke-3-EUR:0.1",
|
||||
MHD_HTTP_OK,
|
||||
"refresh-reveal-2",
|
||||
CONFIG_FILE),
|
||||
config_file),
|
||||
/* Revoke also original coin denomination */
|
||||
TALER_TESTING_cmd_revoke ("revoke-4-EUR:5",
|
||||
MHD_HTTP_OK,
|
||||
"withdraw-revocation-coin-1",
|
||||
CONFIG_FILE),
|
||||
config_file),
|
||||
/* Refund coin EUR:0.1 to original coin, creating zombie! */
|
||||
TALER_TESTING_cmd_recoup_refresh ("recoup-2",
|
||||
MHD_HTTP_OK,
|
||||
@ -248,25 +249,31 @@ int
|
||||
main (int argc,
|
||||
char *const *argv)
|
||||
{
|
||||
const char *cipher;
|
||||
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
/* These environment variables get in the way... */
|
||||
unsetenv ("XDG_DATA_HOME");
|
||||
unsetenv ("XDG_CONFIG_HOME");
|
||||
GNUNET_log_setup ("test-exchange-api-revocation",
|
||||
GNUNET_log_setup (argv[0],
|
||||
"INFO",
|
||||
NULL);
|
||||
cipher = GNUNET_TESTING_get_testname_from_underscore (argv[0]);
|
||||
GNUNET_assert (NULL != cipher);
|
||||
GNUNET_asprintf (&config_file,
|
||||
"test_exchange_api-%s.conf",
|
||||
cipher);
|
||||
/* Check fakebank port is available and get config */
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_prepare_fakebank (CONFIG_FILE,
|
||||
TALER_TESTING_prepare_fakebank (config_file,
|
||||
"exchange-account-2",
|
||||
&bc))
|
||||
return 77;
|
||||
TALER_TESTING_cleanup_files (CONFIG_FILE);
|
||||
TALER_TESTING_cleanup_files (config_file);
|
||||
/* @helpers. Run keyup, create tables, ... Note: it
|
||||
* fetches the port number from config in order to see
|
||||
* if it's available. */
|
||||
switch (TALER_TESTING_prepare_exchange (CONFIG_FILE,
|
||||
switch (TALER_TESTING_prepare_exchange (config_file,
|
||||
GNUNET_YES,
|
||||
&ec))
|
||||
{
|
||||
@ -283,7 +290,7 @@ main (int argc,
|
||||
*/
|
||||
TALER_TESTING_setup_with_exchange (&run,
|
||||
NULL,
|
||||
CONFIG_FILE))
|
||||
config_file))
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "taler_exchange_service.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include <gnunet/gnunet_testing_lib.h>
|
||||
#include <microhttpd.h>
|
||||
#include "taler_bank_service.h"
|
||||
#include "taler_fakebank_lib.h"
|
||||
@ -40,7 +41,7 @@
|
||||
* Configuration file we use. One (big) configuration is used
|
||||
* for the various components for this test.
|
||||
*/
|
||||
#define CONFIG_FILE "test_exchange_api_twisted.conf"
|
||||
static char *config_file;
|
||||
|
||||
/**
|
||||
* (real) Twister URL. Used at startup time to check if it runs.
|
||||
@ -73,7 +74,7 @@ static struct TALER_TESTING_Command
|
||||
CMD_EXEC_WIREWATCH (const char *label)
|
||||
{
|
||||
return TALER_TESTING_cmd_exec_wirewatch (label,
|
||||
CONFIG_FILE);
|
||||
config_file);
|
||||
}
|
||||
|
||||
|
||||
@ -142,7 +143,7 @@ run (void *cls,
|
||||
NULL),
|
||||
/* Trigger 409 Conflict. */
|
||||
TALER_TESTING_cmd_flip_upload ("flip-upload",
|
||||
CONFIG_FILE,
|
||||
config_file,
|
||||
"transfer_privs.0"),
|
||||
TALER_TESTING_cmd_refresh_reveal ("refresh-(flipped-)reveal",
|
||||
"refresh-melt",
|
||||
@ -178,7 +179,7 @@ run (void *cls,
|
||||
"USD:5",
|
||||
"deposit-refund-1"),
|
||||
TALER_TESTING_cmd_flip_upload ("flip-upload",
|
||||
CONFIG_FILE,
|
||||
config_file,
|
||||
"merchant_sig"),
|
||||
TALER_TESTING_cmd_refund ("refund-bad-sig",
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
@ -217,7 +218,7 @@ run (void *cls,
|
||||
*/
|
||||
struct TALER_TESTING_Command expired_keys[] = {
|
||||
TALER_TESTING_cmd_modify_header_dl ("modify-expiration",
|
||||
CONFIG_FILE,
|
||||
config_file,
|
||||
MHD_HTTP_HEADER_EXPIRES,
|
||||
"Wed, 19 Jan 586524 08:01:49 GMT"),
|
||||
TALER_TESTING_cmd_check_keys_pull_all_keys (
|
||||
@ -243,7 +244,7 @@ run (void *cls,
|
||||
MHD_HTTP_NO_CONTENT,
|
||||
false),
|
||||
TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys",
|
||||
CONFIG_FILE),
|
||||
config_file),
|
||||
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys",
|
||||
1),
|
||||
TALER_TESTING_cmd_batch ("refresh-reveal-409-conflict",
|
||||
@ -283,26 +284,31 @@ int
|
||||
main (int argc,
|
||||
char *const *argv)
|
||||
{
|
||||
const char *cipher;
|
||||
int ret;
|
||||
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
/* These environment variables get in the way... */
|
||||
unsetenv ("XDG_DATA_HOME");
|
||||
unsetenv ("XDG_CONFIG_HOME");
|
||||
GNUNET_log_setup ("test-exchange-api-twisted",
|
||||
GNUNET_log_setup (argv[0],
|
||||
"DEBUG",
|
||||
NULL);
|
||||
cipher = GNUNET_TESTING_get_testname_from_underscore (argv[0]);
|
||||
GNUNET_assert (NULL != cipher);
|
||||
GNUNET_asprintf (&config_file,
|
||||
"test_exchange_api_twisted-%s.conf",
|
||||
cipher);
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_prepare_fakebank (CONFIG_FILE,
|
||||
TALER_TESTING_prepare_fakebank (config_file,
|
||||
"exchange-account-2",
|
||||
&bc))
|
||||
return 77;
|
||||
if (NULL == (twister_url = TALER_TWISTER_prepare_twister
|
||||
(CONFIG_FILE)))
|
||||
(config_file)))
|
||||
return 77;
|
||||
TALER_TESTING_cleanup_files (CONFIG_FILE);
|
||||
switch (TALER_TESTING_prepare_exchange (CONFIG_FILE,
|
||||
TALER_TESTING_cleanup_files (config_file);
|
||||
switch (TALER_TESTING_prepare_exchange (config_file,
|
||||
GNUNET_YES,
|
||||
&ec))
|
||||
{
|
||||
@ -312,11 +318,11 @@ main (int argc,
|
||||
case GNUNET_NO:
|
||||
return 77;
|
||||
case GNUNET_OK:
|
||||
if (NULL == (twisterd = TALER_TWISTER_run_twister (CONFIG_FILE)))
|
||||
if (NULL == (twisterd = TALER_TWISTER_run_twister (config_file)))
|
||||
return 77;
|
||||
ret = TALER_TESTING_setup_with_exchange (&run,
|
||||
NULL,
|
||||
CONFIG_FILE);
|
||||
config_file);
|
||||
purge_process (twisterd);
|
||||
GNUNET_free (twister_url);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2020 Taler Systems SA
|
||||
Copyright (C) 2020-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
@ -25,6 +25,7 @@
|
||||
#include "taler_util.h"
|
||||
#include "taler_exchange_service.h"
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include <gnunet/gnunet_testing_lib.h>
|
||||
#include <microhttpd.h>
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
@ -32,7 +33,7 @@
|
||||
* Configuration file we use. One (big) configuration is used
|
||||
* for the various components for this test.
|
||||
*/
|
||||
#define CONFIG_FILE "test_exchange_api.conf"
|
||||
static char *config_file;
|
||||
|
||||
|
||||
/**
|
||||
@ -139,7 +140,7 @@ run (void *cls,
|
||||
MHD_HTTP_NO_CONTENT,
|
||||
false),
|
||||
TALER_TESTING_cmd_exec_offline_sign_keys ("download-future-keys",
|
||||
CONFIG_FILE),
|
||||
config_file),
|
||||
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys",
|
||||
1),
|
||||
TALER_TESTING_cmd_end ()
|
||||
@ -156,25 +157,31 @@ int
|
||||
main (int argc,
|
||||
char *const *argv)
|
||||
{
|
||||
const char *cipher;
|
||||
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
/* These environment variables get in the way... */
|
||||
unsetenv ("XDG_DATA_HOME");
|
||||
unsetenv ("XDG_CONFIG_HOME");
|
||||
GNUNET_log_setup ("test-exchange-management-api",
|
||||
GNUNET_log_setup (argv[0],
|
||||
"INFO",
|
||||
NULL);
|
||||
/* Check fakebank port is available and get config */
|
||||
cipher = GNUNET_TESTING_get_testname_from_underscore (argv[0]);
|
||||
GNUNET_assert (NULL != cipher);
|
||||
GNUNET_asprintf (&config_file,
|
||||
"test_exchange_api-%s.conf",
|
||||
cipher);
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_prepare_fakebank (CONFIG_FILE,
|
||||
TALER_TESTING_prepare_fakebank (config_file,
|
||||
"exchange-account-2",
|
||||
&bc))
|
||||
return 77;
|
||||
TALER_TESTING_cleanup_files (CONFIG_FILE);
|
||||
TALER_TESTING_cleanup_files (config_file);
|
||||
/* @helpers. Create tables, ... Note: it
|
||||
* fetches the port number from config in order to see
|
||||
* if it's available. */
|
||||
switch (TALER_TESTING_prepare_exchange (CONFIG_FILE,
|
||||
switch (TALER_TESTING_prepare_exchange (config_file,
|
||||
GNUNET_YES, /* reset DB? */
|
||||
&ec))
|
||||
{
|
||||
@ -191,7 +198,7 @@ main (int argc,
|
||||
*/
|
||||
TALER_TESTING_setup_with_exchange (&run,
|
||||
NULL,
|
||||
CONFIG_FILE))
|
||||
config_file))
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
|
@ -110,8 +110,20 @@ fee_withdraw = EUR:0.00
|
||||
fee_deposit = EUR:0.00
|
||||
fee_refresh = EUR:0.01
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_eur_ct_2]
|
||||
value = EUR:0.01
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.00
|
||||
fee_deposit = EUR:0.00
|
||||
fee_refresh = EUR:0.01
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_ct_10]
|
||||
value = EUR:0.10
|
||||
duration_withdraw = 7 days
|
||||
@ -121,8 +133,20 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_eur_ct_11]
|
||||
value = EUR:0.10
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_1]
|
||||
value = EUR:1
|
||||
duration_withdraw = 7 days
|
||||
@ -132,8 +156,20 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_eur_2]
|
||||
value = EUR:1
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_5]
|
||||
value = EUR:5
|
||||
duration_withdraw = 7 days
|
||||
@ -143,8 +179,20 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_eur_6]
|
||||
value = EUR:5
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
||||
|
||||
[coin_eur_10]
|
||||
value = EUR:10
|
||||
duration_withdraw = 7 days
|
||||
@ -154,4 +202,16 @@ fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = RSA
|
||||
rsa_keysize = 1024
|
||||
|
||||
[coin_eur_11]
|
||||
value = EUR:10
|
||||
duration_withdraw = 7 days
|
||||
duration_spend = 2 years
|
||||
duration_legal = 3 years
|
||||
fee_withdraw = EUR:0.01
|
||||
fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
CIPHER = CS
|
@ -293,7 +293,7 @@ deposit_run (void *cls,
|
||||
struct TALER_MerchantPublicKeyP merchant_pub;
|
||||
struct TALER_PrivateContractHash h_contract_terms;
|
||||
enum TALER_ErrorCode ec;
|
||||
struct TALER_WireSalt wire_salt;
|
||||
struct TALER_WireSaltP wire_salt;
|
||||
const char *payto_uri;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_string ("payto_uri",
|
||||
|
@ -201,23 +201,27 @@ insert_deposit_run (void *cls,
|
||||
struct TALER_CoinPubHash c_hash;
|
||||
struct TALER_PlanchetDetail pd;
|
||||
struct TALER_BlindedDenominationSignature bds;
|
||||
struct TALER_PlanchetSecretsP ps;
|
||||
struct TALER_ExchangeWithdrawValues alg_values;
|
||||
union TALER_DenominationBlindingKeyP bks;
|
||||
|
||||
TALER_blinding_secret_create (&bks);
|
||||
alg_values.cipher = TALER_DENOMINATION_RSA;
|
||||
TALER_planchet_blinding_secret_create (&ps,
|
||||
&alg_values,
|
||||
&bks);
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_denom_blind (&dpk,
|
||||
&bks,
|
||||
NULL, /* FIXME-Oec */
|
||||
&deposit.coin.coin_pub,
|
||||
&alg_values,
|
||||
&c_hash,
|
||||
&pd.coin_ev,
|
||||
&pd.coin_ev_size));
|
||||
&pd.blinded_planchet));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_denom_sign_blinded (&bds,
|
||||
&denom_priv,
|
||||
pd.coin_ev,
|
||||
pd.coin_ev_size));
|
||||
GNUNET_free (pd.coin_ev);
|
||||
&pd.blinded_planchet));
|
||||
TALER_blinded_planchet_free (&pd.blinded_planchet);
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_denom_sig_unblind (&deposit.coin.denom_sig,
|
||||
&bds,
|
||||
|
@ -237,12 +237,12 @@ recoup_run (void *cls,
|
||||
struct RecoupState *ps = cls;
|
||||
const struct TALER_TESTING_Command *coin_cmd;
|
||||
const struct TALER_CoinSpendPrivateKeyP *coin_priv;
|
||||
const union TALER_DenominationBlindingKeyP *blinding_key;
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *denom_pub;
|
||||
const struct TALER_DenominationSignature *coin_sig;
|
||||
struct TALER_PlanchetSecretsP planchet;
|
||||
const struct TALER_PlanchetSecretsP *planchet;
|
||||
char *cref;
|
||||
unsigned int idx;
|
||||
const struct TALER_ExchangeWithdrawValues *ewv;
|
||||
|
||||
ps->is = is;
|
||||
if (GNUNET_OK !=
|
||||
@ -264,7 +264,6 @@ recoup_run (void *cls,
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_get_trait_coin_priv (coin_cmd,
|
||||
idx,
|
||||
@ -274,18 +273,23 @@ recoup_run (void *cls,
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_get_trait_blinding_key (coin_cmd,
|
||||
TALER_TESTING_get_trait_exchange_wd_value (coin_cmd,
|
||||
idx,
|
||||
&blinding_key))
|
||||
&ewv))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_get_trait_planchet_secret (coin_cmd,
|
||||
&planchet))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
planchet.coin_priv = *coin_priv;
|
||||
planchet.blinding_key = *blinding_key;
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (
|
||||
&coin_priv->eddsa_priv,
|
||||
&ps->reserve_history.details.recoup_details.coin_pub.eddsa_pub);
|
||||
@ -299,7 +303,6 @@ recoup_run (void *cls,
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_get_trait_denom_sig (coin_cmd,
|
||||
idx,
|
||||
@ -309,15 +312,14 @@ recoup_run (void *cls,
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Trying to recoup denomination '%s'\n",
|
||||
TALER_B2S (&denom_pub->h_key));
|
||||
|
||||
ps->ph = TALER_EXCHANGE_recoup (is->exchange,
|
||||
denom_pub,
|
||||
coin_sig,
|
||||
&planchet,
|
||||
ewv,
|
||||
planchet,
|
||||
&recoup_cb,
|
||||
ps);
|
||||
GNUNET_assert (NULL != ps->ph);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2018 Taler Systems SA
|
||||
Copyright (C) 2014-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
@ -231,10 +231,10 @@ recoup_refresh_run (void *cls,
|
||||
struct RecoupRefreshState *ps = cls;
|
||||
const struct TALER_TESTING_Command *coin_cmd;
|
||||
const struct TALER_CoinSpendPrivateKeyP *coin_priv;
|
||||
const union TALER_DenominationBlindingKeyP *blinding_key;
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *denom_pub;
|
||||
const struct TALER_DenominationSignature *coin_sig;
|
||||
struct TALER_PlanchetSecretsP planchet;
|
||||
const struct TALER_PlanchetSecretsP *planchet;
|
||||
const struct TALER_ExchangeWithdrawValues *ewv;
|
||||
char *cref;
|
||||
unsigned int idx;
|
||||
|
||||
@ -258,7 +258,6 @@ recoup_refresh_run (void *cls,
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_get_trait_coin_priv (coin_cmd,
|
||||
idx,
|
||||
@ -268,18 +267,24 @@ recoup_refresh_run (void *cls,
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_get_trait_blinding_key (coin_cmd,
|
||||
TALER_TESTING_get_trait_exchange_wd_value (coin_cmd,
|
||||
idx,
|
||||
&blinding_key))
|
||||
&ewv))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_get_trait_planchet_secrets (coin_cmd,
|
||||
idx,
|
||||
&planchet))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
planchet.coin_priv = *coin_priv;
|
||||
planchet.blinding_key = *blinding_key;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_get_trait_denom_pub (coin_cmd,
|
||||
@ -308,8 +313,9 @@ recoup_refresh_run (void *cls,
|
||||
ps->ph = TALER_EXCHANGE_recoup_refresh (is->exchange,
|
||||
denom_pub,
|
||||
coin_sig,
|
||||
&planchet,
|
||||
recoup_refresh_cb,
|
||||
ewv,
|
||||
planchet,
|
||||
&recoup_refresh_cb,
|
||||
ps);
|
||||
GNUNET_assert (NULL != ps->ph);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2018-2020 Taler Systems SA
|
||||
Copyright (C) 2018-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
@ -91,9 +91,9 @@ struct RefreshMeltState
|
||||
const char *coin_reference;
|
||||
|
||||
/**
|
||||
* "Crypto data" used in the refresh operation.
|
||||
* Data used in the refresh operation.
|
||||
*/
|
||||
json_t *refresh_data;
|
||||
struct TALER_EXCHANGE_RefreshData refresh_data;
|
||||
|
||||
/**
|
||||
* Reference to a previous melt command.
|
||||
@ -116,6 +116,22 @@ struct RefreshMeltState
|
||||
*/
|
||||
struct TALER_EXCHANGE_DenomPublicKey *fresh_pks;
|
||||
|
||||
/**
|
||||
* Array of @a num_fresh_coins of exchange values contributed to the refresh operation
|
||||
*/
|
||||
struct TALER_ExchangeWithdrawValues *alg_values;
|
||||
|
||||
/**
|
||||
* Array of @a num_fresh_coins of blinding key secrets
|
||||
* created during the melt operation.
|
||||
*/
|
||||
union TALER_DenominationBlindingKeyP *bks;
|
||||
|
||||
/**
|
||||
* Entropy seed for the refresh-melt operation.
|
||||
*/
|
||||
struct TALER_PlanchetSecretsP ps;
|
||||
|
||||
/**
|
||||
* Private key of the dirty coin being melted.
|
||||
*/
|
||||
@ -162,7 +178,7 @@ struct RefreshMeltState
|
||||
* exchange to pick any previous /rerfesh/melt operation from
|
||||
* the database.
|
||||
*/
|
||||
unsigned int double_melt;
|
||||
bool double_melt;
|
||||
|
||||
/**
|
||||
* How often should we retry on (transient) failures?
|
||||
@ -337,7 +353,7 @@ static void
|
||||
reveal_cb (void *cls,
|
||||
const struct TALER_EXCHANGE_HttpResponse *hr,
|
||||
unsigned int num_coins,
|
||||
const struct TALER_PlanchetSecretsP *coin_privs,
|
||||
const struct TALER_CoinSpendPrivateKeyP *coin_privs,
|
||||
const struct TALER_DenominationSignature *sigs)
|
||||
{
|
||||
struct RefreshRevealState *rrs = cls;
|
||||
@ -402,6 +418,7 @@ reveal_cb (void *cls,
|
||||
for (unsigned int i = 0; i<num_coins; i++)
|
||||
{
|
||||
struct TALER_TESTING_FreshCoinData *fc = &rrs->fresh_coins[i];
|
||||
const union TALER_DenominationBlindingKeyP *bks;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_get_trait_denom_pub (melt_cmd,
|
||||
@ -412,8 +429,17 @@ reveal_cb (void *cls,
|
||||
TALER_TESTING_interpreter_fail (rrs->is);
|
||||
return;
|
||||
}
|
||||
fc->coin_priv = coin_privs[i].coin_priv;
|
||||
fc->blinding_key = coin_privs[i].blinding_key;
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_get_trait_blinding_key (melt_cmd,
|
||||
i,
|
||||
&bks))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rrs->is);
|
||||
return;
|
||||
}
|
||||
fc->coin_priv = coin_privs[i];
|
||||
fc->blinding_key = *bks;
|
||||
TALER_denom_sig_deep_copy (&fc->sig,
|
||||
&sigs[i]);
|
||||
}
|
||||
@ -461,9 +487,13 @@ refresh_reveal_run (void *cls,
|
||||
TALER_TESTING_interpreter_fail (rrs->is);
|
||||
return;
|
||||
}
|
||||
// FIXME: use trait for 'rms'!
|
||||
rms = melt_cmd->cls;
|
||||
rrs->rrh = TALER_EXCHANGE_refreshes_reveal (is->exchange,
|
||||
rms->refresh_data,
|
||||
&rms->ps,
|
||||
&rms->refresh_data,
|
||||
rms->num_fresh_coins,
|
||||
rms->alg_values,
|
||||
rms->noreveal_index,
|
||||
&reveal_cb,
|
||||
rrs);
|
||||
@ -763,6 +793,7 @@ refresh_link_run (void *cls,
|
||||
|
||||
/* find reserve_withdraw command */
|
||||
{
|
||||
// FIXME: use trait!
|
||||
rms = melt_cmd->cls;
|
||||
coin_cmd = TALER_TESTING_interpreter_lookup_command (rls->is,
|
||||
rms->coin_reference);
|
||||
@ -856,11 +887,6 @@ do_melt_retry (void *cls)
|
||||
rms->retry_task = NULL;
|
||||
rms->is->commands[rms->is->ip].last_req_time
|
||||
= GNUNET_TIME_absolute_get ();
|
||||
if (NULL != rms->refresh_data)
|
||||
{
|
||||
json_decref (rms->refresh_data);
|
||||
rms->refresh_data = NULL;
|
||||
}
|
||||
melt_run (rms,
|
||||
NULL,
|
||||
rms->is);
|
||||
@ -874,6 +900,9 @@ do_melt_retry (void *cls)
|
||||
*
|
||||
* @param cls closure.
|
||||
* @param hr HTTP response details
|
||||
* @param num_coins number of fresh coins to be created, length of the @a exchange_vals array, 0 if the operation failed
|
||||
* @param alg_values array @a num_coins of exchange values contributed to the refresh operation
|
||||
* @param bks array of @a num_coins blinding keys used to blind the fresh coins
|
||||
* @param noreveal_index choice by the exchange in the
|
||||
* cut-and-choose protocol, UINT16_MAX on error.
|
||||
* @param exchange_pub public key the exchange used for signing.
|
||||
@ -881,6 +910,9 @@ do_melt_retry (void *cls)
|
||||
static void
|
||||
melt_cb (void *cls,
|
||||
const struct TALER_EXCHANGE_HttpResponse *hr,
|
||||
unsigned int num_coins,
|
||||
const struct TALER_ExchangeWithdrawValues *alg_values,
|
||||
const union TALER_DenominationBlindingKeyP *bks,
|
||||
uint32_t noreveal_index,
|
||||
const struct TALER_ExchangePublicKeyP *exchange_pub)
|
||||
{
|
||||
@ -929,7 +961,27 @@ melt_cb (void *cls,
|
||||
TALER_TESTING_interpreter_fail (rms->is);
|
||||
return;
|
||||
}
|
||||
if (MHD_HTTP_OK == hr->http_status)
|
||||
{
|
||||
rms->noreveal_index = noreveal_index;
|
||||
if (num_coins != rms->num_fresh_coins)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rms->is);
|
||||
return;
|
||||
}
|
||||
GNUNET_free (rms->alg_values);
|
||||
rms->alg_values = GNUNET_new_array (num_coins,
|
||||
struct TALER_ExchangeWithdrawValues);
|
||||
memcpy (rms->alg_values,
|
||||
alg_values,
|
||||
num_coins * sizeof (struct TALER_ExchangeWithdrawValues));
|
||||
rms->bks = GNUNET_new_array (num_coins,
|
||||
union TALER_DenominationBlindingKeyP);
|
||||
memcpy (rms->bks,
|
||||
bks,
|
||||
num_coins * sizeof (union TALER_DenominationBlindingKeyP));
|
||||
}
|
||||
if (0 != rms->total_backoff.rel_value_us)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
@ -938,15 +990,16 @@ melt_cb (void *cls,
|
||||
GNUNET_STRINGS_relative_time_to_string (rms->total_backoff,
|
||||
GNUNET_YES));
|
||||
}
|
||||
if (GNUNET_YES == rms->double_melt)
|
||||
if (rms->double_melt)
|
||||
{
|
||||
TALER_LOG_DEBUG ("Doubling the melt (%s)\n",
|
||||
rms->is->commands[rms->is->ip].label);
|
||||
rms->rmh = TALER_EXCHANGE_melt (rms->is->exchange,
|
||||
rms->refresh_data,
|
||||
&rms->ps,
|
||||
&rms->refresh_data,
|
||||
&melt_cb,
|
||||
rms);
|
||||
rms->double_melt = GNUNET_NO;
|
||||
rms->double_melt = false;
|
||||
return;
|
||||
}
|
||||
TALER_TESTING_interpreter_next (rms->is);
|
||||
@ -978,13 +1031,14 @@ melt_run (void *cls,
|
||||
melt_fresh_amounts = default_melt_fresh_amounts;
|
||||
rms->is = is;
|
||||
rms->noreveal_index = UINT16_MAX;
|
||||
TALER_planchet_setup_random (&rms->ps);
|
||||
for (num_fresh_coins = 0;
|
||||
NULL != melt_fresh_amounts[num_fresh_coins];
|
||||
num_fresh_coins++)
|
||||
;
|
||||
rms->num_fresh_coins = num_fresh_coins;
|
||||
rms->fresh_pks = GNUNET_new_array
|
||||
(num_fresh_coins,
|
||||
rms->fresh_pks = GNUNET_new_array (
|
||||
num_fresh_coins,
|
||||
struct TALER_EXCHANGE_DenomPublicKey);
|
||||
{
|
||||
struct TALER_Amount melt_amount;
|
||||
@ -994,8 +1048,9 @@ melt_run (void *cls,
|
||||
const struct TALER_TESTING_Command *coin_command;
|
||||
|
||||
if (NULL == (coin_command
|
||||
= TALER_TESTING_interpreter_lookup_command
|
||||
(is, rms->coin_reference)))
|
||||
= TALER_TESTING_interpreter_lookup_command (
|
||||
is,
|
||||
rms->coin_reference)))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rms->is);
|
||||
@ -1011,7 +1066,6 @@ melt_run (void *cls,
|
||||
TALER_TESTING_interpreter_fail (rms->is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_get_trait_denom_sig (coin_command,
|
||||
0,
|
||||
@ -1044,12 +1098,13 @@ melt_run (void *cls,
|
||||
GNUNET_break (0);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to parse amount `%s' at index %u\n",
|
||||
melt_fresh_amounts[i], i);
|
||||
melt_fresh_amounts[i],
|
||||
i);
|
||||
TALER_TESTING_interpreter_fail (rms->is);
|
||||
return;
|
||||
}
|
||||
fresh_pk = TALER_TESTING_find_pk
|
||||
(TALER_EXCHANGE_get_keys (is->exchange), &fresh_amount);
|
||||
fresh_pk = TALER_TESTING_find_pk (TALER_EXCHANGE_get_keys (is->exchange),
|
||||
&fresh_amount);
|
||||
if (NULL == fresh_pk)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
@ -1070,22 +1125,15 @@ melt_run (void *cls,
|
||||
TALER_denom_pub_deep_copy (&rms->fresh_pks[i].key,
|
||||
&fresh_pk->key);
|
||||
} /* end for */
|
||||
GNUNET_assert (NULL == rms->refresh_data);
|
||||
rms->refresh_data
|
||||
= TALER_EXCHANGE_refresh_prepare (rms->melt_priv,
|
||||
&melt_amount,
|
||||
melt_sig,
|
||||
melt_denom_pub,
|
||||
num_fresh_coins,
|
||||
rms->fresh_pks);
|
||||
if (NULL == rms->refresh_data)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rms->is);
|
||||
return;
|
||||
}
|
||||
rms->refresh_data.melt_priv = *rms->melt_priv;
|
||||
rms->refresh_data.melt_amount = melt_amount;
|
||||
rms->refresh_data.melt_sig = *melt_sig;
|
||||
rms->refresh_data.melt_pk = *melt_denom_pub;
|
||||
rms->refresh_data.fresh_pks = rms->fresh_pks;
|
||||
rms->refresh_data.fresh_pks_len = num_fresh_coins;
|
||||
rms->rmh = TALER_EXCHANGE_melt (is->exchange,
|
||||
rms->refresh_data,
|
||||
&rms->ps,
|
||||
&rms->refresh_data,
|
||||
&melt_cb,
|
||||
rms);
|
||||
|
||||
@ -1117,7 +1165,8 @@ melt_cleanup (void *cls,
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Command %u (%s) did not complete\n",
|
||||
rms->is->ip, rms->is->commands[rms->is->ip].label);
|
||||
rms->is->ip,
|
||||
rms->is->commands[rms->is->ip].label);
|
||||
TALER_EXCHANGE_melt_cancel (rms->rmh);
|
||||
rms->rmh = NULL;
|
||||
}
|
||||
@ -1130,11 +1179,10 @@ melt_cleanup (void *cls,
|
||||
{
|
||||
for (unsigned int i = 0; i < rms->num_fresh_coins; i++)
|
||||
TALER_denom_pub_free (&rms->fresh_pks[i].key);
|
||||
}
|
||||
GNUNET_free (rms->fresh_pks);
|
||||
rms->fresh_pks = NULL;
|
||||
json_decref (rms->refresh_data);
|
||||
rms->refresh_data = NULL;
|
||||
}
|
||||
GNUNET_free (rms->alg_values);
|
||||
GNUNET_free (rms->bks);
|
||||
GNUNET_free (rms->melt_fresh_amounts);
|
||||
GNUNET_free (rms);
|
||||
}
|
||||
@ -1168,6 +1216,9 @@ melt_traits (void *cls,
|
||||
&rms->fresh_pks[index]),
|
||||
TALER_TESTING_make_trait_coin_priv (0,
|
||||
rms->melt_priv),
|
||||
// ????
|
||||
TALER_TESTING_make_trait_blinding_key (index,
|
||||
&rms->bks[index]),
|
||||
TALER_TESTING_trait_end ()
|
||||
};
|
||||
|
||||
@ -1241,7 +1292,8 @@ TALER_TESTING_cmd_melt (const char *label,
|
||||
rms = GNUNET_new (struct RefreshMeltState);
|
||||
rms->coin_reference = coin_reference;
|
||||
rms->expected_response_code = expected_response_code;
|
||||
va_start (ap, expected_response_code);
|
||||
va_start (ap,
|
||||
expected_response_code);
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
parse_amounts (rms, ap));
|
||||
va_end (ap);
|
||||
@ -1271,8 +1323,9 @@ TALER_TESTING_cmd_melt_double (const char *label,
|
||||
rms = GNUNET_new (struct RefreshMeltState);
|
||||
rms->coin_reference = coin_reference;
|
||||
rms->expected_response_code = expected_response_code;
|
||||
rms->double_melt = GNUNET_YES;
|
||||
va_start (ap, expected_response_code);
|
||||
rms->double_melt = true;
|
||||
va_start (ap,
|
||||
expected_response_code);
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
parse_amounts (rms, ap));
|
||||
va_end (ap);
|
||||
|
@ -99,6 +99,22 @@ struct WithdrawState
|
||||
*/
|
||||
struct TALER_ReservePublicKeyP reserve_pub;
|
||||
|
||||
/**
|
||||
* Private key of the coin.
|
||||
*/
|
||||
struct TALER_CoinSpendPrivateKeyP coin_priv;
|
||||
|
||||
/**
|
||||
* Blinding key used during the operation.
|
||||
*/
|
||||
union TALER_DenominationBlindingKeyP bks;
|
||||
|
||||
/**
|
||||
* Values contributed from the exchange during the
|
||||
* withdraw protocol.
|
||||
*/
|
||||
struct TALER_ExchangeWithdrawValues exchange_vals;
|
||||
|
||||
/**
|
||||
* Interpreter state (during command).
|
||||
*/
|
||||
@ -263,6 +279,9 @@ reserve_withdraw_cb (void *cls,
|
||||
case MHD_HTTP_OK:
|
||||
TALER_denom_sig_deep_copy (&ws->sig,
|
||||
&wr->details.success.sig);
|
||||
ws->coin_priv = wr->details.success.coin_priv;
|
||||
ws->bks = wr->details.success.bks;
|
||||
ws->exchange_vals = wr->details.success.exchange_vals;
|
||||
if (0 != ws->total_backoff.rel_value_us)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
@ -392,7 +411,7 @@ withdraw_run (void *cls,
|
||||
}
|
||||
else
|
||||
{
|
||||
const struct TALER_CoinSpendPrivateKeyP *coin_priv;
|
||||
const struct TALER_PlanchetSecretsP *ps;
|
||||
const struct TALER_TESTING_Command *cref;
|
||||
char *cstr;
|
||||
unsigned int index;
|
||||
@ -406,11 +425,9 @@ withdraw_run (void *cls,
|
||||
GNUNET_assert (NULL != cref);
|
||||
GNUNET_free (cstr);
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_TESTING_get_trait_coin_priv (cref,
|
||||
index,
|
||||
&coin_priv));
|
||||
TALER_planchet_setup_random (&ws->ps);
|
||||
ws->ps.coin_priv = *coin_priv;
|
||||
TALER_TESTING_get_trait_planchet_secret (cref,
|
||||
&ps));
|
||||
ws->ps = *ps;
|
||||
}
|
||||
if (NULL == ws->pk)
|
||||
{
|
||||
@ -513,9 +530,12 @@ withdraw_traits (void *cls,
|
||||
/* history entry MUST be first due to response code logic below! */
|
||||
TALER_TESTING_make_trait_reserve_history (&ws->reserve_history),
|
||||
TALER_TESTING_make_trait_coin_priv (0 /* only one coin */,
|
||||
&ws->ps.coin_priv),
|
||||
&ws->coin_priv),
|
||||
TALER_TESTING_make_trait_planchet_secret (&ws->ps),
|
||||
TALER_TESTING_make_trait_blinding_key (0 /* only one coin */,
|
||||
&ws->ps.blinding_key),
|
||||
&ws->bks),
|
||||
TALER_TESTING_make_trait_exchange_wd_value (0 /* only one coin */,
|
||||
&ws->exchange_vals),
|
||||
TALER_TESTING_make_trait_denom_pub (0 /* only one coin */,
|
||||
ws->pk),
|
||||
TALER_TESTING_make_trait_denom_sig (0 /* only one coin */,
|
||||
|
@ -670,7 +670,7 @@ TALER_TESTING_prepare_fakebank (const char *config_filename,
|
||||
json_t *
|
||||
TALER_TESTING_make_wire_details (const char *payto)
|
||||
{
|
||||
struct TALER_WireSalt salt;
|
||||
struct TALER_WireSaltP salt;
|
||||
|
||||
/* salt must be constant for aggregation tests! */
|
||||
memset (&salt,
|
||||
|
@ -411,13 +411,6 @@ TALER_TESTING_prepare_exchange (const char *config_filename,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find denomination key matching the given amount.
|
||||
*
|
||||
* @param keys array of keys to search
|
||||
* @param amount coin value to look for
|
||||
* @return NULL if no matching key was found
|
||||
*/
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *
|
||||
TALER_TESTING_find_pk (const struct TALER_EXCHANGE_Keys *keys,
|
||||
const struct TALER_Amount *amount)
|
||||
@ -608,9 +601,9 @@ TALER_TESTING_setup_with_exchange (TALER_TESTING_Main main_cb,
|
||||
* @param[in] helpers the process handles.
|
||||
*/
|
||||
static void
|
||||
stop_helpers (struct GNUNET_OS_Process *helpers[2])
|
||||
stop_helpers (struct GNUNET_OS_Process *helpers[3])
|
||||
{
|
||||
for (unsigned int i = 0; i<2; i++)
|
||||
for (unsigned int i = 0; i<3; i++)
|
||||
{
|
||||
if (NULL == helpers[i])
|
||||
continue;
|
||||
@ -632,7 +625,7 @@ stop_helpers (struct GNUNET_OS_Process *helpers[2])
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
start_helpers (const char *config_filename,
|
||||
struct GNUNET_OS_Process *helpers[2])
|
||||
struct GNUNET_OS_Process *helpers[3])
|
||||
{
|
||||
char *dir;
|
||||
const struct GNUNET_OS_ProjectData *pd;
|
||||
@ -678,9 +671,26 @@ start_helpers (const char *config_filename,
|
||||
NULL);
|
||||
GNUNET_free (fn);
|
||||
}
|
||||
{
|
||||
char *fn;
|
||||
|
||||
GNUNET_asprintf (&fn,
|
||||
"%s/%s",
|
||||
dir,
|
||||
"taler-exchange-secmod-cs");
|
||||
helpers[2] = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
|
||||
NULL, NULL, NULL,
|
||||
fn,
|
||||
"taler-exchange-secmod-cs",
|
||||
"-c", config_filename,
|
||||
"-L", "INFO",
|
||||
NULL);
|
||||
GNUNET_free (fn);
|
||||
}
|
||||
GNUNET_free (dir);
|
||||
if ( (NULL == helpers[0]) ||
|
||||
(NULL == helpers[1]) )
|
||||
(NULL == helpers[1]) ||
|
||||
(NULL == helpers[2]) )
|
||||
{
|
||||
stop_helpers (helpers);
|
||||
return GNUNET_SYSERR;
|
||||
@ -696,7 +706,7 @@ TALER_TESTING_setup_with_exchange_cfg (
|
||||
{
|
||||
const struct TALER_TESTING_SetupContext *setup_ctx = cls;
|
||||
struct GNUNET_OS_Process *exchanged;
|
||||
struct GNUNET_OS_Process *helpers[2];
|
||||
struct GNUNET_OS_Process *helpers[3];
|
||||
unsigned long long port;
|
||||
char *serve;
|
||||
char *base_url;
|
||||
@ -755,6 +765,7 @@ TALER_TESTING_setup_with_exchange_cfg (
|
||||
#endif
|
||||
"taler-exchange-httpd",
|
||||
"taler-exchange-httpd",
|
||||
"-L", "INFO",
|
||||
"-a", /* some tests may need timetravel */
|
||||
"-c", setup_ctx->config_filename,
|
||||
#if GNU_PARALLEL
|
||||
|
@ -691,7 +691,7 @@ main_wrapper_exchange_connect (void *cls)
|
||||
*
|
||||
* @param[in,out] is state to initialize
|
||||
*/
|
||||
static int
|
||||
static enum GNUNET_GenericReturnValue
|
||||
load_keys (struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
char *fn;
|
||||
@ -774,7 +774,7 @@ load_keys (struct TALER_TESTING_Interpreter *is)
|
||||
*
|
||||
* @param[in,out] is state to initialize
|
||||
*/
|
||||
static int
|
||||
static enum GNUNET_GenericReturnValue
|
||||
load_urls (struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
if (GNUNET_OK !=
|
||||
@ -804,7 +804,7 @@ load_urls (struct TALER_TESTING_Interpreter *is)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_TESTING_setup (TALER_TESTING_Main main_cb,
|
||||
void *main_cb_cls,
|
||||
const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||
@ -839,7 +839,8 @@ TALER_TESTING_setup (TALER_TESTING_Main main_cb,
|
||||
is.ctx = GNUNET_CURL_init
|
||||
(&GNUNET_CURL_gnunet_scheduler_reschedule,
|
||||
&is.rc);
|
||||
GNUNET_CURL_enable_async_scope_header (is.ctx, "Taler-Correlation-Id");
|
||||
GNUNET_CURL_enable_async_scope_header (is.ctx,
|
||||
"Taler-Correlation-Id");
|
||||
GNUNET_assert (NULL != is.ctx);
|
||||
is.rc = GNUNET_CURL_gnunet_rc_create (is.ctx);
|
||||
|
||||
|
3
src/util/.gitignore
vendored
3
src/util/.gitignore
vendored
@ -1,8 +1,11 @@
|
||||
taler-config
|
||||
test_payto
|
||||
taler-exchange-secmod-rsa
|
||||
taler-exchange-secmod-cs
|
||||
taler-exchange-secmod-eddsa
|
||||
test_helper_rsa
|
||||
test_helper_rsa_home/
|
||||
test_helper_cs
|
||||
test_helper_cs_home/
|
||||
test_helper_eddsa
|
||||
test_helper_eddsa_home/
|
||||
|
@ -12,17 +12,20 @@ pkgcfgdir = $(prefix)/share/taler/config.d/
|
||||
pkgcfg_DATA = \
|
||||
paths.conf \
|
||||
taler-exchange-secmod-eddsa.conf \
|
||||
taler-exchange-secmod-rsa.conf
|
||||
taler-exchange-secmod-rsa.conf \
|
||||
taler-exchange-secmod-cs.conf
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(pkgcfg_DATA) \
|
||||
taler-config.in \
|
||||
test_helper_eddsa.conf \
|
||||
test_helper_rsa.conf
|
||||
test_helper_rsa.conf \
|
||||
test_helper_cs.conf
|
||||
|
||||
bin_PROGRAMS = \
|
||||
taler-exchange-secmod-eddsa \
|
||||
taler-exchange-secmod-rsa
|
||||
taler-exchange-secmod-rsa \
|
||||
taler-exchange-secmod-cs
|
||||
|
||||
bin_SCRIPTS = \
|
||||
taler-config
|
||||
@ -48,6 +51,16 @@ taler_exchange_secmod_rsa_LDADD = \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
$(XLIB)
|
||||
|
||||
taler_exchange_secmod_cs_SOURCES = \
|
||||
taler-exchange-secmod-cs.c taler-exchange-secmod-cs.h \
|
||||
secmod_common.c secmod_common.h
|
||||
taler_exchange_secmod_cs_LDADD = \
|
||||
libtalerutil.la \
|
||||
-lgnunetutil \
|
||||
-lpthread \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
$(XLIB)
|
||||
|
||||
taler_exchange_secmod_eddsa_SOURCES = \
|
||||
taler-exchange-secmod-eddsa.c taler-exchange-secmod-eddsa.h \
|
||||
secmod_common.c secmod_common.h
|
||||
@ -68,6 +81,7 @@ libtalerutil_la_SOURCES = \
|
||||
crypto.c \
|
||||
crypto_helper_common.c crypto_helper_common.h \
|
||||
crypto_helper_rsa.c \
|
||||
crypto_helper_cs.c \
|
||||
crypto_helper_esign.c \
|
||||
crypto_wire.c \
|
||||
denom.c \
|
||||
@ -105,6 +119,7 @@ check_PROGRAMS = \
|
||||
test_crypto \
|
||||
test_helper_eddsa \
|
||||
test_helper_rsa \
|
||||
test_helper_cs \
|
||||
test_payto \
|
||||
test_url
|
||||
|
||||
@ -142,6 +157,12 @@ test_helper_rsa_LDADD = \
|
||||
-lgnunetutil \
|
||||
libtalerutil.la
|
||||
|
||||
test_helper_cs_SOURCES = \
|
||||
test_helper_cs.c
|
||||
test_helper_cs_LDADD = \
|
||||
-lgnunetutil \
|
||||
libtalerutil.la
|
||||
|
||||
test_url_SOURCES = \
|
||||
test_url.c
|
||||
test_url_LDADD = \
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2017 Taler Systems SA
|
||||
Copyright (C) 2014-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -116,7 +116,6 @@ TALER_link_derive_transfer_secret (
|
||||
GNUNET_CRYPTO_ecdh_eddsa (&trans_priv->ecdhe_priv,
|
||||
&coin_pub.eddsa_pub,
|
||||
&ts->key));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -147,7 +146,18 @@ TALER_link_recover_transfer_secret (
|
||||
|
||||
|
||||
void
|
||||
TALER_planchet_setup_refresh (const struct TALER_TransferSecretP *secret_seed,
|
||||
TALER_planchet_setup_random (
|
||||
struct TALER_PlanchetSecretsP *ps)
|
||||
{
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
|
||||
ps,
|
||||
sizeof (*ps));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_transfer_secret_to_planchet_secret (
|
||||
const struct TALER_TransferSecretP *secret_seed,
|
||||
uint32_t coin_num_salt,
|
||||
struct TALER_PlanchetSecretsP *ps)
|
||||
{
|
||||
@ -167,61 +177,296 @@ TALER_planchet_setup_refresh (const struct TALER_TransferSecretP *secret_seed,
|
||||
|
||||
|
||||
void
|
||||
TALER_planchet_setup_random (struct TALER_PlanchetSecretsP *ps)
|
||||
TALER_planchet_secret_to_transfer_priv (
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
uint32_t cnc_num,
|
||||
struct TALER_TransferPrivateKeyP *tpriv)
|
||||
{
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
|
||||
uint32_t be_salt = htonl (cnc_num);
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
GNUNET_CRYPTO_kdf (tpriv,
|
||||
sizeof (*tpriv),
|
||||
&be_salt,
|
||||
sizeof (be_salt),
|
||||
ps,
|
||||
sizeof (*ps));
|
||||
sizeof (*ps),
|
||||
"taler-transfer-priv-derivation",
|
||||
strlen ("taler-transfer-priv-derivation"),
|
||||
NULL, 0));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_cs_withdraw_nonce_derive (
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
struct TALER_CsNonce *nonce)
|
||||
{
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
GNUNET_CRYPTO_kdf (nonce,
|
||||
sizeof (*nonce),
|
||||
"n",
|
||||
strlen ("n"),
|
||||
ps,
|
||||
sizeof(*ps),
|
||||
NULL,
|
||||
0));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_cs_refresh_nonce_derive (
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
uint32_t coin_num_salt,
|
||||
struct TALER_CsNonce *nonce)
|
||||
{
|
||||
uint32_t be_salt = htonl (coin_num_salt);
|
||||
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
GNUNET_CRYPTO_kdf (nonce,
|
||||
sizeof (*nonce),
|
||||
&be_salt,
|
||||
sizeof (be_salt),
|
||||
"refresh-n", // FIXME: value used in spec?
|
||||
strlen ("refresh-n"),
|
||||
ps,
|
||||
sizeof(*ps),
|
||||
NULL,
|
||||
0));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_planchet_blinding_secret_create (
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
const struct TALER_ExchangeWithdrawValues *alg_values,
|
||||
union TALER_DenominationBlindingKeyP *bks)
|
||||
{
|
||||
switch (alg_values->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_INVALID:
|
||||
GNUNET_break (0);
|
||||
return;
|
||||
case TALER_DENOMINATION_RSA:
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
GNUNET_CRYPTO_kdf (&bks->rsa_bks,
|
||||
sizeof (bks->rsa_bks),
|
||||
"bks",
|
||||
strlen ("bks"),
|
||||
ps,
|
||||
sizeof(*ps),
|
||||
NULL,
|
||||
0));
|
||||
return;
|
||||
case TALER_DENOMINATION_CS:
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
GNUNET_CRYPTO_kdf (&bks->nonce,
|
||||
sizeof (bks->nonce),
|
||||
"bseed",
|
||||
strlen ("bseed"),
|
||||
ps,
|
||||
sizeof(*ps),
|
||||
&alg_values->details.cs_values,
|
||||
sizeof(alg_values->details.cs_values),
|
||||
NULL,
|
||||
0));
|
||||
return;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_planchet_setup_coin_priv (
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
const struct TALER_ExchangeWithdrawValues *alg_values,
|
||||
struct TALER_CoinSpendPrivateKeyP *coin_priv)
|
||||
{
|
||||
switch (alg_values->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
GNUNET_CRYPTO_kdf (coin_priv,
|
||||
sizeof (*coin_priv),
|
||||
"coin",
|
||||
strlen ("coin"),
|
||||
ps,
|
||||
sizeof(*ps),
|
||||
NULL,
|
||||
0));
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
GNUNET_CRYPTO_kdf (coin_priv,
|
||||
sizeof (*coin_priv),
|
||||
"coin",
|
||||
strlen ("coin"),
|
||||
ps,
|
||||
sizeof(*ps),
|
||||
&alg_values->details, /* Could be null on RSA case*/
|
||||
sizeof(alg_values->details),
|
||||
NULL,
|
||||
0));
|
||||
break;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
return;
|
||||
}
|
||||
coin_priv->eddsa_priv.d[0] &= 248;
|
||||
coin_priv->eddsa_priv.d[31] &= 127;
|
||||
coin_priv->eddsa_priv.d[31] |= 64;
|
||||
}
|
||||
|
||||
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk,
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
const struct TALER_ExchangeWithdrawValues *alg_values,
|
||||
const union TALER_DenominationBlindingKeyP *bks,
|
||||
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
|
||||
struct TALER_CoinPubHash *c_hash,
|
||||
struct TALER_PlanchetDetail *pd)
|
||||
struct TALER_PlanchetDetail *pd
|
||||
)
|
||||
{
|
||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&ps->coin_priv.eddsa_priv,
|
||||
GNUNET_assert (alg_values->cipher == dk->cipher);
|
||||
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
|
||||
&coin_pub.eddsa_pub);
|
||||
|
||||
switch (dk->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
if (GNUNET_OK !=
|
||||
TALER_denom_blind (dk,
|
||||
&ps->blinding_key,
|
||||
bks,
|
||||
NULL, /* FIXME-Oec */
|
||||
&coin_pub,
|
||||
alg_values,
|
||||
c_hash,
|
||||
&pd->coin_ev,
|
||||
&pd->coin_ev_size))
|
||||
&pd->blinded_planchet))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
if (GNUNET_OK !=
|
||||
TALER_denom_blind (dk,
|
||||
bks,
|
||||
NULL, /* FIXME-Oec */
|
||||
&coin_pub,
|
||||
alg_values,
|
||||
c_hash,
|
||||
&pd->blinded_planchet))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
pd->blinded_planchet.cipher = dk->cipher;
|
||||
TALER_denom_pub_hash (dk,
|
||||
&pd->denom_pub_hash);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_planchet_detail_free (struct TALER_PlanchetDetail *pd)
|
||||
{
|
||||
TALER_blinded_planchet_free (&pd->blinded_planchet);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_blinded_planchet_free (struct TALER_BlindedPlanchet *blinded_planchet)
|
||||
{
|
||||
switch (blinded_planchet->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
GNUNET_free (blinded_planchet->details.rsa_blinded_planchet.blinded_msg);
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
/* nothing to do for CS */
|
||||
break;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_planchet_to_coin (
|
||||
const struct TALER_DenominationPublicKey *dk,
|
||||
const struct TALER_BlindedDenominationSignature *blind_sig,
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
const union TALER_DenominationBlindingKeyP *bks,
|
||||
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
|
||||
const struct TALER_CoinPubHash *c_hash,
|
||||
const struct TALER_ExchangeWithdrawValues *alg_values,
|
||||
struct TALER_FreshCoin *coin)
|
||||
{
|
||||
struct TALER_DenominationSignature sig;
|
||||
|
||||
if (dk->cipher != blind_sig->cipher
|
||||
&& dk->cipher != alg_values->cipher)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
switch (dk->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
if (GNUNET_OK !=
|
||||
TALER_denom_sig_unblind (&sig,
|
||||
blind_sig,
|
||||
&ps->blinding_key,
|
||||
bks,
|
||||
dk))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
{
|
||||
struct GNUNET_CRYPTO_CsC c[2];
|
||||
struct GNUNET_CRYPTO_CsBlindingSecret bs[2];
|
||||
struct TALER_DenominationCSPublicRPairP r_pub_blind;
|
||||
|
||||
GNUNET_CRYPTO_cs_blinding_secrets_derive (&bks->nonce,
|
||||
bs);
|
||||
GNUNET_CRYPTO_cs_calc_blinded_c (
|
||||
bs,
|
||||
alg_values->details.cs_values.r_pub_pair.r_pub,
|
||||
&dk->details.cs_public_key,
|
||||
&c_hash->hash,
|
||||
sizeof(struct GNUNET_HashCode),
|
||||
c,
|
||||
r_pub_blind.r_pub);
|
||||
sig.details.cs_signature.r_point
|
||||
= r_pub_blind.r_pub[blind_sig->details.blinded_cs_answer.b];
|
||||
if (GNUNET_OK !=
|
||||
TALER_denom_sig_unblind (&sig,
|
||||
blind_sig,
|
||||
bks,
|
||||
dk))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_denom_pub_verify (dk,
|
||||
&sig,
|
||||
@ -231,8 +476,9 @@ TALER_planchet_to_coin (
|
||||
TALER_denom_sig_free (&sig);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
coin->sig = sig;
|
||||
coin->coin_priv = ps->coin_priv;
|
||||
coin->coin_priv = *coin_priv;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
@ -294,9 +540,8 @@ TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc,
|
||||
{
|
||||
const struct TALER_RefreshCoinData *rcd = &rce->new_coins[j];
|
||||
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
rcd->coin_ev,
|
||||
rcd->coin_ev_size);
|
||||
TALER_blinded_planchet_hash (&rcd->blinded_planchet,
|
||||
hash_context);
|
||||
}
|
||||
}
|
||||
|
||||
@ -306,14 +551,39 @@ TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_coin_ev_hash (const void *coin_ev,
|
||||
size_t coin_ev_size,
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_coin_ev_hash (const struct TALER_BlindedPlanchet *blinded_planchet,
|
||||
const struct TALER_DenominationHash *denom_hash,
|
||||
struct TALER_BlindedCoinHash *bch)
|
||||
{
|
||||
GNUNET_CRYPTO_hash (coin_ev,
|
||||
coin_ev_size,
|
||||
struct GNUNET_HashContext *hash_context;
|
||||
|
||||
hash_context = GNUNET_CRYPTO_hash_context_start ();
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
denom_hash,
|
||||
sizeof(*denom_hash));
|
||||
switch (blinded_planchet->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
GNUNET_CRYPTO_hash_context_read (
|
||||
hash_context,
|
||||
blinded_planchet->details.rsa_blinded_planchet.blinded_msg,
|
||||
blinded_planchet->details.rsa_blinded_planchet.blinded_msg_size);
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
GNUNET_CRYPTO_hash_context_read (
|
||||
hash_context,
|
||||
&blinded_planchet->details.cs_blinded_planchet.nonce,
|
||||
sizeof (blinded_planchet->details.cs_blinded_planchet.nonce));
|
||||
break;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
GNUNET_CRYPTO_hash_context_abort (hash_context);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
GNUNET_CRYPTO_hash_context_finish (hash_context,
|
||||
&bch->hash);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -340,11 +610,9 @@ TALER_coin_pub_hash (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
GNUNET_memcpy (&data[0],
|
||||
&coin_pub->eddsa_pub,
|
||||
key_s);
|
||||
|
||||
GNUNET_memcpy (&data[key_s],
|
||||
age_commitment_hash,
|
||||
age_s);
|
||||
|
||||
GNUNET_CRYPTO_hash (&data,
|
||||
key_s + age_s,
|
||||
&coin_h->hash);
|
||||
|
815
src/util/crypto_helper_cs.c
Normal file
815
src/util/crypto_helper_cs.c
Normal file
@ -0,0 +1,815 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2020, 2021 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 3, or (at your option) any later version.
|
||||
|
||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file util/crypto_helper_cs.c
|
||||
* @brief utility functions for running out-of-process private key operations
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "taler_util.h"
|
||||
#include "taler_signatures.h"
|
||||
#include "taler-exchange-secmod-cs.h"
|
||||
#include <poll.h>
|
||||
#include "crypto_helper_common.h"
|
||||
|
||||
|
||||
struct TALER_CRYPTO_CsDenominationHelper
|
||||
{
|
||||
/**
|
||||
* Function to call with updates to available key material.
|
||||
*/
|
||||
TALER_CRYPTO_CsDenominationKeyStatusCallback dkc;
|
||||
|
||||
/**
|
||||
* Closure for @e dkc
|
||||
*/
|
||||
void *dkc_cls;
|
||||
|
||||
/**
|
||||
* Socket address of the denomination helper process.
|
||||
* Used to reconnect if the connection breaks.
|
||||
*/
|
||||
struct sockaddr_un sa;
|
||||
|
||||
/**
|
||||
* The UNIX domain socket, -1 if we are currently not connected.
|
||||
*/
|
||||
int sock;
|
||||
|
||||
/**
|
||||
* Have we ever been sync'ed?
|
||||
*/
|
||||
bool synced;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Disconnect from the helper process. Updates
|
||||
* @e sock field in @a dh.
|
||||
*
|
||||
* @param[in,out] dh handle to tear down connection of
|
||||
*/
|
||||
static void
|
||||
do_disconnect (struct TALER_CRYPTO_CsDenominationHelper *dh)
|
||||
{
|
||||
GNUNET_break (0 == close (dh->sock));
|
||||
dh->sock = -1;
|
||||
dh->synced = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Try to connect to the helper process. Updates
|
||||
* @e sock field in @a dh.
|
||||
*
|
||||
* @param[in,out] dh handle to establish connection for
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
try_connect (struct TALER_CRYPTO_CsDenominationHelper *dh)
|
||||
{
|
||||
if (-1 != dh->sock)
|
||||
return GNUNET_OK;
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Establishing connection!\n");
|
||||
dh->sock = socket (AF_UNIX,
|
||||
SOCK_STREAM,
|
||||
0);
|
||||
if (-1 == dh->sock)
|
||||
{
|
||||
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
|
||||
"socket");
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (0 !=
|
||||
connect (dh->sock,
|
||||
(const struct sockaddr *) &dh->sa,
|
||||
sizeof (dh->sa)))
|
||||
{
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
|
||||
"connect",
|
||||
dh->sa.sun_path);
|
||||
do_disconnect (dh);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
TALER_CRYPTO_helper_cs_poll (dh);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
struct TALER_CRYPTO_CsDenominationHelper *
|
||||
TALER_CRYPTO_helper_cs_connect (
|
||||
const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||
TALER_CRYPTO_CsDenominationKeyStatusCallback dkc,
|
||||
void *dkc_cls)
|
||||
{
|
||||
struct TALER_CRYPTO_CsDenominationHelper *dh;
|
||||
char *unixpath;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_filename (cfg,
|
||||
"taler-exchange-secmod-cs",
|
||||
"UNIXPATH",
|
||||
&unixpath))
|
||||
{
|
||||
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||
"taler-exchange-secmod-cs",
|
||||
"UNIXPATH");
|
||||
return NULL;
|
||||
}
|
||||
/* we use >= here because we want the sun_path to always
|
||||
be 0-terminated */
|
||||
if (strlen (unixpath) >= sizeof (dh->sa.sun_path))
|
||||
{
|
||||
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
||||
"taler-exchange-secmod-cs",
|
||||
"UNIXPATH",
|
||||
"path too long");
|
||||
GNUNET_free (unixpath);
|
||||
return NULL;
|
||||
}
|
||||
dh = GNUNET_new (struct TALER_CRYPTO_CsDenominationHelper);
|
||||
dh->dkc = dkc;
|
||||
dh->dkc_cls = dkc_cls;
|
||||
dh->sa.sun_family = AF_UNIX;
|
||||
strncpy (dh->sa.sun_path,
|
||||
unixpath,
|
||||
sizeof (dh->sa.sun_path) - 1);
|
||||
GNUNET_free (unixpath);
|
||||
dh->sock = -1;
|
||||
if (GNUNET_OK !=
|
||||
try_connect (dh))
|
||||
{
|
||||
TALER_CRYPTO_helper_cs_disconnect (dh);
|
||||
return NULL;
|
||||
}
|
||||
return dh;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle a #TALER_HELPER_CS_MT_AVAIL message from the helper.
|
||||
*
|
||||
* @param dh helper context
|
||||
* @param hdr message that we received
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
handle_mt_avail (struct TALER_CRYPTO_CsDenominationHelper *dh,
|
||||
const struct GNUNET_MessageHeader *hdr)
|
||||
{
|
||||
const struct TALER_CRYPTO_CsKeyAvailableNotification *kan
|
||||
= (const struct TALER_CRYPTO_CsKeyAvailableNotification *) hdr;
|
||||
const char *buf = (const char *) &kan[1];
|
||||
const char *section_name;
|
||||
uint16_t snl;
|
||||
|
||||
if (sizeof (*kan) > ntohs (hdr->size))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
snl = ntohs (kan->section_name_len);
|
||||
if (ntohs (hdr->size) != sizeof (*kan) + snl)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (0 == snl)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
section_name = buf;
|
||||
if ('\0' != section_name[snl - 1])
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
{
|
||||
struct TALER_DenominationPublicKey denom_pub;
|
||||
struct TALER_CsPubHashP h_cs;
|
||||
|
||||
denom_pub.cipher = TALER_DENOMINATION_CS;
|
||||
denom_pub.details.cs_public_key = kan->denom_pub;
|
||||
|
||||
TALER_cs_pub_hash (&denom_pub.details.cs_public_key, &h_cs);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Received CS key %s (%s)\n",
|
||||
GNUNET_h2s (&h_cs.hash),
|
||||
section_name);
|
||||
if (GNUNET_OK !=
|
||||
TALER_exchange_secmod_cs_verify (
|
||||
&h_cs,
|
||||
section_name,
|
||||
GNUNET_TIME_timestamp_ntoh (kan->anchor_time),
|
||||
GNUNET_TIME_relative_ntoh (kan->duration_withdraw),
|
||||
&kan->secm_pub,
|
||||
&kan->secm_sig))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
TALER_denom_pub_free (&denom_pub);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
dh->dkc (dh->dkc_cls,
|
||||
section_name,
|
||||
GNUNET_TIME_timestamp_ntoh (kan->anchor_time),
|
||||
GNUNET_TIME_relative_ntoh (kan->duration_withdraw),
|
||||
&h_cs,
|
||||
&denom_pub,
|
||||
&kan->secm_pub,
|
||||
&kan->secm_sig);
|
||||
TALER_denom_pub_free (&denom_pub);
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle a #TALER_HELPER_CS_MT_PURGE message from the helper.
|
||||
*
|
||||
* @param dh helper context
|
||||
* @param hdr message that we received
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
handle_mt_purge (struct TALER_CRYPTO_CsDenominationHelper *dh,
|
||||
const struct GNUNET_MessageHeader *hdr)
|
||||
{
|
||||
const struct TALER_CRYPTO_CsKeyPurgeNotification *pn
|
||||
= (const struct TALER_CRYPTO_CsKeyPurgeNotification *) hdr;
|
||||
|
||||
if (sizeof (*pn) != ntohs (hdr->size))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Received revocation of denomination key %s\n",
|
||||
GNUNET_h2s (&pn->h_cs.hash));
|
||||
dh->dkc (dh->dkc_cls,
|
||||
NULL,
|
||||
GNUNET_TIME_UNIT_ZERO_TS,
|
||||
GNUNET_TIME_UNIT_ZERO,
|
||||
&pn->h_cs,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_CRYPTO_helper_cs_poll (struct TALER_CRYPTO_CsDenominationHelper *dh)
|
||||
{
|
||||
char buf[UINT16_MAX];
|
||||
size_t off = 0;
|
||||
unsigned int retry_limit = 3;
|
||||
const struct GNUNET_MessageHeader *hdr
|
||||
= (const struct GNUNET_MessageHeader *) buf;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
try_connect (dh))
|
||||
return; /* give up */
|
||||
while (1)
|
||||
{
|
||||
uint16_t msize;
|
||||
ssize_t ret;
|
||||
|
||||
ret = recv (dh->sock,
|
||||
buf + off,
|
||||
sizeof (buf) - off,
|
||||
(dh->synced && (0 == off))
|
||||
? MSG_DONTWAIT
|
||||
: 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (EINTR == errno)
|
||||
continue;
|
||||
if (EAGAIN == errno)
|
||||
{
|
||||
GNUNET_assert (dh->synced);
|
||||
GNUNET_assert (0 == off);
|
||||
break;
|
||||
}
|
||||
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
|
||||
"recv");
|
||||
do_disconnect (dh);
|
||||
if (0 == retry_limit)
|
||||
return; /* give up */
|
||||
if (GNUNET_OK !=
|
||||
try_connect (dh))
|
||||
return; /* give up */
|
||||
retry_limit--;
|
||||
continue;
|
||||
}
|
||||
if (0 == ret)
|
||||
{
|
||||
GNUNET_break (0 == off);
|
||||
return;
|
||||
}
|
||||
off += ret;
|
||||
more:
|
||||
if (off < sizeof (struct GNUNET_MessageHeader))
|
||||
continue;
|
||||
msize = ntohs (hdr->size);
|
||||
if (off < msize)
|
||||
continue;
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Received message of type %u and length %u\n",
|
||||
(unsigned int) ntohs (hdr->type),
|
||||
(unsigned int) msize);
|
||||
switch (ntohs (hdr->type))
|
||||
{
|
||||
case TALER_HELPER_CS_MT_AVAIL:
|
||||
if (GNUNET_OK !=
|
||||
handle_mt_avail (dh,
|
||||
hdr))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
do_disconnect (dh);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case TALER_HELPER_CS_MT_PURGE:
|
||||
if (GNUNET_OK !=
|
||||
handle_mt_purge (dh,
|
||||
hdr))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
do_disconnect (dh);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case TALER_HELPER_CS_SYNCED:
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Now synchronized with CS helper\n");
|
||||
dh->synced = true;
|
||||
break;
|
||||
default:
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Received unexpected message of type %d (len: %u)\n",
|
||||
(unsigned int) ntohs (hdr->type),
|
||||
(unsigned int) msize);
|
||||
GNUNET_break_op (0);
|
||||
do_disconnect (dh);
|
||||
return;
|
||||
}
|
||||
memmove (buf,
|
||||
&buf[msize],
|
||||
off - msize);
|
||||
off -= msize;
|
||||
goto more;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct TALER_BlindedDenominationSignature
|
||||
TALER_CRYPTO_helper_cs_sign (
|
||||
struct TALER_CRYPTO_CsDenominationHelper *dh,
|
||||
const struct TALER_CsPubHashP *h_cs,
|
||||
const struct TALER_BlindedCsPlanchet *blinded_planchet,
|
||||
enum TALER_ErrorCode *ec)
|
||||
{
|
||||
struct TALER_BlindedDenominationSignature ds = {
|
||||
.cipher = TALER_DENOMINATION_INVALID
|
||||
};
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Starting signature process\n");
|
||||
if (GNUNET_OK !=
|
||||
try_connect (dh))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Failed to connect to helper\n");
|
||||
*ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
|
||||
return ds;
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Requesting signature\n");
|
||||
{
|
||||
char buf[sizeof (struct TALER_CRYPTO_CsSignRequest)];
|
||||
struct TALER_CRYPTO_CsSignRequest *sr
|
||||
= (struct TALER_CRYPTO_CsSignRequest *) buf;
|
||||
|
||||
sr->header.size = htons (sizeof (buf));
|
||||
sr->header.type = htons (TALER_HELPER_CS_MT_REQ_SIGN);
|
||||
sr->reserved = htonl (0);
|
||||
sr->h_cs = *h_cs;
|
||||
sr->planchet = *blinded_planchet;
|
||||
if (GNUNET_OK !=
|
||||
TALER_crypto_helper_send_all (dh->sock,
|
||||
buf,
|
||||
sizeof (buf)))
|
||||
{
|
||||
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
|
||||
"send");
|
||||
do_disconnect (dh);
|
||||
*ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
|
||||
return ds;
|
||||
}
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Awaiting reply\n");
|
||||
{
|
||||
char buf[UINT16_MAX];
|
||||
size_t off = 0;
|
||||
const struct GNUNET_MessageHeader *hdr
|
||||
= (const struct GNUNET_MessageHeader *) buf;
|
||||
bool finished = false;
|
||||
|
||||
*ec = TALER_EC_INVALID;
|
||||
while (1)
|
||||
{
|
||||
uint16_t msize;
|
||||
ssize_t ret;
|
||||
|
||||
ret = recv (dh->sock,
|
||||
&buf[off],
|
||||
sizeof (buf) - off,
|
||||
(finished && (0 == off))
|
||||
? MSG_DONTWAIT
|
||||
: 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (EINTR == errno)
|
||||
continue;
|
||||
if (EAGAIN == errno)
|
||||
{
|
||||
GNUNET_assert (finished);
|
||||
GNUNET_assert (0 == off);
|
||||
return ds;
|
||||
}
|
||||
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
|
||||
"recv");
|
||||
do_disconnect (dh);
|
||||
*ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
|
||||
break;
|
||||
}
|
||||
if (0 == ret)
|
||||
{
|
||||
GNUNET_break (0 == off);
|
||||
if (! finished)
|
||||
*ec = TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
|
||||
return ds;
|
||||
}
|
||||
off += ret;
|
||||
more:
|
||||
if (off < sizeof (struct GNUNET_MessageHeader))
|
||||
continue;
|
||||
msize = ntohs (hdr->size);
|
||||
if (off < msize)
|
||||
continue;
|
||||
switch (ntohs (hdr->type))
|
||||
{
|
||||
case TALER_HELPER_CS_MT_RES_SIGNATURE:
|
||||
if (msize < sizeof (struct TALER_CRYPTO_SignResponse))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
do_disconnect (dh);
|
||||
*ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
|
||||
goto end;
|
||||
}
|
||||
if (finished)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
do_disconnect (dh);
|
||||
*ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
|
||||
goto end;
|
||||
}
|
||||
{
|
||||
const struct TALER_CRYPTO_SignResponse *sr =
|
||||
(const struct TALER_CRYPTO_SignResponse *) buf;
|
||||
// TODO: add nullcheck
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Received signature\n");
|
||||
*ec = TALER_EC_NONE;
|
||||
finished = true;
|
||||
ds.cipher = TALER_DENOMINATION_CS;
|
||||
ds.details.blinded_cs_answer = sr->cs_answer;
|
||||
break;
|
||||
}
|
||||
case TALER_HELPER_CS_MT_RES_SIGN_FAILURE:
|
||||
if (msize != sizeof (struct TALER_CRYPTO_SignFailure))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
do_disconnect (dh);
|
||||
*ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
|
||||
goto end;
|
||||
}
|
||||
{
|
||||
const struct TALER_CRYPTO_SignFailure *sf =
|
||||
(const struct TALER_CRYPTO_SignFailure *) buf;
|
||||
|
||||
*ec = (enum TALER_ErrorCode) ntohl (sf->ec);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Signing failed!\n");
|
||||
finished = true;
|
||||
break;
|
||||
}
|
||||
case TALER_HELPER_CS_MT_AVAIL:
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Received new key!\n");
|
||||
if (GNUNET_OK !=
|
||||
handle_mt_avail (dh,
|
||||
hdr))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
do_disconnect (dh);
|
||||
*ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
|
||||
goto end;
|
||||
}
|
||||
break; /* while(1) loop ensures we recvfrom() again */
|
||||
case TALER_HELPER_CS_MT_PURGE:
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Received revocation!\n");
|
||||
if (GNUNET_OK !=
|
||||
handle_mt_purge (dh,
|
||||
hdr))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
do_disconnect (dh);
|
||||
*ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
|
||||
goto end;
|
||||
}
|
||||
break; /* while(1) loop ensures we recvfrom() again */
|
||||
case TALER_HELPER_CS_SYNCED:
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Synchronized add odd time with CS helper!\n");
|
||||
dh->synced = true;
|
||||
break;
|
||||
default:
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Received unexpected message of type %u\n",
|
||||
ntohs (hdr->type));
|
||||
do_disconnect (dh);
|
||||
*ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
|
||||
goto end;
|
||||
}
|
||||
memmove (buf,
|
||||
&buf[msize],
|
||||
off - msize);
|
||||
off -= msize;
|
||||
goto more;
|
||||
} /* while(1) */
|
||||
end:
|
||||
if (finished)
|
||||
TALER_blinded_denom_sig_free (&ds);
|
||||
return ds;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_CRYPTO_helper_cs_revoke (
|
||||
struct TALER_CRYPTO_CsDenominationHelper *dh,
|
||||
const struct TALER_CsPubHashP *h_cs)
|
||||
{
|
||||
struct TALER_CRYPTO_CsRevokeRequest rr = {
|
||||
.header.size = htons (sizeof (rr)),
|
||||
.header.type = htons (TALER_HELPER_CS_MT_REQ_REVOKE),
|
||||
.h_cs = *h_cs
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
try_connect (dh))
|
||||
return; /* give up */
|
||||
if (GNUNET_OK !=
|
||||
TALER_crypto_helper_send_all (dh->sock,
|
||||
&rr,
|
||||
sizeof (rr)))
|
||||
{
|
||||
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
|
||||
"send");
|
||||
do_disconnect (dh);
|
||||
return;
|
||||
}
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Requested revocation of denomination key %s\n",
|
||||
GNUNET_h2s (&h_cs->hash));
|
||||
}
|
||||
|
||||
|
||||
struct TALER_DenominationCSPublicRPairP
|
||||
TALER_CRYPTO_helper_cs_r_derive (struct TALER_CRYPTO_CsDenominationHelper *dh,
|
||||
const struct TALER_CsPubHashP *h_cs,
|
||||
const struct TALER_CsNonce *nonce,
|
||||
enum TALER_ErrorCode *ec)
|
||||
{
|
||||
struct TALER_DenominationCSPublicRPairP r_pub;
|
||||
|
||||
memset (&r_pub,
|
||||
0,
|
||||
sizeof (r_pub));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Starting R derivation process\n");
|
||||
if (GNUNET_OK !=
|
||||
try_connect (dh))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Failed to connect to helper\n");
|
||||
*ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
|
||||
return r_pub;
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Requesting R\n");
|
||||
{
|
||||
struct TALER_CRYPTO_CsRDeriveRequest rdr;
|
||||
|
||||
rdr.header.size = htons (sizeof (rdr));
|
||||
rdr.header.type = htons (TALER_HELPER_CS_MT_REQ_RDERIVE);
|
||||
rdr.reserved = htonl (0);
|
||||
rdr.h_cs = *h_cs;
|
||||
rdr.nonce = *nonce;
|
||||
if (GNUNET_OK !=
|
||||
TALER_crypto_helper_send_all (dh->sock,
|
||||
&rdr,
|
||||
sizeof (rdr)))
|
||||
{
|
||||
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
|
||||
"send");
|
||||
do_disconnect (dh);
|
||||
*ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
|
||||
return r_pub;
|
||||
}
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Awaiting reply\n");
|
||||
{
|
||||
char buf[UINT16_MAX];
|
||||
size_t off = 0;
|
||||
const struct GNUNET_MessageHeader *hdr
|
||||
= (const struct GNUNET_MessageHeader *) buf;
|
||||
bool finished = false;
|
||||
|
||||
*ec = TALER_EC_INVALID;
|
||||
while (1)
|
||||
{
|
||||
uint16_t msize;
|
||||
ssize_t ret;
|
||||
|
||||
ret = recv (dh->sock,
|
||||
&buf[off],
|
||||
sizeof (buf) - off,
|
||||
(finished && (0 == off))
|
||||
? MSG_DONTWAIT
|
||||
: 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (EINTR == errno)
|
||||
continue;
|
||||
if (EAGAIN == errno)
|
||||
{
|
||||
GNUNET_assert (finished);
|
||||
GNUNET_assert (0 == off);
|
||||
return r_pub;
|
||||
}
|
||||
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
|
||||
"recv");
|
||||
do_disconnect (dh);
|
||||
*ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
|
||||
break;
|
||||
}
|
||||
if (0 == ret)
|
||||
{
|
||||
GNUNET_break (0 == off);
|
||||
if (! finished)
|
||||
*ec = TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
|
||||
return r_pub;
|
||||
}
|
||||
off += ret;
|
||||
more:
|
||||
if (off < sizeof (struct GNUNET_MessageHeader))
|
||||
continue;
|
||||
msize = ntohs (hdr->size);
|
||||
if (off < msize)
|
||||
continue;
|
||||
switch (ntohs (hdr->type))
|
||||
{
|
||||
case TALER_HELPER_CS_MT_RES_RDERIVE:
|
||||
if (msize != sizeof (struct TALER_CRYPTO_RDeriveResponse))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
do_disconnect (dh);
|
||||
*ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
|
||||
goto end;
|
||||
}
|
||||
if (finished)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
do_disconnect (dh);
|
||||
*ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
|
||||
goto end;
|
||||
}
|
||||
{
|
||||
const struct TALER_CRYPTO_RDeriveResponse *rdr =
|
||||
(const struct TALER_CRYPTO_RDeriveResponse *) buf;
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Received R\n");
|
||||
*ec = TALER_EC_NONE;
|
||||
finished = true;
|
||||
r_pub = rdr->r_pub;
|
||||
break;
|
||||
}
|
||||
case TALER_HELPER_CS_MT_RES_RDERIVE_FAILURE:
|
||||
if (msize != sizeof (struct TALER_CRYPTO_RDeriveFailure))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
do_disconnect (dh);
|
||||
*ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
|
||||
goto end;
|
||||
}
|
||||
{
|
||||
const struct TALER_CRYPTO_RDeriveFailure *rdf =
|
||||
(const struct TALER_CRYPTO_RDeriveFailure *) buf;
|
||||
|
||||
*ec = (enum TALER_ErrorCode) ntohl (rdf->ec);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"R derivation failed!\n");
|
||||
finished = true;
|
||||
break;
|
||||
}
|
||||
case TALER_HELPER_CS_MT_AVAIL:
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Received new key!\n");
|
||||
if (GNUNET_OK !=
|
||||
handle_mt_avail (dh,
|
||||
hdr))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
do_disconnect (dh);
|
||||
*ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
|
||||
goto end;
|
||||
}
|
||||
break; /* while(1) loop ensures we recvfrom() again */
|
||||
case TALER_HELPER_CS_MT_PURGE:
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Received revocation!\n");
|
||||
if (GNUNET_OK !=
|
||||
handle_mt_purge (dh,
|
||||
hdr))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
do_disconnect (dh);
|
||||
*ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
|
||||
goto end;
|
||||
}
|
||||
break; /* while(1) loop ensures we recvfrom() again */
|
||||
case TALER_HELPER_CS_SYNCED:
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Synchronized add odd time with CS helper!\n");
|
||||
dh->synced = true;
|
||||
break;
|
||||
default:
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Received unexpected message of type %u\n",
|
||||
ntohs (hdr->type));
|
||||
do_disconnect (dh);
|
||||
*ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
|
||||
goto end;
|
||||
}
|
||||
memmove (buf,
|
||||
&buf[msize],
|
||||
off - msize);
|
||||
off -= msize;
|
||||
goto more;
|
||||
} /* while(1) */
|
||||
end:
|
||||
return r_pub;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_CRYPTO_helper_cs_disconnect (
|
||||
struct TALER_CRYPTO_CsDenominationHelper *dh)
|
||||
{
|
||||
if (-1 != dh->sock)
|
||||
do_disconnect (dh);
|
||||
GNUNET_free (dh);
|
||||
}
|
||||
|
||||
|
||||
/* end of crypto_helper_cs.c */
|
@ -64,7 +64,7 @@ TALER_exchange_wire_signature_make (
|
||||
|
||||
void
|
||||
TALER_merchant_wire_signature_hash (const char *payto_uri,
|
||||
const struct TALER_WireSalt *salt,
|
||||
const struct TALER_WireSaltP *salt,
|
||||
struct TALER_MerchantWireHash *hc)
|
||||
{
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
@ -83,7 +83,7 @@ TALER_merchant_wire_signature_hash (const char *payto_uri,
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_merchant_wire_signature_check (
|
||||
const char *payto_uri,
|
||||
const struct TALER_WireSalt *salt,
|
||||
const struct TALER_WireSaltP *salt,
|
||||
const struct TALER_MerchantPublicKeyP *merch_pub,
|
||||
const struct TALER_MerchantSignatureP *merch_sig)
|
||||
{
|
||||
@ -105,7 +105,7 @@ TALER_merchant_wire_signature_check (
|
||||
void
|
||||
TALER_merchant_wire_signature_make (
|
||||
const char *payto_uri,
|
||||
const struct TALER_WireSalt *salt,
|
||||
const struct TALER_WireSaltP *salt,
|
||||
const struct TALER_MerchantPrivateKeyP *merch_priv,
|
||||
struct TALER_MerchantSignatureP *merch_sig)
|
||||
{
|
||||
|
279
src/util/denom.c
279
src/util/denom.c
@ -34,6 +34,7 @@ TALER_denom_priv_create (struct TALER_DenominationPrivateKey *denom_priv,
|
||||
memset (denom_pub,
|
||||
0,
|
||||
sizeof (*denom_pub));
|
||||
|
||||
switch (cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_INVALID:
|
||||
@ -63,10 +64,17 @@ TALER_denom_priv_create (struct TALER_DenominationPrivateKey *denom_priv,
|
||||
denom_pub->details.rsa_public_key
|
||||
= GNUNET_CRYPTO_rsa_private_key_get_public (
|
||||
denom_priv->details.rsa_private_key);
|
||||
denom_priv->cipher = cipher;
|
||||
denom_pub->cipher = cipher;
|
||||
denom_priv->cipher = TALER_DENOMINATION_RSA;
|
||||
denom_pub->cipher = TALER_DENOMINATION_RSA;
|
||||
return GNUNET_OK;
|
||||
case TALER_DENOMINATION_CS:
|
||||
GNUNET_CRYPTO_cs_private_key_generate (&denom_priv->details.cs_private_key);
|
||||
GNUNET_CRYPTO_cs_private_key_get_public (
|
||||
&denom_priv->details.cs_private_key,
|
||||
&denom_pub->details.cs_public_key);
|
||||
denom_priv->cipher = TALER_DENOMINATION_CS;
|
||||
denom_pub->cipher = TALER_DENOMINATION_CS;
|
||||
return GNUNET_OK;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
}
|
||||
@ -74,15 +82,43 @@ TALER_denom_priv_create (struct TALER_DenominationPrivateKey *denom_priv,
|
||||
}
|
||||
|
||||
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_denom_cs_derive_r_public (const struct TALER_CsNonce *nonce,
|
||||
const struct
|
||||
TALER_DenominationPrivateKey *denom_priv,
|
||||
struct TALER_DenominationCSPublicRPairP *r_pub)
|
||||
{
|
||||
if (denom_priv->cipher != TALER_DENOMINATION_CS)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
struct GNUNET_CRYPTO_CsRSecret r[2];
|
||||
GNUNET_CRYPTO_cs_r_derive (&nonce->nonce,
|
||||
&denom_priv->details.cs_private_key,
|
||||
r);
|
||||
GNUNET_CRYPTO_cs_r_get_public (&r[0], &r_pub->r_pub[0]);
|
||||
GNUNET_CRYPTO_cs_r_get_public (&r[1], &r_pub->r_pub[1]);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_denom_sign_blinded (struct TALER_BlindedDenominationSignature *denom_sig,
|
||||
const struct TALER_DenominationPrivateKey *denom_priv,
|
||||
void *blinded_msg,
|
||||
size_t blinded_msg_size)
|
||||
const struct TALER_BlindedPlanchet *blinded_planchet)
|
||||
{
|
||||
memset (denom_sig,
|
||||
0,
|
||||
sizeof (*denom_sig));
|
||||
|
||||
if (blinded_planchet->cipher != denom_priv->cipher)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
switch (denom_priv->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_INVALID:
|
||||
@ -92,8 +128,8 @@ TALER_denom_sign_blinded (struct TALER_BlindedDenominationSignature *denom_sig,
|
||||
denom_sig->details.blinded_rsa_signature
|
||||
= GNUNET_CRYPTO_rsa_sign_blinded (
|
||||
denom_priv->details.rsa_private_key,
|
||||
blinded_msg,
|
||||
blinded_msg_size);
|
||||
blinded_planchet->details.rsa_blinded_planchet.blinded_msg,
|
||||
blinded_planchet->details.rsa_blinded_planchet.blinded_msg_size);
|
||||
if (NULL == denom_sig->details.blinded_rsa_signature)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
@ -101,7 +137,27 @@ TALER_denom_sign_blinded (struct TALER_BlindedDenominationSignature *denom_sig,
|
||||
}
|
||||
denom_sig->cipher = TALER_DENOMINATION_RSA;
|
||||
return GNUNET_OK;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
{
|
||||
struct GNUNET_CRYPTO_CsRSecret r[2];
|
||||
GNUNET_CRYPTO_cs_r_derive (
|
||||
&blinded_planchet->details.cs_blinded_planchet.nonce.nonce,
|
||||
&denom_priv->details.cs_private_key,
|
||||
r);
|
||||
|
||||
denom_sig->details.blinded_cs_answer.b =
|
||||
GNUNET_CRYPTO_cs_sign_derive (&denom_priv->details.cs_private_key,
|
||||
r,
|
||||
blinded_planchet->details.
|
||||
cs_blinded_planchet.c,
|
||||
&blinded_planchet->details.
|
||||
cs_blinded_planchet.nonce.nonce,
|
||||
&denom_sig->details.blinded_cs_answer.
|
||||
s_scalar);
|
||||
|
||||
denom_sig->cipher = TALER_DENOMINATION_CS;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
}
|
||||
@ -139,7 +195,17 @@ TALER_denom_sig_unblind (
|
||||
}
|
||||
denom_sig->cipher = TALER_DENOMINATION_RSA;
|
||||
return GNUNET_OK;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
{
|
||||
struct GNUNET_CRYPTO_CsBlindingSecret bs[2];
|
||||
GNUNET_CRYPTO_cs_blinding_secrets_derive (&bks->nonce, bs);
|
||||
|
||||
GNUNET_CRYPTO_cs_unblind (&bdenom_sig->details.blinded_cs_answer.s_scalar,
|
||||
&bs[bdenom_sig->details.blinded_cs_answer.b],
|
||||
&denom_sig->details.cs_signature.s_scalar);
|
||||
denom_sig->cipher = TALER_DENOMINATION_CS;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
}
|
||||
@ -147,15 +213,6 @@ TALER_denom_sig_unblind (
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_blinding_secret_create (union TALER_DenominationBlindingKeyP *bs)
|
||||
{
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
|
||||
bs,
|
||||
sizeof (*bs));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Hash @a rsa.
|
||||
*
|
||||
@ -172,6 +229,22 @@ TALER_rsa_pub_hash (const struct GNUNET_CRYPTO_RsaPublicKey *rsa,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Hash @a cs. key
|
||||
*
|
||||
* @param cs key to hash
|
||||
* @param[out] h_cs where to write the result
|
||||
*/
|
||||
void
|
||||
TALER_cs_pub_hash (const struct GNUNET_CRYPTO_CsPublicKey *cs,
|
||||
struct TALER_CsPubHashP *h_cs)
|
||||
{
|
||||
GNUNET_CRYPTO_hash (cs,
|
||||
sizeof(*cs),
|
||||
&h_cs->hash);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_denom_pub_hash (const struct TALER_DenominationPublicKey *denom_pub,
|
||||
struct TALER_DenominationHash *denom_hash)
|
||||
@ -202,7 +275,11 @@ TALER_denom_pub_hash (const struct TALER_DenominationPublicKey *denom_pub,
|
||||
GNUNET_free (buf);
|
||||
}
|
||||
break;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
GNUNET_CRYPTO_hash_context_read (hc,
|
||||
&denom_pub->details.cs_public_key,
|
||||
sizeof(denom_pub->details.cs_public_key));
|
||||
break;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -225,7 +302,13 @@ TALER_denom_priv_to_pub (const struct TALER_DenominationPrivateKey *denom_priv,
|
||||
= GNUNET_CRYPTO_rsa_private_key_get_public (
|
||||
denom_priv->details.rsa_private_key);
|
||||
return;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
denom_pub->cipher = TALER_DENOMINATION_CS;
|
||||
denom_pub->age_mask = age_mask;
|
||||
GNUNET_CRYPTO_cs_private_key_get_public (
|
||||
&denom_priv->details.cs_private_key,
|
||||
&denom_pub->details.cs_public_key);
|
||||
return;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -233,32 +316,55 @@ TALER_denom_priv_to_pub (const struct TALER_DenominationPrivateKey *denom_priv,
|
||||
|
||||
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_denom_blind (const struct TALER_DenominationPublicKey *dk,
|
||||
TALER_denom_blind (
|
||||
const struct TALER_DenominationPublicKey *dk,
|
||||
const union TALER_DenominationBlindingKeyP *coin_bks,
|
||||
const struct TALER_AgeHash *age_commitment_hash,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
const struct TALER_ExchangeWithdrawValues *alg_values,
|
||||
struct TALER_CoinPubHash *c_hash,
|
||||
void **coin_ev,
|
||||
size_t *coin_ev_size)
|
||||
struct TALER_BlindedPlanchet *blinded_planchet)
|
||||
{
|
||||
switch (dk->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
TALER_coin_pub_hash (coin_pub,
|
||||
age_commitment_hash,
|
||||
c_hash);
|
||||
switch (dk->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
blinded_planchet->cipher = dk->cipher;
|
||||
|
||||
if (GNUNET_YES !=
|
||||
GNUNET_CRYPTO_rsa_blind (&c_hash->hash,
|
||||
&coin_bks->rsa_bks,
|
||||
dk->details.rsa_public_key,
|
||||
coin_ev,
|
||||
coin_ev_size))
|
||||
&blinded_planchet->details.rsa_blinded_planchet
|
||||
.blinded_msg,
|
||||
&blinded_planchet->details.rsa_blinded_planchet
|
||||
.blinded_msg_size))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
{
|
||||
blinded_planchet->cipher = dk->cipher;
|
||||
struct TALER_DenominationCSPublicRPairP blinded_r_pub;
|
||||
struct GNUNET_CRYPTO_CsBlindingSecret bs[2];
|
||||
|
||||
GNUNET_CRYPTO_cs_blinding_secrets_derive (&coin_bks->nonce,
|
||||
bs);
|
||||
GNUNET_CRYPTO_cs_calc_blinded_c (
|
||||
bs,
|
||||
alg_values->details.cs_values.r_pub_pair.r_pub,
|
||||
&dk->details.cs_public_key,
|
||||
&c_hash->hash,
|
||||
sizeof(struct GNUNET_HashCode),
|
||||
blinded_planchet->details.
|
||||
cs_blinded_planchet.c,
|
||||
blinded_r_pub.r_pub);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
@ -276,6 +382,7 @@ TALER_denom_pub_verify (const struct TALER_DenominationPublicKey *denom_pub,
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
switch (denom_pub->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_INVALID:
|
||||
@ -292,7 +399,18 @@ TALER_denom_pub_verify (const struct TALER_DenominationPublicKey *denom_pub,
|
||||
return GNUNET_NO;
|
||||
}
|
||||
return GNUNET_YES;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CRYPTO_cs_verify (&denom_sig->details.cs_signature,
|
||||
&denom_pub->details.cs_public_key,
|
||||
&c_hash->hash,
|
||||
sizeof(struct GNUNET_HashCode)))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Coin signature is invalid\n");
|
||||
return GNUNET_NO;
|
||||
}
|
||||
return GNUNET_YES;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -314,7 +432,9 @@ TALER_denom_pub_free (struct TALER_DenominationPublicKey *denom_pub)
|
||||
}
|
||||
denom_pub->cipher = TALER_DENOMINATION_INVALID;
|
||||
return;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
// ATM nothing needs to be freed, but check again after implementation.
|
||||
return;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -336,7 +456,9 @@ TALER_denom_priv_free (struct TALER_DenominationPrivateKey *denom_priv)
|
||||
}
|
||||
denom_priv->cipher = TALER_DENOMINATION_INVALID;
|
||||
return;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
// ATM nothing needs to be freed, but check again after implementation.
|
||||
return;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -358,7 +480,9 @@ TALER_denom_sig_free (struct TALER_DenominationSignature *denom_sig)
|
||||
}
|
||||
denom_sig->cipher = TALER_DENOMINATION_INVALID;
|
||||
return;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
// ATM nothing needs to be freed, but check again after implementation.
|
||||
return;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -382,7 +506,9 @@ TALER_blinded_denom_sig_free (
|
||||
}
|
||||
denom_sig->cipher = TALER_DENOMINATION_INVALID;
|
||||
return;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
// ATM nothing needs to be freed, but check again after implementation.
|
||||
return;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -408,7 +534,9 @@ TALER_denom_pub_deep_copy (struct TALER_DenominationPublicKey *denom_dst,
|
||||
= GNUNET_CRYPTO_rsa_public_key_dup (
|
||||
denom_src->details.rsa_public_key);
|
||||
return;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
// In Case of CS, the above is already a deep copy *denom_dst = *denom_src;
|
||||
return;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -429,7 +557,9 @@ TALER_denom_sig_deep_copy (struct TALER_DenominationSignature *denom_dst,
|
||||
= GNUNET_CRYPTO_rsa_signature_dup (
|
||||
denom_src->details.rsa_signature);
|
||||
return;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
// In Case of CS, the above is already a deep copy *denom_dst = *denom_src;
|
||||
return;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -451,7 +581,9 @@ TALER_blinded_denom_sig_deep_copy (
|
||||
= GNUNET_CRYPTO_rsa_signature_dup (
|
||||
denom_src->details.blinded_rsa_signature);
|
||||
return;
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
// In Case of CS, the above is already a deep copy *denom_dst = *denom_src;
|
||||
return;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -473,7 +605,9 @@ TALER_denom_pub_cmp (const struct TALER_DenominationPublicKey *denom1,
|
||||
case TALER_DENOMINATION_RSA:
|
||||
return GNUNET_CRYPTO_rsa_public_key_cmp (denom1->details.rsa_public_key,
|
||||
denom2->details.rsa_public_key);
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
return GNUNET_memcmp (&denom1->details.cs_public_key,
|
||||
&denom2->details.cs_public_key);
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -494,7 +628,38 @@ TALER_denom_sig_cmp (const struct TALER_DenominationSignature *sig1,
|
||||
case TALER_DENOMINATION_RSA:
|
||||
return GNUNET_CRYPTO_rsa_signature_cmp (sig1->details.rsa_signature,
|
||||
sig2->details.rsa_signature);
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
return GNUNET_memcmp (&sig1->details.cs_signature,
|
||||
&sig2->details.cs_signature);
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
TALER_blinded_planchet_cmp (
|
||||
const struct TALER_BlindedPlanchet *bp1,
|
||||
const struct TALER_BlindedPlanchet *bp2)
|
||||
{
|
||||
if (bp1->cipher != bp2->cipher)
|
||||
return (bp1->cipher > bp2->cipher) ? 1 : -1;
|
||||
switch (bp1->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_INVALID:
|
||||
return 0;
|
||||
case TALER_DENOMINATION_RSA:
|
||||
if (bp1->details.rsa_blinded_planchet.blinded_msg_size !=
|
||||
bp2->details.rsa_blinded_planchet.blinded_msg_size)
|
||||
return (bp1->details.rsa_blinded_planchet.blinded_msg_size >
|
||||
bp2->details.rsa_blinded_planchet.blinded_msg_size) ? 1 : -1;
|
||||
return memcmp (bp1->details.rsa_blinded_planchet.blinded_msg,
|
||||
bp2->details.rsa_blinded_planchet.blinded_msg,
|
||||
bp1->details.rsa_blinded_planchet.blinded_msg_size);
|
||||
case TALER_DENOMINATION_CS:
|
||||
return GNUNET_memcmp (&bp1->details.cs_blinded_planchet,
|
||||
&bp2->details.cs_blinded_planchet);
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -516,7 +681,9 @@ TALER_blinded_denom_sig_cmp (
|
||||
case TALER_DENOMINATION_RSA:
|
||||
return GNUNET_CRYPTO_rsa_signature_cmp (sig1->details.blinded_rsa_signature,
|
||||
sig2->details.blinded_rsa_signature);
|
||||
// TODO: add case for Clause-Schnorr
|
||||
case TALER_DENOMINATION_CS:
|
||||
return GNUNET_memcmp (&sig1->details.blinded_cs_answer,
|
||||
&sig2->details.blinded_cs_answer);
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
@ -524,4 +691,36 @@ TALER_blinded_denom_sig_cmp (
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_blinded_planchet_hash (const struct TALER_BlindedPlanchet *bp,
|
||||
struct GNUNET_HashContext *hash_context)
|
||||
{
|
||||
uint32_t cipher = htonl (bp->cipher);
|
||||
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
&cipher,
|
||||
sizeof (cipher));
|
||||
switch (bp->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_INVALID:
|
||||
break;
|
||||
case TALER_DENOMINATION_RSA:
|
||||
GNUNET_CRYPTO_hash_context_read (
|
||||
hash_context,
|
||||
bp->details.rsa_blinded_planchet.blinded_msg,
|
||||
bp->details.rsa_blinded_planchet.blinded_msg_size);
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
GNUNET_CRYPTO_hash_context_read (
|
||||
hash_context,
|
||||
&bp->details.cs_blinded_planchet,
|
||||
sizeof (bp->details.cs_blinded_planchet));
|
||||
break;
|
||||
default:
|
||||
GNUNET_assert (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* end of denom.c */
|
||||
|
@ -81,7 +81,7 @@ TALER_exchange_secmod_rsa_sign (
|
||||
struct TALER_DenominationKeyAnnouncementPS dka = {
|
||||
.purpose.purpose = htonl (TALER_SIGNATURE_SM_RSA_DENOMINATION_KEY),
|
||||
.purpose.size = htonl (sizeof (dka)),
|
||||
.h_rsa = *h_rsa,
|
||||
.h_denom.hash = h_rsa->hash,
|
||||
.anchor_time = GNUNET_TIME_timestamp_hton (start_sign),
|
||||
.duration_withdraw = GNUNET_TIME_relative_hton (duration)
|
||||
};
|
||||
@ -108,7 +108,7 @@ TALER_exchange_secmod_rsa_verify (
|
||||
struct TALER_DenominationKeyAnnouncementPS dka = {
|
||||
.purpose.purpose = htonl (TALER_SIGNATURE_SM_RSA_DENOMINATION_KEY),
|
||||
.purpose.size = htonl (sizeof (dka)),
|
||||
.h_rsa = *h_rsa,
|
||||
.h_denom.hash = h_rsa->hash,
|
||||
.anchor_time = GNUNET_TIME_timestamp_hton (start_sign),
|
||||
.duration_withdraw = GNUNET_TIME_relative_hton (duration)
|
||||
};
|
||||
@ -124,4 +124,59 @@ TALER_exchange_secmod_rsa_verify (
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_exchange_secmod_cs_sign (
|
||||
const struct TALER_CsPubHashP *h_cs,
|
||||
const char *section_name,
|
||||
struct GNUNET_TIME_Timestamp start_sign,
|
||||
struct GNUNET_TIME_Relative duration,
|
||||
const struct TALER_SecurityModulePrivateKeyP *secm_priv,
|
||||
struct TALER_SecurityModuleSignatureP *secm_sig)
|
||||
{
|
||||
struct TALER_DenominationKeyAnnouncementPS dka = {
|
||||
.purpose.purpose = htonl (TALER_SIGNATURE_SM_CS_DENOMINATION_KEY),
|
||||
.purpose.size = htonl (sizeof (dka)),
|
||||
.h_denom.hash = h_cs->hash,
|
||||
.anchor_time = GNUNET_TIME_timestamp_hton (start_sign),
|
||||
.duration_withdraw = GNUNET_TIME_relative_hton (duration)
|
||||
};
|
||||
|
||||
GNUNET_CRYPTO_hash (section_name,
|
||||
strlen (section_name) + 1,
|
||||
&dka.h_section_name);
|
||||
GNUNET_CRYPTO_eddsa_sign (&secm_priv->eddsa_priv,
|
||||
&dka,
|
||||
&secm_sig->eddsa_signature);
|
||||
|
||||
}
|
||||
|
||||
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_exchange_secmod_cs_verify (
|
||||
const struct TALER_CsPubHashP *h_cs,
|
||||
const char *section_name,
|
||||
struct GNUNET_TIME_Timestamp start_sign,
|
||||
struct GNUNET_TIME_Relative duration,
|
||||
const struct TALER_SecurityModulePublicKeyP *secm_pub,
|
||||
const struct TALER_SecurityModuleSignatureP *secm_sig)
|
||||
{
|
||||
struct TALER_DenominationKeyAnnouncementPS dka = {
|
||||
.purpose.purpose = htonl (TALER_SIGNATURE_SM_CS_DENOMINATION_KEY),
|
||||
.purpose.size = htonl (sizeof (dka)),
|
||||
.h_denom.hash = h_cs->hash,
|
||||
.anchor_time = GNUNET_TIME_timestamp_hton (start_sign),
|
||||
.duration_withdraw = GNUNET_TIME_relative_hton (duration)
|
||||
};
|
||||
|
||||
GNUNET_CRYPTO_hash (section_name,
|
||||
strlen (section_name) + 1,
|
||||
&dka.h_section_name);
|
||||
return
|
||||
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_SM_CS_DENOMINATION_KEY,
|
||||
&dka,
|
||||
&secm_sig->eddsa_signature,
|
||||
&secm_pub->eddsa_pub);
|
||||
}
|
||||
|
||||
|
||||
/* end of secmod_signatures.c */
|
||||
|
1621
src/util/taler-exchange-secmod-cs.c
Normal file
1621
src/util/taler-exchange-secmod-cs.c
Normal file
File diff suppressed because it is too large
Load Diff
23
src/util/taler-exchange-secmod-cs.conf
Normal file
23
src/util/taler-exchange-secmod-cs.conf
Normal file
@ -0,0 +1,23 @@
|
||||
[taler-exchange-secmod-cs]
|
||||
|
||||
# How long should generated coins overlap in their validity
|
||||
# periods. Should be long enough to avoid problems with
|
||||
# wallets picking one key and then due to network latency
|
||||
# another key being valid. The DURATION_WITHDRAW period
|
||||
# must be longer than this value.
|
||||
OVERLAP_DURATION = 5 m
|
||||
|
||||
# Where do we store the generated private keys.
|
||||
KEY_DIR = ${TALER_DATA_HOME}/exchange-secmod-cs/keys
|
||||
|
||||
# Where does the helper listen for requests?
|
||||
UNIXPATH = $TALER_RUNTIME_DIR/exchange-secmod-cs/server.sock
|
||||
|
||||
# Directory for clients.
|
||||
CLIENT_DIR = $TALER_RUNTIME_DIR/exchange-secmod-cs/clients
|
||||
|
||||
# Where should the security module store its own private key?
|
||||
SM_PRIV_KEY = ${TALER_DATA_HOME}/exchange-secmod-cs/secmod-private-key
|
||||
|
||||
# For how long into the future do we pre-generate keys?
|
||||
LOOKAHEAD_SIGN = 1 year
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user