diff options
Diffstat (limited to 'src/util/wallet_signatures.c')
-rw-r--r-- | src/util/wallet_signatures.c | 769 |
1 files changed, 657 insertions, 112 deletions
diff --git a/src/util/wallet_signatures.c b/src/util/wallet_signatures.c index 27a28256c..0b6ab5432 100644 --- a/src/util/wallet_signatures.c +++ b/src/util/wallet_signatures.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2021, 2022 Taler Systems SA + Copyright (C) 2021-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -17,12 +17,16 @@ * @file wallet_signatures.c * @brief Utility functions for Taler wallet signatures * @author Christian Grothoff + * @author Özgür Kesim */ #include "platform.h" #include "taler_util.h" #include "taler_signatures.h" +#include <gnunet/gnunet_common.h> +GNUNET_NETWORK_STRUCT_BEGIN + /** * @brief Format used to generate the signature on a request to deposit * a coin into the account of a merchant. @@ -47,9 +51,9 @@ struct TALER_DepositRequestPS struct TALER_AgeCommitmentHash h_age_commitment GNUNET_PACKED; /** - * Hash over extension attributes shared with the exchange. + * Hash over optional policy extension attributes shared with the exchange. */ - struct TALER_ExtensionContractHashP h_extensions GNUNET_PACKED; + struct TALER_ExtensionPolicyHashP h_policy GNUNET_PACKED; /** * Hash over the wiring information of the merchant. @@ -107,8 +111,15 @@ struct TALER_DepositRequestPS */ struct TALER_MerchantPublicKeyP merchant; + /** + * Hash over a JSON containing data provided by the + * wallet to complete the contract upon payment. + */ + struct GNUNET_HashCode wallet_data_hash; + }; +GNUNET_NETWORK_STRUCT_END void TALER_wallet_deposit_sign ( @@ -116,8 +127,9 @@ TALER_wallet_deposit_sign ( const struct TALER_Amount *deposit_fee, const struct TALER_MerchantWireHashP *h_wire, const struct TALER_PrivateContractHashP *h_contract_terms, + const struct GNUNET_HashCode *wallet_data_hash, const struct TALER_AgeCommitmentHash *h_age_commitment, - const struct TALER_ExtensionContractHashP *h_extensions, + const struct TALER_ExtensionPolicyHashP *h_policy, const struct TALER_DenominationHashP *h_denom_pub, const struct GNUNET_TIME_Timestamp wallet_timestamp, const struct TALER_MerchantPublicKeyP *merchant_pub, @@ -136,12 +148,12 @@ TALER_wallet_deposit_sign ( .merchant = *merchant_pub }; + if (NULL != wallet_data_hash) + dr.wallet_data_hash = *wallet_data_hash; if (NULL != h_age_commitment) dr.h_age_commitment = *h_age_commitment; - - if (NULL != h_extensions) - dr.h_extensions = *h_extensions; - + if (NULL != h_policy) + dr.h_policy = *h_policy; TALER_amount_hton (&dr.amount_with_fee, amount); TALER_amount_hton (&dr.deposit_fee, @@ -158,8 +170,9 @@ TALER_wallet_deposit_verify ( const struct TALER_Amount *deposit_fee, const struct TALER_MerchantWireHashP *h_wire, const struct TALER_PrivateContractHashP *h_contract_terms, + const struct GNUNET_HashCode *wallet_data_hash, const struct TALER_AgeCommitmentHash *h_age_commitment, - const struct TALER_ExtensionContractHashP *h_extensions, + const struct TALER_ExtensionPolicyHashP *h_policy, const struct TALER_DenominationHashP *h_denom_pub, struct GNUNET_TIME_Timestamp wallet_timestamp, const struct TALER_MerchantPublicKeyP *merchant_pub, @@ -176,21 +189,18 @@ TALER_wallet_deposit_verify ( .wallet_timestamp = GNUNET_TIME_timestamp_hton (wallet_timestamp), .refund_deadline = GNUNET_TIME_timestamp_hton (refund_deadline), .merchant = *merchant_pub, - .h_age_commitment = {{{0}}}, - .h_extensions = {{{0}}} }; + if (NULL != wallet_data_hash) + dr.wallet_data_hash = *wallet_data_hash; if (NULL != h_age_commitment) dr.h_age_commitment = *h_age_commitment; - - if (NULL != h_extensions) - dr.h_extensions = *h_extensions; - + if (NULL != h_policy) + dr.h_policy = *h_policy; TALER_amount_hton (&dr.amount_with_fee, amount); TALER_amount_hton (&dr.deposit_fee, deposit_fee); - if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT, &dr, @@ -204,6 +214,8 @@ TALER_wallet_deposit_verify ( } +GNUNET_NETWORK_STRUCT_BEGIN + /** * @brief Format used for to allow the wallet to authenticate * link data provided by the exchange. @@ -238,6 +250,7 @@ struct TALER_LinkDataPS struct TALER_BlindedCoinHashP coin_envelope_hash; }; +GNUNET_NETWORK_STRUCT_END void TALER_wallet_link_sign (const struct TALER_DenominationHashP *h_denom_pub, @@ -284,6 +297,8 @@ TALER_wallet_link_verify ( } +GNUNET_NETWORK_STRUCT_BEGIN + /** * Signed data to request that a coin should be refunded as part of * the "emergency" /recoup protocol. The refund will go back to the bank @@ -305,15 +320,17 @@ struct TALER_RecoupRequestPS /** * Blinding factor that was used to withdraw the coin. */ - union TALER_DenominationBlindingKeyP coin_blind; + union GNUNET_CRYPTO_BlindingSecretP coin_blind; }; +GNUNET_NETWORK_STRUCT_END + enum GNUNET_GenericReturnValue TALER_wallet_recoup_verify ( const struct TALER_DenominationHashP *h_denom_pub, - const union TALER_DenominationBlindingKeyP *coin_bks, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_CoinSpendSignatureP *coin_sig) { @@ -334,7 +351,7 @@ TALER_wallet_recoup_verify ( void TALER_wallet_recoup_sign ( const struct TALER_DenominationHashP *h_denom_pub, - const union TALER_DenominationBlindingKeyP *coin_bks, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, const struct TALER_CoinSpendPrivateKeyP *coin_priv, struct TALER_CoinSpendSignatureP *coin_sig) { @@ -354,7 +371,7 @@ TALER_wallet_recoup_sign ( enum GNUNET_GenericReturnValue TALER_wallet_recoup_refresh_verify ( const struct TALER_DenominationHashP *h_denom_pub, - const union TALER_DenominationBlindingKeyP *coin_bks, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_CoinSpendSignatureP *coin_sig) { @@ -375,7 +392,7 @@ TALER_wallet_recoup_refresh_verify ( void TALER_wallet_recoup_refresh_sign ( const struct TALER_DenominationHashP *h_denom_pub, - const union TALER_DenominationBlindingKeyP *coin_bks, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, const struct TALER_CoinSpendPrivateKeyP *coin_priv, struct TALER_CoinSpendSignatureP *coin_sig) { @@ -392,6 +409,8 @@ TALER_wallet_recoup_refresh_sign ( } +GNUNET_NETWORK_STRUCT_BEGIN + /** * @brief Message signed by a coin to indicate that the coin should be * melted. @@ -443,6 +462,7 @@ struct TALER_RefreshMeltCoinAffirmationPS struct TALER_AmountNBO melt_fee; }; +GNUNET_NETWORK_STRUCT_END void TALER_wallet_melt_sign ( @@ -509,6 +529,9 @@ TALER_wallet_melt_verify ( } +GNUNET_NETWORK_STRUCT_BEGIN + + /** * @brief Format used for to generate the signature on a request to withdraw * coins from a reserve. @@ -543,6 +566,8 @@ struct TALER_WithdrawRequestPS }; +GNUNET_NETWORK_STRUCT_END + void TALER_wallet_withdraw_sign ( const struct TALER_DenominationHashP *h_denom_pub, @@ -591,45 +616,181 @@ TALER_wallet_withdraw_verify ( } +GNUNET_NETWORK_STRUCT_BEGIN + +/** + * @brief Format used for to generate the signature on a request to + * age-withdraw from a reserve. + */ +struct TALER_AgeWithdrawRequestPS +{ + + /** + * Purpose must be #TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW. + * Used with an EdDSA signature of a `struct TALER_ReservePublicKeyP`. + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * The reserve's public key + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * Value of the coin being exchanged (matching the denomination key) + * plus the transaction fee. We include this in what is being + * signed so that we can verify a reserve's remaining total balance + * without needing to access the respective denomination key + * information each time. + */ + struct TALER_AmountNBO amount_with_fee; + + /** + * Running SHA512 hash of the commitment of n*kappa coins + */ + struct TALER_AgeWithdrawCommitmentHashP h_commitment; + + /** + * The mask that defines the age groups. MUST be the same for all denominations. + */ + struct TALER_AgeMask mask; + + /** + * Maximum age group that the coins are going to be restricted to. + */ + uint8_t max_age_group; +}; + + +GNUNET_NETWORK_STRUCT_END + +void +TALER_wallet_age_withdraw_sign ( + const struct TALER_AgeWithdrawCommitmentHashP *h_commitment, + const struct TALER_Amount *amount_with_fee, + const struct TALER_AgeMask *mask, + uint8_t max_age, + const struct TALER_ReservePrivateKeyP *reserve_priv, + struct TALER_ReserveSignatureP *reserve_sig) +{ + struct TALER_AgeWithdrawRequestPS req = { + .purpose.size = htonl (sizeof (req)), + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_AGE_WITHDRAW), + .h_commitment = *h_commitment, + .mask = *mask, + .max_age_group = TALER_get_age_group (mask, max_age) + }; + + GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv, + &req.reserve_pub.eddsa_pub); + TALER_amount_hton (&req.amount_with_fee, + amount_with_fee); + GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv, + &req, + &reserve_sig->eddsa_signature); +} + + +enum GNUNET_GenericReturnValue +TALER_wallet_age_withdraw_verify ( + const struct TALER_AgeWithdrawCommitmentHashP *h_commitment, + const struct TALER_Amount *amount_with_fee, + const struct TALER_AgeMask *mask, + uint8_t max_age, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig) +{ + struct TALER_AgeWithdrawRequestPS awsrd = { + .purpose.size = htonl (sizeof (awsrd)), + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_AGE_WITHDRAW), + .reserve_pub = *reserve_pub, + .h_commitment = *h_commitment, + .mask = *mask, + .max_age_group = TALER_get_age_group (mask, max_age) + }; + + TALER_amount_hton (&awsrd.amount_with_fee, + amount_with_fee); + return GNUNET_CRYPTO_eddsa_verify ( + TALER_SIGNATURE_WALLET_RESERVE_AGE_WITHDRAW, + &awsrd, + &reserve_sig->eddsa_signature, + &reserve_pub->eddsa_pub); +} + + +GNUNET_NETWORK_STRUCT_BEGIN + + +/** + * @brief Format used for to generate the signature on a request to withdraw + * coins from a reserve. + */ +struct TALER_AccountSetupRequestSignaturePS +{ + + /** + * Purpose must be #TALER_SIGNATURE_WALLET_ACCOUNT_SETUP. + * Used with an EdDSA signature of a `struct TALER_ReservePublicKeyP`. + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * Balance threshold the wallet is about to cross. + */ + struct TALER_AmountNBO threshold; + +}; + + +GNUNET_NETWORK_STRUCT_END + + void TALER_wallet_account_setup_sign ( const struct TALER_ReservePrivateKeyP *reserve_priv, + const struct TALER_Amount *balance_threshold, struct TALER_ReserveSignatureP *reserve_sig) { - struct GNUNET_CRYPTO_EccSignaturePurpose purpose = { - .size = htonl (sizeof (purpose)), - .purpose = htonl (TALER_SIGNATURE_WALLET_ACCOUNT_SETUP) + struct TALER_AccountSetupRequestSignaturePS asap = { + .purpose.size = htonl (sizeof (asap)), + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_ACCOUNT_SETUP) }; - GNUNET_assert (GNUNET_OK == - GNUNET_CRYPTO_eddsa_sign_ (&reserve_priv->eddsa_priv, - &purpose, - &reserve_sig->eddsa_signature)); + TALER_amount_hton (&asap.threshold, + balance_threshold); + GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv, + &asap, + &reserve_sig->eddsa_signature); } enum GNUNET_GenericReturnValue TALER_wallet_account_setup_verify ( const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_Amount *balance_threshold, const struct TALER_ReserveSignatureP *reserve_sig) { - struct GNUNET_CRYPTO_EccSignaturePurpose purpose = { - .size = htonl (sizeof (purpose)), - .purpose = htonl (TALER_SIGNATURE_WALLET_ACCOUNT_SETUP) + struct TALER_AccountSetupRequestSignaturePS asap = { + .purpose.size = htonl (sizeof (asap)), + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_ACCOUNT_SETUP) }; - return GNUNET_CRYPTO_eddsa_verify_ ( + TALER_amount_hton (&asap.threshold, + balance_threshold); + return GNUNET_CRYPTO_eddsa_verify ( TALER_SIGNATURE_WALLET_ACCOUNT_SETUP, - &purpose, + &asap, &reserve_sig->eddsa_signature, &reserve_pub->eddsa_pub); } +GNUNET_NETWORK_STRUCT_BEGIN + + /** - * Response by which a wallet requests a full - * reserve history and indicates it is willing - * to pay for it. + * Response by which a wallet requests a reserve history. */ struct TALER_ReserveHistoryRequestPS { @@ -640,35 +801,29 @@ struct TALER_ReserveHistoryRequestPS struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** - * When did the wallet make the requst. - */ - struct GNUNET_TIME_TimestampNBO request_timestamp; - - /** - * How much does the exchange charge for the history? + * Which entries to exclude. Only return above this offset. */ - struct TALER_AmountNBO history_fee; + uint64_t start_off; }; +GNUNET_NETWORK_STRUCT_END + enum GNUNET_GenericReturnValue TALER_wallet_reserve_history_verify ( - const struct GNUNET_TIME_Timestamp ts, - const struct TALER_Amount *history_fee, + uint64_t start_off, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_ReserveSignatureP *reserve_sig) { struct TALER_ReserveHistoryRequestPS rhr = { .purpose.size = htonl (sizeof (rhr)), .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_HISTORY), - .request_timestamp = GNUNET_TIME_timestamp_hton (ts) + .start_off = GNUNET_htonll (start_off) }; - TALER_amount_hton (&rhr.history_fee, - history_fee); return GNUNET_CRYPTO_eddsa_verify ( - TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW, + TALER_SIGNATURE_WALLET_RESERVE_HISTORY, &rhr, &reserve_sig->eddsa_signature, &reserve_pub->eddsa_pub); @@ -677,82 +832,84 @@ TALER_wallet_reserve_history_verify ( void TALER_wallet_reserve_history_sign ( - const struct GNUNET_TIME_Timestamp ts, - const struct TALER_Amount *history_fee, + uint64_t start_off, const struct TALER_ReservePrivateKeyP *reserve_priv, struct TALER_ReserveSignatureP *reserve_sig) { struct TALER_ReserveHistoryRequestPS rhr = { .purpose.size = htonl (sizeof (rhr)), .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_HISTORY), - .request_timestamp = GNUNET_TIME_timestamp_hton (ts) + .start_off = GNUNET_htonll (start_off) }; - TALER_amount_hton (&rhr.history_fee, - history_fee); GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv, &rhr, &reserve_sig->eddsa_signature); } +GNUNET_NETWORK_STRUCT_BEGIN + /** - * Response by which a wallet requests an account status. + * Response by which a wallet requests a coin history. */ -struct TALER_ReserveStatusRequestPS +struct TALER_CoinHistoryRequestPS { /** - * Purpose is #TALER_SIGNATURE_WALLET_RESERVE_STATUS + * Purpose is #TALER_SIGNATURE_WALLET_COIN_HISTORY */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** - * When did the wallet make the requst. + * Which entries to exclude. Only return above this offset. */ - struct GNUNET_TIME_TimestampNBO request_timestamp; + uint64_t start_off; }; +GNUNET_NETWORK_STRUCT_END enum GNUNET_GenericReturnValue -TALER_wallet_reserve_status_verify ( - const struct GNUNET_TIME_Timestamp ts, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_ReserveSignatureP *reserve_sig) +TALER_wallet_coin_history_verify ( + uint64_t start_off, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendSignatureP *coin_sig) { - struct TALER_ReserveStatusRequestPS rsr = { + struct TALER_CoinHistoryRequestPS rsr = { .purpose.size = htonl (sizeof (rsr)), - .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_STATUS), - .request_timestamp = GNUNET_TIME_timestamp_hton (ts) + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_HISTORY), + .start_off = GNUNET_htonll (start_off) }; return GNUNET_CRYPTO_eddsa_verify ( - TALER_SIGNATURE_WALLET_RESERVE_STATUS, + TALER_SIGNATURE_WALLET_COIN_HISTORY, &rsr, - &reserve_sig->eddsa_signature, - &reserve_pub->eddsa_pub); + &coin_sig->eddsa_signature, + &coin_pub->eddsa_pub); } void -TALER_wallet_reserve_status_sign ( - const struct GNUNET_TIME_Timestamp ts, - const struct TALER_ReservePrivateKeyP *reserve_priv, - struct TALER_ReserveSignatureP *reserve_sig) +TALER_wallet_coin_history_sign ( + uint64_t start_off, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + struct TALER_CoinSpendSignatureP *coin_sig) { - struct TALER_ReserveStatusRequestPS rsr = { + struct TALER_CoinHistoryRequestPS rsr = { .purpose.size = htonl (sizeof (rsr)), - .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_STATUS), - .request_timestamp = GNUNET_TIME_timestamp_hton (ts) + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_HISTORY), + .start_off = GNUNET_htonll (start_off) }; - GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv, + GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv, &rsr, - &reserve_sig->eddsa_signature); + &coin_sig->eddsa_signature); } +GNUNET_NETWORK_STRUCT_BEGIN + /** * Message signed to create a purse (without reserve). */ @@ -792,10 +949,13 @@ struct TALER_PurseCreatePS }; +GNUNET_NETWORK_STRUCT_END + + void TALER_wallet_purse_create_sign ( struct GNUNET_TIME_Timestamp purse_expiration, - struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_PrivateContractHashP *h_contract_terms, const struct TALER_PurseMergePublicKeyP *merge_pub, uint32_t min_age, const struct TALER_Amount *amount, @@ -822,7 +982,7 @@ TALER_wallet_purse_create_sign ( enum GNUNET_GenericReturnValue TALER_wallet_purse_create_verify ( struct GNUNET_TIME_Timestamp purse_expiration, - struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_PrivateContractHashP *h_contract_terms, const struct TALER_PurseMergePublicKeyP *merge_pub, uint32_t min_age, const struct TALER_Amount *amount, @@ -848,6 +1008,59 @@ TALER_wallet_purse_create_verify ( } +GNUNET_NETWORK_STRUCT_BEGIN + +/** + * Message signed to delete a purse. + */ +struct TALER_PurseDeletePS +{ + + /** + * Purpose is #TALER_SIGNATURE_WALLET_PURSE_DELETE + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + +}; + + +GNUNET_NETWORK_STRUCT_END + + +void +TALER_wallet_purse_delete_sign ( + const struct TALER_PurseContractPrivateKeyP *purse_priv, + struct TALER_PurseContractSignatureP *purse_sig) +{ + struct TALER_PurseDeletePS pm = { + .purpose.size = htonl (sizeof (pm)), + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_DELETE) + }; + + GNUNET_CRYPTO_eddsa_sign (&purse_priv->eddsa_priv, + &pm, + &purse_sig->eddsa_signature); +} + + +enum GNUNET_GenericReturnValue +TALER_wallet_purse_delete_verify ( + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseContractSignatureP *purse_sig) +{ + struct TALER_PurseDeletePS pm = { + .purpose.size = htonl (sizeof (pm)), + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_DELETE) + }; + + return GNUNET_CRYPTO_eddsa_verify ( + TALER_SIGNATURE_WALLET_PURSE_DELETE, + &pm, + &purse_sig->eddsa_signature, + &purse_pub->eddsa_pub); +} + + void TALER_wallet_purse_status_sign ( const struct TALER_PurseContractPrivateKeyP *purse_priv, @@ -882,6 +1095,8 @@ TALER_wallet_purse_status_verify ( } +GNUNET_NETWORK_STRUCT_BEGIN + /** * Message signed to deposit a coin into a purse. */ @@ -899,6 +1114,17 @@ struct TALER_PurseDepositPS struct TALER_AmountNBO coin_amount; /** + * Hash over the denomination public key used to sign the coin. + */ + struct TALER_DenominationHashP h_denom_pub GNUNET_PACKED; + + /** + * Hash over the age commitment that went into the coin. Maybe all zero, if + * age commitment isn't applicable to the denomination. + */ + struct TALER_AgeCommitmentHash h_age_commitment GNUNET_PACKED; + + /** * Purse to deposit funds into. */ struct TALER_PurseContractPublicKeyP purse_pub; @@ -907,15 +1133,18 @@ struct TALER_PurseDepositPS * Hash of the base URL of the exchange hosting the * @e purse_pub. */ - struct GNUNET_HashCode h_exchange_base_url; + struct GNUNET_HashCode h_exchange_base_url GNUNET_PACKED; }; +GNUNET_NETWORK_STRUCT_END void TALER_wallet_purse_deposit_sign ( const char *exchange_base_url, const struct TALER_PurseContractPublicKeyP *purse_pub, const struct TALER_Amount *amount, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AgeCommitmentHash *h_age_commitment, const struct TALER_CoinSpendPrivateKeyP *coin_priv, struct TALER_CoinSpendSignatureP *coin_sig) { @@ -923,6 +1152,8 @@ TALER_wallet_purse_deposit_sign ( .purpose.size = htonl (sizeof (pm)), .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_DEPOSIT), .purse_pub = *purse_pub, + .h_denom_pub = *h_denom_pub, + .h_age_commitment = *h_age_commitment }; GNUNET_CRYPTO_hash (exchange_base_url, @@ -941,6 +1172,8 @@ TALER_wallet_purse_deposit_verify ( const char *exchange_base_url, const struct TALER_PurseContractPublicKeyP *purse_pub, const struct TALER_Amount *amount, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AgeCommitmentHash *h_age_commitment, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_CoinSpendSignatureP *coin_sig) { @@ -948,6 +1181,8 @@ TALER_wallet_purse_deposit_verify ( .purpose.size = htonl (sizeof (pm)), .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_DEPOSIT), .purse_pub = *purse_pub, + .h_denom_pub = *h_denom_pub, + .h_age_commitment = *h_age_commitment }; GNUNET_CRYPTO_hash (exchange_base_url, @@ -963,6 +1198,8 @@ TALER_wallet_purse_deposit_verify ( } +GNUNET_NETWORK_STRUCT_BEGIN + /** * Message signed to merge a purse into a reserve. */ @@ -992,10 +1229,11 @@ struct TALER_PurseMergePS }; +GNUNET_NETWORK_STRUCT_END void TALER_wallet_purse_merge_sign ( - const char *reserve_url, + const char *reserve_uri, struct GNUNET_TIME_Timestamp merge_timestamp, const struct TALER_PurseContractPublicKeyP *purse_pub, const struct TALER_PurseMergePrivateKeyP *merge_priv, @@ -1008,7 +1246,11 @@ TALER_wallet_purse_merge_sign ( .purse_pub = *purse_pub }; - TALER_payto_hash (reserve_url, + GNUNET_assert (0 == + strncasecmp (reserve_uri, + "payto://taler-reserve", + strlen ("payto://taler-reserve"))); + TALER_payto_hash (reserve_uri, &pm.h_payto); GNUNET_CRYPTO_eddsa_sign (&merge_priv->eddsa_priv, &pm, @@ -1018,7 +1260,7 @@ TALER_wallet_purse_merge_sign ( enum GNUNET_GenericReturnValue TALER_wallet_purse_merge_verify ( - const char *reserve_url, + const char *reserve_uri, struct GNUNET_TIME_Timestamp merge_timestamp, const struct TALER_PurseContractPublicKeyP *purse_pub, const struct TALER_PurseMergePublicKeyP *merge_pub, @@ -1031,7 +1273,15 @@ TALER_wallet_purse_merge_verify ( .purse_pub = *purse_pub }; - TALER_payto_hash (reserve_url, + if (0 != + strncasecmp (reserve_uri, + "payto://taler-reserve", + strlen ("payto://taler-reserve"))) + { + GNUNET_break (0); + return GNUNET_NO; + } + TALER_payto_hash (reserve_uri, &pm.h_payto); return GNUNET_CRYPTO_eddsa_verify ( TALER_SIGNATURE_WALLET_PURSE_MERGE, @@ -1041,6 +1291,8 @@ TALER_wallet_purse_merge_verify ( } +GNUNET_NETWORK_STRUCT_BEGIN + /** * Message signed by account to merge a purse into a reserve. */ @@ -1096,6 +1348,8 @@ struct TALER_AccountMergePS uint32_t flags GNUNET_PACKED; }; +GNUNET_NETWORK_STRUCT_END + void TALER_wallet_account_merge_sign ( @@ -1167,40 +1421,323 @@ TALER_wallet_account_merge_verify ( } +GNUNET_NETWORK_STRUCT_BEGIN + +/** + * Message signed by reserve key. + */ +struct TALER_ReserveOpenPS +{ + + /** + * Purpose is #TALER_SIGNATURE_WALLET_RESERVE_OPEN + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * Amount to be paid from the reserve balance to open + * the reserve. + */ + struct TALER_AmountNBO reserve_payment; + + /** + * When was the request created. + */ + struct GNUNET_TIME_TimestampNBO request_timestamp; + + /** + * For how long should the reserve be kept open. + * (Determines amount to be paid.) + */ + struct GNUNET_TIME_TimestampNBO reserve_expiration; + + /** + * How many open purses should be included with the + * open reserve? + * (Determines amount to be paid.) + */ + uint32_t purse_limit GNUNET_PACKED; + +}; + +GNUNET_NETWORK_STRUCT_END + + void -TALER_wallet_account_close_sign ( +TALER_wallet_reserve_open_sign ( + const struct TALER_Amount *reserve_payment, + struct GNUNET_TIME_Timestamp request_timestamp, + struct GNUNET_TIME_Timestamp reserve_expiration, + uint32_t purse_limit, const struct TALER_ReservePrivateKeyP *reserve_priv, struct TALER_ReserveSignatureP *reserve_sig) { - struct GNUNET_CRYPTO_EccSignaturePurpose purpose = { - .size = htonl (sizeof (purpose)), - .purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_CLOSE) + struct TALER_ReserveOpenPS rop = { + .purpose.size = htonl (sizeof (rop)), + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_OPEN), + .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp), + .reserve_expiration = GNUNET_TIME_timestamp_hton (reserve_expiration), + .purse_limit = htonl (purse_limit) }; + TALER_amount_hton (&rop.reserve_payment, + reserve_payment); GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign_ (&reserve_priv->eddsa_priv, - &purpose, + &rop.purpose, &reserve_sig->eddsa_signature)); } enum GNUNET_GenericReturnValue -TALER_wallet_account_close_verify ( +TALER_wallet_reserve_open_verify ( + const struct TALER_Amount *reserve_payment, + struct GNUNET_TIME_Timestamp request_timestamp, + struct GNUNET_TIME_Timestamp reserve_expiration, + uint32_t purse_limit, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_ReserveSignatureP *reserve_sig) { - struct GNUNET_CRYPTO_EccSignaturePurpose purpose = { - .size = htonl (sizeof (purpose)), - .purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_CLOSE) + struct TALER_ReserveOpenPS rop = { + .purpose.size = htonl (sizeof (rop)), + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_OPEN), + .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp), + .reserve_expiration = GNUNET_TIME_timestamp_hton (reserve_expiration), + .purse_limit = htonl (purse_limit) }; + TALER_amount_hton (&rop.reserve_payment, + reserve_payment); + return GNUNET_CRYPTO_eddsa_verify_ (TALER_SIGNATURE_WALLET_RESERVE_OPEN, + &rop.purpose, + &reserve_sig->eddsa_signature, + &reserve_pub->eddsa_pub); +} + + +GNUNET_NETWORK_STRUCT_BEGIN + +/** + * Message signed by + */ +struct TALER_ReserveOpenDepositPS +{ + + /** + * Purpose is #TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * Which reserve's opening signature should be paid for? + */ + struct TALER_ReserveSignatureP reserve_sig; + + /** + * Specifies how much of the coin's value should be spent on opening this + * reserve. + */ + struct TALER_AmountNBO coin_contribution; +}; + +GNUNET_NETWORK_STRUCT_END + + +// FIXME-#7267: add h_age_commitment, h_denom_pub to have proof! +void +TALER_wallet_reserve_open_deposit_sign ( + const struct TALER_Amount *coin_contribution, + const struct TALER_ReserveSignatureP *reserve_sig, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + struct TALER_CoinSpendSignatureP *coin_sig) +{ + struct TALER_ReserveOpenDepositPS rod = { + .purpose.size = htonl (sizeof (rod)), + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT), + .reserve_sig = *reserve_sig + }; + + TALER_amount_hton (&rod.coin_contribution, + coin_contribution); + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_eddsa_sign_ (&coin_priv->eddsa_priv, + &rod.purpose, + &coin_sig->eddsa_signature)); +} + + +enum GNUNET_GenericReturnValue +TALER_wallet_reserve_open_deposit_verify ( + const struct TALER_Amount *coin_contribution, + const struct TALER_ReserveSignatureP *reserve_sig, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendSignatureP *coin_sig) +{ + struct TALER_ReserveOpenDepositPS rod = { + .purpose.size = htonl (sizeof (rod)), + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT), + .reserve_sig = *reserve_sig + }; + + TALER_amount_hton (&rod.coin_contribution, + coin_contribution); + return GNUNET_CRYPTO_eddsa_verify_ ( + TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT, + &rod.purpose, + &coin_sig->eddsa_signature, + &coin_pub->eddsa_pub); +} + + +GNUNET_NETWORK_STRUCT_BEGIN + +/** + * Message signed by reserve key. + */ +struct TALER_ReserveClosePS +{ + + /** + * Purpose is #TALER_SIGNATURE_WALLET_RESERVE_CLOSE + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * When was the request created. + */ + struct GNUNET_TIME_TimestampNBO request_timestamp; + + /** + * Hash of the payto://-URI of the target account + * for the closure, or all zeros for the reserve + * origin account. + */ + struct TALER_PaytoHashP target_account_h_payto; + +}; + +GNUNET_NETWORK_STRUCT_END + + +void +TALER_wallet_reserve_close_sign ( + struct GNUNET_TIME_Timestamp request_timestamp, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_ReservePrivateKeyP *reserve_priv, + struct TALER_ReserveSignatureP *reserve_sig) +{ + struct TALER_ReserveClosePS rcp = { + .purpose.size = htonl (sizeof (rcp)), + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_CLOSE), + .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp) + }; + + if (NULL != h_payto) + rcp.target_account_h_payto = *h_payto; + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_eddsa_sign_ (&reserve_priv->eddsa_priv, + &rcp.purpose, + &reserve_sig->eddsa_signature)); +} + + +enum GNUNET_GenericReturnValue +TALER_wallet_reserve_close_verify ( + struct GNUNET_TIME_Timestamp request_timestamp, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig) +{ + struct TALER_ReserveClosePS rcp = { + .purpose.size = htonl (sizeof (rcp)), + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_CLOSE), + .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp) + }; + + if (NULL != h_payto) + rcp.target_account_h_payto = *h_payto; return GNUNET_CRYPTO_eddsa_verify_ (TALER_SIGNATURE_WALLET_RESERVE_CLOSE, - &purpose, + &rcp.purpose, &reserve_sig->eddsa_signature, &reserve_pub->eddsa_pub); } +GNUNET_NETWORK_STRUCT_BEGIN + +/** + * Message signed by reserve private key. + */ +struct TALER_ReserveAttestRequestPS +{ + + /** + * Purpose is #TALER_SIGNATURE_WALLET_ATTEST_REQUEST + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * When was the request created. + */ + struct GNUNET_TIME_TimestampNBO request_timestamp; + + /** + * Hash over the JSON array of requested attributes. + */ + struct GNUNET_HashCode h_details; + +}; + +GNUNET_NETWORK_STRUCT_END + + +void +TALER_wallet_reserve_attest_request_sign ( + struct GNUNET_TIME_Timestamp request_timestamp, + const json_t *details, + const struct TALER_ReservePrivateKeyP *reserve_priv, + struct TALER_ReserveSignatureP *reserve_sig) +{ + struct TALER_ReserveAttestRequestPS rcp = { + .purpose.size = htonl (sizeof (rcp)), + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_ATTEST_DETAILS), + .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp) + }; + + TALER_json_hash (details, + &rcp.h_details); + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_eddsa_sign_ (&reserve_priv->eddsa_priv, + &rcp.purpose, + &reserve_sig->eddsa_signature)); +} + + +enum GNUNET_GenericReturnValue +TALER_wallet_reserve_attest_request_verify ( + struct GNUNET_TIME_Timestamp request_timestamp, + const json_t *details, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig) +{ + struct TALER_ReserveAttestRequestPS rcp = { + .purpose.size = htonl (sizeof (rcp)), + .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_ATTEST_DETAILS), + .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp) + }; + + TALER_json_hash (details, + &rcp.h_details); + return GNUNET_CRYPTO_eddsa_verify_ ( + TALER_SIGNATURE_WALLET_RESERVE_ATTEST_DETAILS, + &rcp.purpose, + &reserve_sig->eddsa_signature, + &reserve_pub->eddsa_pub); +} + + +GNUNET_NETWORK_STRUCT_BEGIN + /** * Message signed by purse to associate an encrypted contract. */ @@ -1223,6 +1760,7 @@ struct TALER_PurseContractPS struct TALER_ContractDiffiePublicP contract_pub; }; +GNUNET_NETWORK_STRUCT_END void TALER_wallet_econtract_upload_sign ( @@ -1248,20 +1786,9 @@ TALER_wallet_econtract_upload_sign ( } -/** - * Verify a signature over encrypted contract. - * - * @param econtract encrypted contract - * @param econtract_size number of bytes in @a econtract - * @param contract_pub public key for the DH-encryption - * @param purse_pub purse’s public key - * @param purse_sig the signature made with purpose #TALER_SIGNATURE_WALLET_PURSE_CREATE - * @return #GNUNET_OK if the signature is valid - */ enum GNUNET_GenericReturnValue -TALER_wallet_econtract_upload_verify ( - const void *econtract, - size_t econtract_size, +TALER_wallet_econtract_upload_verify2 ( + const struct GNUNET_HashCode *h_econtract, const struct TALER_ContractDiffiePublicP *contract_pub, const struct TALER_PurseContractPublicKeyP *purse_pub, const struct TALER_PurseContractSignatureP *purse_sig) @@ -1269,12 +1796,10 @@ TALER_wallet_econtract_upload_verify ( struct TALER_PurseContractPS pc = { .purpose.size = htonl (sizeof (pc)), .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_ECONTRACT), - .contract_pub = *contract_pub + .contract_pub = *contract_pub, + .h_econtract = *h_econtract }; - GNUNET_CRYPTO_hash (econtract, - econtract_size, - &pc.h_econtract); return GNUNET_CRYPTO_eddsa_verify_ (TALER_SIGNATURE_WALLET_PURSE_ECONTRACT, &pc.purpose, &purse_sig->eddsa_signature, @@ -1282,4 +1807,24 @@ TALER_wallet_econtract_upload_verify ( } +enum GNUNET_GenericReturnValue +TALER_wallet_econtract_upload_verify ( + const void *econtract, + size_t econtract_size, + const struct TALER_ContractDiffiePublicP *contract_pub, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseContractSignatureP *purse_sig) +{ + struct GNUNET_HashCode h_econtract; + + GNUNET_CRYPTO_hash (econtract, + econtract_size, + &h_econtract); + return TALER_wallet_econtract_upload_verify2 (&h_econtract, + contract_pub, + purse_pub, + purse_sig); +} + + /* end of wallet_signatures.c */ |