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