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