exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

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 */