Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2020, 2024 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 3, or (at your option) any later version.
8 :
9 : TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 : WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 : A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 :
13 : You should have received a copy of the GNU General Public License along with
14 : TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
15 : */
16 : /**
17 : * @file merchant_signatures.c
18 : * @brief Utility functions for Taler merchant signatures
19 : * @author Christian Grothoff
20 : */
21 : #include "taler/taler_util.h"
22 : #include "taler/taler_signatures.h"
23 :
24 :
25 : GNUNET_NETWORK_STRUCT_BEGIN
26 :
27 : /**
28 : * @brief Format used to generate the signature on a request to obtain
29 : * the wire transfer identifier associated with a deposit.
30 : */
31 : struct TALER_DepositTrackPS
32 : {
33 : /**
34 : * Purpose must be #TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION.
35 : */
36 : struct GNUNET_CRYPTO_SignaturePurpose purpose;
37 :
38 : /**
39 : * Hash over the proposal data of the contract for which this deposit is made.
40 : */
41 : struct TALER_PrivateContractHashP h_contract_terms GNUNET_PACKED;
42 :
43 : /**
44 : * Hash over the wiring information of the merchant.
45 : */
46 : struct TALER_MerchantWireHashP h_wire GNUNET_PACKED;
47 :
48 : /**
49 : * The coin's public key. This is the value that must have been
50 : * signed (blindly) by the Exchange.
51 : */
52 : struct TALER_CoinSpendPublicKeyP coin_pub;
53 :
54 : };
55 :
56 : GNUNET_NETWORK_STRUCT_END
57 :
58 :
59 : void
60 8 : TALER_merchant_deposit_sign (
61 : const struct TALER_PrivateContractHashP *h_contract_terms,
62 : const struct TALER_MerchantWireHashP *h_wire,
63 : const struct TALER_CoinSpendPublicKeyP *coin_pub,
64 : const struct TALER_MerchantPrivateKeyP *merchant_priv,
65 : struct TALER_MerchantSignatureP *merchant_sig)
66 : {
67 8 : struct TALER_DepositTrackPS dtp = {
68 8 : .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION),
69 8 : .purpose.size = htonl (sizeof (dtp)),
70 : .h_contract_terms = *h_contract_terms,
71 : .h_wire = *h_wire,
72 : .coin_pub = *coin_pub
73 : };
74 :
75 8 : GNUNET_CRYPTO_eddsa_sign (&merchant_priv->eddsa_priv,
76 : &dtp,
77 : &merchant_sig->eddsa_sig);
78 8 : }
79 :
80 :
81 : enum GNUNET_GenericReturnValue
82 8 : TALER_merchant_deposit_verify (
83 : const struct TALER_MerchantPublicKeyP *merchant,
84 : const struct TALER_CoinSpendPublicKeyP *coin_pub,
85 : const struct TALER_PrivateContractHashP *h_contract_terms,
86 : const struct TALER_MerchantWireHashP *h_wire,
87 : const struct TALER_MerchantSignatureP *merchant_sig)
88 : {
89 8 : struct TALER_DepositTrackPS tps = {
90 8 : .purpose.size = htonl (sizeof (tps)),
91 8 : .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION),
92 : .coin_pub = *coin_pub,
93 : .h_contract_terms = *h_contract_terms,
94 : .h_wire = *h_wire
95 : };
96 :
97 8 : return GNUNET_CRYPTO_eddsa_verify (
98 : TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION,
99 : &tps,
100 : &merchant_sig->eddsa_sig,
101 : &merchant->eddsa_pub);
102 : }
103 :
104 :
105 : /**
106 : * @brief Format used to generate the signature on a request to refund
107 : * a coin into the account of the customer.
108 : */
109 : struct TALER_RefundRequestPS
110 : {
111 : /**
112 : * Purpose must be #TALER_SIGNATURE_MERCHANT_REFUND.
113 : */
114 : struct GNUNET_CRYPTO_SignaturePurpose purpose;
115 :
116 : /**
117 : * Hash over the proposal data to identify the contract
118 : * which is being refunded.
119 : */
120 : struct TALER_PrivateContractHashP h_contract_terms GNUNET_PACKED;
121 :
122 : /**
123 : * The coin's public key. This is the value that must have been
124 : * signed (blindly) by the Exchange.
125 : */
126 : struct TALER_CoinSpendPublicKeyP coin_pub;
127 :
128 : /**
129 : * Merchant-generated transaction ID for the refund.
130 : */
131 : uint64_t rtransaction_id GNUNET_PACKED;
132 :
133 : /**
134 : * Amount to be refunded, including refund fee charged by the
135 : * exchange to the customer.
136 : */
137 : struct TALER_AmountNBO refund_amount;
138 : };
139 :
140 :
141 : void
142 28 : TALER_merchant_refund_sign (
143 : const struct TALER_CoinSpendPublicKeyP *coin_pub,
144 : const struct TALER_PrivateContractHashP *h_contract_terms,
145 : uint64_t rtransaction_id,
146 : const struct TALER_Amount *amount,
147 : const struct TALER_MerchantPrivateKeyP *merchant_priv,
148 : struct TALER_MerchantSignatureP *merchant_sig)
149 : {
150 56 : struct TALER_RefundRequestPS rr = {
151 28 : .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND),
152 28 : .purpose.size = htonl (sizeof (rr)),
153 : .h_contract_terms = *h_contract_terms,
154 : .coin_pub = *coin_pub,
155 28 : .rtransaction_id = GNUNET_htonll (rtransaction_id)
156 : };
157 :
158 28 : TALER_amount_hton (&rr.refund_amount,
159 : amount);
160 28 : GNUNET_CRYPTO_eddsa_sign (&merchant_priv->eddsa_priv,
161 : &rr,
162 : &merchant_sig->eddsa_sig);
163 28 : }
164 :
165 :
166 : enum GNUNET_GenericReturnValue
167 14 : TALER_merchant_refund_verify (
168 : const struct TALER_CoinSpendPublicKeyP *coin_pub,
169 : const struct TALER_PrivateContractHashP *h_contract_terms,
170 : uint64_t rtransaction_id,
171 : const struct TALER_Amount *amount,
172 : const struct TALER_MerchantPublicKeyP *merchant_pub,
173 : const struct TALER_MerchantSignatureP *merchant_sig)
174 : {
175 28 : struct TALER_RefundRequestPS rr = {
176 14 : .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND),
177 14 : .purpose.size = htonl (sizeof (rr)),
178 : .h_contract_terms = *h_contract_terms,
179 : .coin_pub = *coin_pub,
180 14 : .rtransaction_id = GNUNET_htonll (rtransaction_id)
181 : };
182 :
183 14 : TALER_amount_hton (&rr.refund_amount,
184 : amount);
185 14 : return GNUNET_CRYPTO_eddsa_verify (
186 : TALER_SIGNATURE_MERCHANT_REFUND,
187 : &rr,
188 : &merchant_sig->eddsa_sig,
189 : &merchant_pub->eddsa_pub);
190 : }
191 :
192 :
193 : /**
194 : * @brief Information signed by the exchange's master
195 : * key affirming the IBAN details for the exchange.
196 : */
197 : struct TALER_MerchantWireDetailsPS
198 : {
199 :
200 : /**
201 : * Purpose is #TALER_SIGNATURE_MERCHANT_WIRE_DETAILS.
202 : */
203 : struct GNUNET_CRYPTO_SignaturePurpose purpose;
204 :
205 : /**
206 : * Salted hash over the account holder's payto:// URL and
207 : * the salt, as done by #TALER_merchant_wire_signature_hash().
208 : */
209 : struct TALER_MerchantWireHashP h_wire_details GNUNET_PACKED;
210 :
211 : };
212 :
213 :
214 : enum GNUNET_GenericReturnValue
215 3 : TALER_merchant_wire_signature_check (
216 : const struct TALER_FullPayto payto_uri,
217 : const struct TALER_WireSaltP *salt,
218 : const struct TALER_MerchantPublicKeyP *merch_pub,
219 : const struct TALER_MerchantSignatureP *merch_sig)
220 : {
221 3 : struct TALER_MerchantWireDetailsPS wd = {
222 3 : .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_WIRE_DETAILS),
223 3 : .purpose.size = htonl (sizeof (wd))
224 : };
225 :
226 3 : TALER_merchant_wire_signature_hash (payto_uri,
227 : salt,
228 : &wd.h_wire_details);
229 3 : return GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_WIRE_DETAILS,
230 : &wd,
231 : &merch_sig->eddsa_sig,
232 : &merch_pub->eddsa_pub);
233 : }
234 :
235 :
236 : void
237 1 : TALER_merchant_wire_signature_make (
238 : const struct TALER_FullPayto payto_uri,
239 : const struct TALER_WireSaltP *salt,
240 : const struct TALER_MerchantPrivateKeyP *merch_priv,
241 : struct TALER_MerchantSignatureP *merch_sig)
242 : {
243 1 : struct TALER_MerchantWireDetailsPS wd = {
244 1 : .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_WIRE_DETAILS),
245 1 : .purpose.size = htonl (sizeof (wd))
246 : };
247 :
248 1 : TALER_merchant_wire_signature_hash (payto_uri,
249 : salt,
250 : &wd.h_wire_details);
251 1 : GNUNET_CRYPTO_eddsa_sign (&merch_priv->eddsa_priv,
252 : &wd,
253 : &merch_sig->eddsa_sig);
254 1 : }
255 :
256 :
257 : /**
258 : * Used by merchants to return signed responses to /pay requests.
259 : * Currently only used to return 200 OK signed responses.
260 : */
261 : struct TALER_PaymentResponsePS
262 : {
263 : /**
264 : * Set to #TALER_SIGNATURE_MERCHANT_PAYMENT_OK. Note that
265 : * unsuccessful payments are usually proven by some exchange's signature.
266 : */
267 : struct GNUNET_CRYPTO_SignaturePurpose purpose;
268 :
269 : /**
270 : * Hash of the proposal data associated with this confirmation
271 : */
272 : struct TALER_PrivateContractHashP h_contract_terms;
273 : };
274 :
275 : void
276 0 : TALER_merchant_pay_sign (
277 : const struct TALER_PrivateContractHashP *h_contract_terms,
278 : const struct TALER_MerchantPrivateKeyP *merch_priv,
279 : struct TALER_MerchantSignatureP *merch_sig)
280 : {
281 0 : struct TALER_PaymentResponsePS mr = {
282 0 : .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_PAYMENT_OK),
283 0 : .purpose.size = htonl (sizeof (mr)),
284 : .h_contract_terms = *h_contract_terms
285 : };
286 :
287 0 : GNUNET_CRYPTO_eddsa_sign (&merch_priv->eddsa_priv,
288 : &mr,
289 : &merch_sig->eddsa_sig);
290 0 : }
291 :
292 :
293 : enum GNUNET_GenericReturnValue
294 0 : TALER_merchant_pay_verify (
295 : const struct TALER_PrivateContractHashP *h_contract_terms,
296 : const struct TALER_MerchantPublicKeyP *merchant_pub,
297 : const struct TALER_MerchantSignatureP *merchant_sig)
298 : {
299 0 : struct TALER_PaymentResponsePS pr = {
300 0 : .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_PAYMENT_OK),
301 0 : .purpose.size = htonl (sizeof (pr)),
302 : .h_contract_terms = *h_contract_terms
303 : };
304 :
305 0 : return GNUNET_CRYPTO_eddsa_verify (
306 : TALER_SIGNATURE_MERCHANT_PAYMENT_OK,
307 : &pr,
308 : &merchant_sig->eddsa_sig,
309 : &merchant_pub->eddsa_pub);
310 : }
311 :
312 :
313 : /**
314 : * The contract sent by the merchant to the wallet.
315 : */
316 : struct TALER_ProposalDataPS
317 : {
318 : /**
319 : * Purpose header for the signature over the proposal data
320 : * with purpose #TALER_SIGNATURE_MERCHANT_CONTRACT.
321 : */
322 : struct GNUNET_CRYPTO_SignaturePurpose purpose;
323 :
324 : /**
325 : * Hash of the JSON contract in UTF-8 including 0-termination,
326 : * using JSON_COMPACT | JSON_SORT_KEYS
327 : */
328 : struct TALER_PrivateContractHashP hash;
329 : };
330 :
331 :
332 : void
333 98 : TALER_merchant_contract_sign (
334 : const struct TALER_PrivateContractHashP *h_contract_terms,
335 : const struct TALER_MerchantPrivateKeyP *merchant_priv,
336 : struct TALER_MerchantSignatureP *merchant_sig)
337 : {
338 98 : struct TALER_ProposalDataPS pdps = {
339 98 : .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT),
340 98 : .purpose.size = htonl (sizeof (pdps)),
341 : .hash = *h_contract_terms
342 : };
343 :
344 98 : GNUNET_CRYPTO_eddsa_sign (&merchant_priv->eddsa_priv,
345 : &pdps,
346 : &merchant_sig->eddsa_sig);
347 98 : }
348 :
349 :
350 : enum GNUNET_GenericReturnValue
351 98 : TALER_merchant_contract_verify (
352 : const struct TALER_PrivateContractHashP *h_contract_terms,
353 : const struct TALER_MerchantPublicKeyP *merchant_pub,
354 : struct TALER_MerchantSignatureP *merchant_sig)
355 : {
356 98 : struct TALER_ProposalDataPS pdps = {
357 98 : .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT),
358 98 : .purpose.size = htonl (sizeof (pdps)),
359 : .hash = *h_contract_terms
360 : };
361 :
362 98 : return GNUNET_CRYPTO_eddsa_verify (
363 : TALER_SIGNATURE_MERCHANT_CONTRACT,
364 : &pdps,
365 : &merchant_sig->eddsa_sig,
366 : &merchant_pub->eddsa_pub);
367 : }
368 :
369 :
370 : /* end of merchant_signatures.c */
|