exchange

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

test_crypto.c (23830B)


      1 /*
      2   This file is part of TALER
      3   (C) 2015, 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 /**
     18  * @file util/test_crypto.c
     19  * @brief Tests for Taler-specific crypto logic
     20  * @author Christian Grothoff <christian@grothoff.org>
     21  */
     22 #include "taler/taler_util.h"
     23 
     24 
     25 /**
     26  * Test high-level link encryption/decryption API.
     27  *
     28  * @return 0 on success
     29  */
     30 static int
     31 test_high_level (void)
     32 {
     33   struct TALER_CoinSpendPrivateKeyP coin_priv;
     34   struct TALER_CoinSpendPublicKeyP coin_pub;
     35   struct TALER_TransferPrivateKeyP trans_priv;
     36   struct TALER_TransferPublicKeyP trans_pub;
     37   struct TALER_TransferSecretP secret;
     38   struct TALER_TransferSecretP secret2;
     39   union GNUNET_CRYPTO_BlindingSecretP bks1;
     40   union GNUNET_CRYPTO_BlindingSecretP bks2;
     41   struct TALER_CoinSpendPrivateKeyP coin_priv1;
     42   struct TALER_CoinSpendPrivateKeyP coin_priv2;
     43   struct TALER_PlanchetMasterSecretP ps1;
     44   struct TALER_PlanchetMasterSecretP ps2;
     45   struct GNUNET_CRYPTO_BlindingInputValues bi = {
     46     .cipher = GNUNET_CRYPTO_BSA_RSA
     47   };
     48   struct TALER_ExchangeBlindingValues alg1 = {
     49     .blinding_inputs = &bi
     50   };
     51   struct TALER_ExchangeBlindingValues alg2 = {
     52     .blinding_inputs = &bi
     53   };
     54 
     55   GNUNET_CRYPTO_eddsa_key_create (&coin_priv.eddsa_priv);
     56   GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv.eddsa_priv,
     57                                       &coin_pub.eddsa_pub);
     58   GNUNET_CRYPTO_ecdhe_key_create (&trans_priv.ecdhe_priv);
     59   GNUNET_CRYPTO_ecdhe_key_get_public (&trans_priv.ecdhe_priv,
     60                                       &trans_pub.ecdhe_pub);
     61   TALER_link_derive_transfer_secret (&coin_priv,
     62                                      &trans_priv,
     63                                      &secret);
     64   TALER_link_reveal_transfer_secret (&trans_priv,
     65                                      &coin_pub,
     66                                      &secret2);
     67   GNUNET_assert (0 ==
     68                  GNUNET_memcmp (&secret,
     69                                 &secret2));
     70   TALER_link_recover_transfer_secret (&trans_pub,
     71                                       &coin_priv,
     72                                       &secret2);
     73   GNUNET_assert (0 ==
     74                  GNUNET_memcmp (&secret,
     75                                 &secret2));
     76   TALER_transfer_secret_to_planchet_secret (&secret,
     77                                             0,
     78                                             &ps1);
     79   TALER_planchet_setup_coin_priv (&ps1,
     80                                   &alg1,
     81                                   &coin_priv1);
     82   TALER_planchet_blinding_secret_create (&ps1,
     83                                          &alg1,
     84                                          &bks1);
     85   TALER_transfer_secret_to_planchet_secret (&secret,
     86                                             1,
     87                                             &ps2);
     88   TALER_planchet_setup_coin_priv (&ps2,
     89                                   &alg2,
     90                                   &coin_priv2);
     91   TALER_planchet_blinding_secret_create (&ps2,
     92                                          &alg2,
     93                                          &bks2);
     94   GNUNET_assert (0 !=
     95                  GNUNET_memcmp (&ps1,
     96                                 &ps2));
     97   GNUNET_assert (0 !=
     98                  GNUNET_memcmp (&coin_priv1,
     99                                 &coin_priv2));
    100   GNUNET_assert (0 !=
    101                  GNUNET_memcmp (&bks1,
    102                                 &bks2));
    103   return 0;
    104 }
    105 
    106 
    107 static struct TALER_AgeMask age_mask = {
    108   .bits = 1 | 1 << 8 | 1 << 10 | 1 << 12
    109           | 1 << 14 | 1 << 16 | 1 << 18 | 1 << 21
    110 };
    111 
    112 /**
    113  * Test the basic planchet functionality of creating a fresh planchet
    114  * and extracting the respective signature.
    115  *
    116  * @return 0 on success
    117  */
    118 static int
    119 test_planchets_rsa (uint8_t age)
    120 {
    121   struct TALER_PlanchetMasterSecretP ps;
    122   struct TALER_CoinSpendPrivateKeyP coin_priv;
    123   union GNUNET_CRYPTO_BlindingSecretP bks;
    124   struct TALER_DenominationPrivateKey dk_priv;
    125   struct TALER_DenominationPublicKey dk_pub;
    126   const struct TALER_ExchangeBlindingValues *alg_values;
    127   struct TALER_PlanchetDetail pd;
    128   struct TALER_BlindedDenominationSignature blind_sig;
    129   struct TALER_FreshCoin coin;
    130   struct TALER_CoinPubHashP c_hash;
    131   struct TALER_AgeCommitmentHashP *ach = NULL;
    132   struct TALER_AgeCommitmentHashP ah = {0};
    133 
    134   alg_values = TALER_denom_ewv_rsa_singleton ();
    135   if (0 < age)
    136   {
    137     struct TALER_AgeCommitmentProof acp;
    138     struct GNUNET_HashCode seed;
    139 
    140     GNUNET_CRYPTO_random_block (&seed,
    141                                 sizeof(seed));
    142     TALER_age_restriction_commit (&age_mask,
    143                                   age,
    144                                   &seed,
    145                                   &acp);
    146     TALER_age_commitment_hash (&acp.commitment,
    147                                &ah);
    148     ach = &ah;
    149     TALER_age_commitment_proof_free (&acp);
    150   }
    151 
    152   GNUNET_CRYPTO_random_block (&ps,
    153                               sizeof (ps));
    154   GNUNET_log_skip (1, GNUNET_YES);
    155   GNUNET_assert (GNUNET_SYSERR ==
    156                  TALER_denom_priv_create (&dk_priv,
    157                                           &dk_pub,
    158                                           GNUNET_CRYPTO_BSA_INVALID));
    159   GNUNET_log_skip (1, GNUNET_YES);
    160   GNUNET_assert (GNUNET_SYSERR ==
    161                  TALER_denom_priv_create (&dk_priv,
    162                                           &dk_pub,
    163                                           42));
    164 
    165   GNUNET_assert (GNUNET_OK ==
    166                  TALER_denom_priv_create (&dk_priv,
    167                                           &dk_pub,
    168                                           GNUNET_CRYPTO_BSA_RSA,
    169                                           1024));
    170   TALER_planchet_setup_coin_priv (&ps,
    171                                   alg_values,
    172                                   &coin_priv);
    173   TALER_planchet_blinding_secret_create (&ps,
    174                                          alg_values,
    175                                          &bks);
    176   GNUNET_assert (GNUNET_OK ==
    177                  TALER_planchet_prepare (&dk_pub,
    178                                          alg_values,
    179                                          &bks,
    180                                          NULL,
    181                                          &coin_priv,
    182                                          ach,
    183                                          &c_hash,
    184                                          &pd));
    185   GNUNET_assert (GNUNET_OK ==
    186                  TALER_denom_sign_blinded (&blind_sig,
    187                                            &dk_priv,
    188                                            false,
    189                                            &pd.blinded_planchet));
    190   TALER_planchet_detail_free (&pd);
    191   GNUNET_assert (GNUNET_OK ==
    192                  TALER_planchet_to_coin (&dk_pub,
    193                                          &blind_sig,
    194                                          &bks,
    195                                          &coin_priv,
    196                                          ach,
    197                                          &c_hash,
    198                                          alg_values,
    199                                          &coin));
    200   TALER_blinded_denom_sig_free (&blind_sig);
    201   TALER_denom_sig_free (&coin.sig);
    202   TALER_denom_priv_free (&dk_priv);
    203   TALER_denom_pub_free (&dk_pub);
    204   return 0;
    205 }
    206 
    207 
    208 /**
    209  * Test the basic planchet functionality of creating a fresh planchet with CS denomination
    210  * and extracting the respective signature.
    211  *
    212  * @return 0 on success
    213  */
    214 static int
    215 test_planchets_cs (uint8_t age)
    216 {
    217   struct TALER_WithdrawMasterSeedP seed;
    218   struct TALER_BlindingMasterSeedP blinding_seed;
    219   struct TALER_PlanchetMasterSecretP ps;
    220   struct TALER_CoinSpendPrivateKeyP coin_priv;
    221   union GNUNET_CRYPTO_BlindingSecretP bks;
    222   struct TALER_DenominationPrivateKey dk_priv;
    223   struct TALER_DenominationPublicKey dk_pub;
    224   struct TALER_PlanchetDetail pd;
    225   struct TALER_CoinPubHashP c_hash;
    226   union GNUNET_CRYPTO_BlindSessionNonce nonce;
    227   struct TALER_BlindedDenominationSignature blind_sig;
    228   struct TALER_FreshCoin coin;
    229   struct TALER_ExchangeBlindingValues alg_values;
    230   struct TALER_AgeCommitmentHashP *ach = NULL;
    231   struct TALER_AgeCommitmentHashP ah = {0};
    232   const uint32_t coin_offset = 0;
    233 
    234   if (0 < age)
    235   {
    236     struct TALER_AgeCommitmentProof acp;
    237     struct GNUNET_HashCode seed;
    238 
    239     GNUNET_CRYPTO_random_block (&seed,
    240                                 sizeof(seed));
    241     TALER_age_restriction_commit (&age_mask,
    242                                   age,
    243                                   &seed,
    244                                   &acp);
    245     TALER_age_commitment_hash (&acp.commitment,
    246                                &ah);
    247     ach = &ah;
    248     TALER_age_commitment_proof_free (&acp);
    249   }
    250 
    251   TALER_withdraw_master_seed_setup_random (&seed);
    252   TALER_withdraw_expand_secrets (1,
    253                                  &seed,
    254                                  &ps);
    255   TALER_cs_withdraw_seed_to_blinding_seed (&seed,
    256                                            &blinding_seed);
    257   GNUNET_assert (GNUNET_OK ==
    258                  TALER_denom_priv_create (&dk_priv,
    259                                           &dk_pub,
    260                                           GNUNET_CRYPTO_BSA_CS));
    261   TALER_cs_derive_only_cs_blind_nonces_from_seed (
    262     &blinding_seed,
    263     false,
    264     1,
    265     &coin_offset,
    266     &nonce);
    267   // FIXME: define Taler abstraction for this:
    268   alg_values.blinding_inputs
    269     = GNUNET_CRYPTO_get_blinding_input_values (dk_priv.bsign_priv_key,
    270                                                &nonce,
    271                                                "rw");
    272   TALER_denom_pub_hash (&dk_pub,
    273                         &pd.denom_pub_hash);
    274   TALER_planchet_setup_coin_priv (&ps,
    275                                   &alg_values,
    276                                   &coin_priv);
    277   TALER_planchet_blinding_secret_create (&ps,
    278                                          &alg_values,
    279                                          &bks);
    280   GNUNET_assert (GNUNET_OK ==
    281                  TALER_planchet_prepare (&dk_pub,
    282                                          &alg_values,
    283                                          &bks,
    284                                          &nonce,
    285                                          &coin_priv,
    286                                          ach,
    287                                          &c_hash,
    288                                          &pd));
    289   GNUNET_assert (GNUNET_OK ==
    290                  TALER_denom_sign_blinded (&blind_sig,
    291                                            &dk_priv,
    292                                            false,
    293                                            &pd.blinded_planchet));
    294   GNUNET_assert (GNUNET_OK ==
    295                  TALER_planchet_to_coin (&dk_pub,
    296                                          &blind_sig,
    297                                          &bks,
    298                                          &coin_priv,
    299                                          ach,
    300                                          &c_hash,
    301                                          &alg_values,
    302                                          &coin));
    303   TALER_blinded_denom_sig_free (&blind_sig);
    304   TALER_denom_sig_free (&coin.sig);
    305   TALER_denom_priv_free (&dk_priv);
    306   TALER_denom_pub_free (&dk_pub);
    307   return 0;
    308 }
    309 
    310 
    311 /**
    312  * Test the basic planchet functionality of creating a fresh planchet
    313  * and extracting the respective signature.
    314  * Calls test_planchets_rsa and test_planchets_cs
    315  *
    316  * @return 0 on success
    317  */
    318 static int
    319 test_planchets (uint8_t age)
    320 {
    321   if (0 != test_planchets_rsa (age))
    322     return -1;
    323   return test_planchets_cs (age);
    324 }
    325 
    326 
    327 static int
    328 test_exchange_sigs (void)
    329 {
    330   const struct TALER_FullPayto pt = {
    331     .full_payto
    332       = (char *) "payto://x-taler-bank/localhost/Account?receiver-name=ACC"
    333   };
    334   const struct TALER_FullPayto pto = {
    335     .full_payto
    336       = (char *) "payto://x-taler-bank/localhost/Other?receiver-name=OTH"
    337   };
    338   struct TALER_MasterPrivateKeyP priv;
    339   struct TALER_MasterPublicKeyP pub;
    340   struct TALER_MasterSignatureP sig;
    341   json_t *rest;
    342 
    343   GNUNET_CRYPTO_eddsa_key_create (&priv.eddsa_priv);
    344   rest = json_array ();
    345   GNUNET_assert (NULL != rest);
    346   TALER_exchange_wire_signature_make (pt,
    347                                       NULL,
    348                                       "https://example.com/",
    349                                       NULL,
    350                                       rest,
    351                                       rest,
    352                                       &priv,
    353                                       &sig);
    354   GNUNET_CRYPTO_eddsa_key_get_public (&priv.eddsa_priv,
    355                                       &pub.eddsa_pub);
    356   if (GNUNET_OK !=
    357       TALER_exchange_wire_signature_check (pt,
    358                                            NULL,
    359                                            "https://example.com/",
    360                                            NULL,
    361                                            rest,
    362                                            rest,
    363                                            &pub,
    364                                            &sig))
    365   {
    366     GNUNET_break (0);
    367     return 1;
    368   }
    369   if (GNUNET_OK ==
    370       TALER_exchange_wire_signature_check (
    371         pto,
    372         NULL,
    373         "https://example.com/",
    374         NULL,
    375         rest,
    376         rest,
    377         &pub,
    378         &sig))
    379   {
    380     GNUNET_break (0);
    381     return 1;
    382   }
    383   if (GNUNET_OK ==
    384       TALER_exchange_wire_signature_check (
    385         pt,
    386         "http://example.com/",
    387         NULL,
    388         NULL,
    389         rest,
    390         rest,
    391         &pub,
    392         &sig))
    393   {
    394     GNUNET_break (0);
    395     return 1;
    396   }
    397   json_decref (rest);
    398   return 0;
    399 }
    400 
    401 
    402 /**
    403  * Private key used by #test_sign_cb().
    404  */
    405 static struct TALER_ExchangePrivateKeyP test_exchange_priv;
    406 
    407 
    408 /**
    409  * Sign @a purpose with #test_exchange_priv, standing in for
    410  * the exchange's signing helper.
    411  *
    412  * @param purpose message to sign
    413  * @param[out] pub set to the public key of #test_exchange_priv
    414  * @param[out] sig set to the signature
    415  * @return #TALER_EC_NONE
    416  */
    417 static enum TALER_ErrorCode
    418 test_sign_cb (const struct GNUNET_CRYPTO_SignaturePurpose *purpose,
    419               struct TALER_ExchangePublicKeyP *pub,
    420               struct TALER_ExchangeSignatureP *sig)
    421 {
    422   GNUNET_CRYPTO_eddsa_key_get_public (&test_exchange_priv.eddsa_priv,
    423                                       &pub->eddsa_pub);
    424   GNUNET_CRYPTO_eddsa_sign_ (&test_exchange_priv.eddsa_priv,
    425                              purpose,
    426                              &sig->eddsa_signature);
    427   return TALER_EC_NONE;
    428 }
    429 
    430 
    431 /**
    432  * Test the batch recoup confirmation signatures and the hash
    433  * over the recouped coins they cover.
    434  *
    435  * @return 0 on success
    436  */
    437 static int
    438 test_recoup_batch_sigs (void)
    439 {
    440   struct TALER_RecoupedCoin recoups[3];
    441   struct TALER_RecoupedCoin swapped[3];
    442   struct GNUNET_HashCode h_recoups;
    443   struct GNUNET_HashCode h_swapped;
    444   struct TALER_Amount total;
    445   struct TALER_ReservePublicKeyP reserve_pub;
    446   struct TALER_HashBlindedPlanchetsP planchets_h;
    447   struct TALER_CoinSpendPublicKeyP old_coin_pub;
    448   struct TALER_RefreshCommitmentP rc;
    449   struct GNUNET_TIME_Timestamp ts;
    450   struct TALER_ExchangePublicKeyP pub;
    451   struct TALER_ExchangeSignatureP sig;
    452 
    453   GNUNET_CRYPTO_eddsa_key_create (&test_exchange_priv.eddsa_priv);
    454   GNUNET_assert (GNUNET_OK ==
    455                  TALER_amount_set_zero ("EUR",
    456                                         &total));
    457   for (unsigned int i = 0; i < 3; i++)
    458   {
    459     GNUNET_CRYPTO_random_block (&recoups[i].coin_pub,
    460                                 sizeof (recoups[i].coin_pub));
    461     GNUNET_assert (GNUNET_OK ==
    462                    TALER_string_to_amount ("EUR:1.5",
    463                                            &recoups[i].amount));
    464     GNUNET_assert (0 <=
    465                    TALER_amount_add (&total,
    466                                      &total,
    467                                      &recoups[i].amount));
    468   }
    469   GNUNET_CRYPTO_random_block (&reserve_pub,
    470                               sizeof (reserve_pub));
    471   GNUNET_CRYPTO_random_block (&planchets_h,
    472                               sizeof (planchets_h));
    473   GNUNET_CRYPTO_random_block (&old_coin_pub,
    474                               sizeof (old_coin_pub));
    475   GNUNET_CRYPTO_random_block (&rc,
    476                               sizeof (rc));
    477   ts = GNUNET_TIME_timestamp_get ();
    478 
    479   /* the hash must depend on the order of the coins */
    480   TALER_recoup_batch_hash (3,
    481                            recoups,
    482                            &h_recoups);
    483   swapped[0] = recoups[1];
    484   swapped[1] = recoups[0];
    485   swapped[2] = recoups[2];
    486   TALER_recoup_batch_hash (3,
    487                            swapped,
    488                            &h_swapped);
    489   if (0 ==
    490       GNUNET_memcmp (&h_recoups,
    491                      &h_swapped))
    492   {
    493     GNUNET_break (0);
    494     return 1;
    495   }
    496 
    497   /* withdraw batch confirmation */
    498   if (TALER_EC_NONE !=
    499       TALER_exchange_online_confirm_recoup_withdraw_batch_sign (
    500         &test_sign_cb,
    501         ts,
    502         &reserve_pub,
    503         &planchets_h,
    504         &total,
    505         &h_recoups,
    506         &pub,
    507         &sig))
    508   {
    509     GNUNET_break (0);
    510     return 1;
    511   }
    512   if (GNUNET_OK !=
    513       TALER_exchange_online_confirm_recoup_withdraw_batch_verify (
    514         ts,
    515         &reserve_pub,
    516         &planchets_h,
    517         &total,
    518         &h_recoups,
    519         &pub,
    520         &sig))
    521   {
    522     GNUNET_break (0);
    523     return 1;
    524   }
    525   if (GNUNET_OK ==
    526       TALER_exchange_online_confirm_recoup_withdraw_batch_verify (
    527         ts,
    528         &reserve_pub,
    529         &planchets_h,
    530         &total,
    531         &h_swapped,
    532         &pub,
    533         &sig))
    534   {
    535     GNUNET_break (0);
    536     return 1;
    537   }
    538   if (GNUNET_OK ==
    539       TALER_exchange_online_confirm_recoup_withdraw_batch_verify (
    540         ts,
    541         &reserve_pub,
    542         &planchets_h,
    543         &recoups[0].amount,
    544         &h_recoups,
    545         &pub,
    546         &sig))
    547   {
    548     GNUNET_break (0);
    549     return 1;
    550   }
    551 
    552   /* refresh batch confirmation */
    553   if (TALER_EC_NONE !=
    554       TALER_exchange_online_confirm_recoup_refresh_batch_sign (
    555         &test_sign_cb,
    556         ts,
    557         &old_coin_pub,
    558         &rc,
    559         &total,
    560         &h_recoups,
    561         &pub,
    562         &sig))
    563   {
    564     GNUNET_break (0);
    565     return 1;
    566   }
    567   if (GNUNET_OK !=
    568       TALER_exchange_online_confirm_recoup_refresh_batch_verify (
    569         ts,
    570         &old_coin_pub,
    571         &rc,
    572         &total,
    573         &h_recoups,
    574         &pub,
    575         &sig))
    576   {
    577     GNUNET_break (0);
    578     return 1;
    579   }
    580   if (GNUNET_OK ==
    581       TALER_exchange_online_confirm_recoup_refresh_batch_verify (
    582         GNUNET_TIME_timestamp_get (),
    583         &old_coin_pub,
    584         &rc,
    585         &total,
    586         &h_recoups,
    587         &pub,
    588         &sig))
    589   {
    590     /* only fails if the clock did not advance; tolerate that */
    591     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    592                 "timestamp did not change, skipping negative check\n");
    593   }
    594   return 0;
    595 }
    596 
    597 
    598 static int
    599 test_merchant_sigs (void)
    600 {
    601   const struct TALER_FullPayto pt = {
    602     .full_payto
    603       = (char *) "payto://x-taler-bank/localhost/Account?receiver-name=ACC"
    604   };
    605   const struct TALER_FullPayto pto = {
    606     .full_payto
    607       = (char *) "payto://x-taler-bank/localhost/Other?receiver-name=OTH"
    608   };
    609   struct TALER_WireSaltP salt;
    610   struct TALER_MerchantPrivateKeyP priv;
    611   struct TALER_MerchantPublicKeyP pub;
    612   struct TALER_MerchantSignatureP sig;
    613 
    614   GNUNET_CRYPTO_eddsa_key_create (&priv.eddsa_priv);
    615   memset (&salt,
    616           42,
    617           sizeof (salt));
    618   TALER_merchant_wire_signature_make (pt,
    619                                       &salt,
    620                                       &priv,
    621                                       &sig);
    622   GNUNET_CRYPTO_eddsa_key_get_public (&priv.eddsa_priv,
    623                                       &pub.eddsa_pub);
    624   if (GNUNET_OK !=
    625       TALER_merchant_wire_signature_check (pt,
    626                                            &salt,
    627                                            &pub,
    628                                            &sig))
    629   {
    630     GNUNET_break (0);
    631     return 1;
    632   }
    633   if (GNUNET_OK ==
    634       TALER_merchant_wire_signature_check (
    635         pto,
    636         &salt,
    637         &pub,
    638         &sig))
    639   {
    640     GNUNET_break (0);
    641     return 1;
    642   }
    643   memset (&salt,
    644           43,
    645           sizeof (salt));
    646   if (GNUNET_OK ==
    647       TALER_merchant_wire_signature_check (pt,
    648                                            &salt,
    649                                            &pub,
    650                                            &sig))
    651   {
    652     GNUNET_break (0);
    653     return 1;
    654   }
    655   return 0;
    656 }
    657 
    658 
    659 static int
    660 test_contracts (void)
    661 {
    662   struct TALER_ContractDiffiePrivateP cpriv;
    663   struct TALER_PurseContractPublicKeyP purse_pub;
    664   struct TALER_PurseContractPrivateKeyP purse_priv;
    665   void *econtract;
    666   size_t econtract_size;
    667   struct TALER_PurseMergePrivateKeyP mpriv_in;
    668   struct TALER_PurseMergePrivateKeyP mpriv_out;
    669   json_t *c;
    670 
    671   GNUNET_CRYPTO_ecdhe_key_create (&cpriv.ecdhe_priv);
    672   GNUNET_CRYPTO_eddsa_key_create (&purse_priv.eddsa_priv);
    673   GNUNET_CRYPTO_eddsa_key_get_public (&purse_priv.eddsa_priv,
    674                                       &purse_pub.eddsa_pub);
    675   memset (&mpriv_in,
    676           42,
    677           sizeof (mpriv_in));
    678   c = json_pack ("{s:s}", "test", "value");
    679   GNUNET_assert (NULL != c);
    680   TALER_CRYPTO_contract_encrypt_for_merge (&purse_pub,
    681                                            &cpriv,
    682                                            &mpriv_in,
    683                                            c,
    684                                            &econtract,
    685                                            &econtract_size);
    686   json_decref (c);
    687   c = TALER_CRYPTO_contract_decrypt_for_merge (&cpriv,
    688                                                &purse_pub,
    689                                                econtract,
    690                                                econtract_size,
    691                                                &mpriv_out);
    692   GNUNET_free (econtract);
    693   if (NULL == c)
    694     return 1;
    695   json_decref (c);
    696   if (0 != GNUNET_memcmp (&mpriv_in,
    697                           &mpriv_out))
    698     return 1;
    699   return 0;
    700 }
    701 
    702 
    703 static int
    704 test_attributes (void)
    705 {
    706   struct TALER_AttributeEncryptionKeyP key;
    707   void *eattr;
    708   size_t eattr_size;
    709   json_t *c;
    710 
    711   GNUNET_CRYPTO_random_block (&key,
    712                               sizeof (key));
    713   c = json_pack ("{s:s}", "test", "value");
    714   GNUNET_assert (NULL != c);
    715   TALER_CRYPTO_kyc_attributes_encrypt (&key,
    716                                        c,
    717                                        &eattr,
    718                                        &eattr_size);
    719   json_decref (c);
    720   c = TALER_CRYPTO_kyc_attributes_decrypt (&key,
    721                                            eattr,
    722                                            eattr_size);
    723   GNUNET_free (eattr);
    724   if (NULL == c)
    725   {
    726     GNUNET_break (0);
    727     return 1;
    728   }
    729   GNUNET_assert (0 ==
    730                  strcmp ("value",
    731                          json_string_value (json_object_get (c,
    732                                                              "test"))));
    733   json_decref (c);
    734   return 0;
    735 }
    736 
    737 
    738 int
    739 main (int argc,
    740       const char *const argv[])
    741 {
    742   (void) argc;
    743   (void) argv;
    744   GNUNET_log_setup ("test-crypto",
    745                     "WARNING",
    746                     NULL);
    747   if (0 != test_high_level ())
    748     return 1;
    749   if (0 != test_planchets (0))
    750     return 2;
    751   if (0 != test_planchets (13))
    752     return 3;
    753   if (0 != test_exchange_sigs ())
    754     return 4;
    755   if (0 != test_recoup_batch_sigs ())
    756     return 9;
    757   if (0 != test_merchant_sigs ())
    758     return 5;
    759   if (0 != test_contracts ())
    760     return 6;
    761   if (0 != test_attributes ())
    762     return 7;
    763   return 0;
    764 }
    765 
    766 
    767 /* end of test_crypto.c */