merchant_signatures.c (10816B)
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 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 struct TALER_DepositTrackPS dtp = { 68 .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION), 69 .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 GNUNET_CRYPTO_eddsa_sign (&merchant_priv->eddsa_priv, 76 &dtp, 77 &merchant_sig->eddsa_sig); 78 } 79 80 81 enum GNUNET_GenericReturnValue 82 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 struct TALER_DepositTrackPS tps = { 90 .purpose.size = htonl (sizeof (tps)), 91 .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 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 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 struct TALER_RefundRequestPS rr = { 151 .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND), 152 .purpose.size = htonl (sizeof (rr)), 153 .h_contract_terms = *h_contract_terms, 154 .coin_pub = *coin_pub, 155 .rtransaction_id = GNUNET_htonll (rtransaction_id) 156 }; 157 158 TALER_amount_hton (&rr.refund_amount, 159 amount); 160 GNUNET_CRYPTO_eddsa_sign (&merchant_priv->eddsa_priv, 161 &rr, 162 &merchant_sig->eddsa_sig); 163 } 164 165 166 enum GNUNET_GenericReturnValue 167 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 struct TALER_RefundRequestPS rr = { 176 .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND), 177 .purpose.size = htonl (sizeof (rr)), 178 .h_contract_terms = *h_contract_terms, 179 .coin_pub = *coin_pub, 180 .rtransaction_id = GNUNET_htonll (rtransaction_id) 181 }; 182 183 TALER_amount_hton (&rr.refund_amount, 184 amount); 185 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 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 struct TALER_MerchantWireDetailsPS wd = { 222 .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_WIRE_DETAILS), 223 .purpose.size = htonl (sizeof (wd)) 224 }; 225 226 TALER_merchant_wire_signature_hash (payto_uri, 227 salt, 228 &wd.h_wire_details); 229 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 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 struct TALER_MerchantWireDetailsPS wd = { 244 .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_WIRE_DETAILS), 245 .purpose.size = htonl (sizeof (wd)) 246 }; 247 248 TALER_merchant_wire_signature_hash (payto_uri, 249 salt, 250 &wd.h_wire_details); 251 GNUNET_CRYPTO_eddsa_sign (&merch_priv->eddsa_priv, 252 &wd, 253 &merch_sig->eddsa_sig); 254 } 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 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 struct TALER_PaymentResponsePS mr = { 282 .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_PAYMENT_OK), 283 .purpose.size = htonl (sizeof (mr)), 284 .h_contract_terms = *h_contract_terms 285 }; 286 287 GNUNET_CRYPTO_eddsa_sign (&merch_priv->eddsa_priv, 288 &mr, 289 &merch_sig->eddsa_sig); 290 } 291 292 293 enum GNUNET_GenericReturnValue 294 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 struct TALER_PaymentResponsePS pr = { 300 .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_PAYMENT_OK), 301 .purpose.size = htonl (sizeof (pr)), 302 .h_contract_terms = *h_contract_terms 303 }; 304 305 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 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 struct TALER_ProposalDataPS pdps = { 339 .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT), 340 .purpose.size = htonl (sizeof (pdps)), 341 .hash = *h_contract_terms 342 }; 343 344 GNUNET_CRYPTO_eddsa_sign (&merchant_priv->eddsa_priv, 345 &pdps, 346 &merchant_sig->eddsa_sig); 347 } 348 349 350 enum GNUNET_GenericReturnValue 351 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 struct TALER_ProposalDataPS pdps = { 357 .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT), 358 .purpose.size = htonl (sizeof (pdps)), 359 .hash = *h_contract_terms 360 }; 361 362 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 */