From 18a2fae3b594f7ef54104b708d00641f6ed5de1e Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 18 Sep 2022 17:36:35 +0200 Subject: add new signature functions for DD31 --- src/util/exchange_signatures.c | 99 ++++++++++++ src/util/util.c | 25 +++ src/util/wallet_signatures.c | 357 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 467 insertions(+), 14 deletions(-) (limited to 'src/util') diff --git a/src/util/exchange_signatures.c b/src/util/exchange_signatures.c index 52919d2e9..d42f70d66 100644 --- a/src/util/exchange_signatures.c +++ b/src/util/exchange_signatures.c @@ -1591,4 +1591,103 @@ TALER_exchange_online_purse_status_verify ( } +GNUNET_NETWORK_STRUCT_BEGIN + +/** + * Message signed by the exchange to affirm that the + * owner of a reserve has certain attributes. + */ +struct TALER_ExchangeAttestPS +{ + + /** + * Purpose is #TALER_SIGNATURE_EXCHANGE_RESERVE_ATTEST_DETAILS + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * Time when the attestation was made. + */ + struct GNUNET_TIME_TimestampNBO attest_timestamp; + + /** + * Time when the attestation expires. + */ + struct GNUNET_TIME_TimestampNBO expiration_time; + + /** + * Public key of the reserve for which the attributes + * are attested. + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * Hash over the attributes. + */ + struct GNUNET_HashCode h_attributes; + +}; + +GNUNET_NETWORK_STRUCT_END + + +enum TALER_ErrorCode +TALER_exchange_online_reserve_attest_details_sign ( + TALER_ExchangeSignCallback scb, + struct GNUNET_TIME_Timestamp attest_timestamp, + struct GNUNET_TIME_Timestamp expiration_time, + const struct TALER_ReservePublicKeyP *reserve_pub, + const json_t *attributes, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig) +{ + struct TALER_ExchangeAttestPS rap = { + .purpose.size = htonl (sizeof (rap)), + .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_ATTEST_DETAILS), + .attest_timestamp = GNUNET_TIME_timestamp_hton (attest_timestamp), + .expiration_time = GNUNET_TIME_timestamp_hton (expiration_time), + .reserve_pub = *reserve_pub + }; + + TALER_json_hash (attributes, + &rap.h_attributes); + return scb (&rap.purpose, + pub, + sig); +} + + +enum GNUNET_GenericReturnValue +TALER_exchange_online_reserve_attest_details_verify ( + struct GNUNET_TIME_Timestamp attest_timestamp, + struct GNUNET_TIME_Timestamp expiration_time, + const struct TALER_ReservePublicKeyP *reserve_pub, + const json_t *attributes, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig) +{ + struct TALER_ExchangeAttestPS rap = { + .purpose.size = htonl (sizeof (rap)), + .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_ATTEST_DETAILS), + .attest_timestamp = GNUNET_TIME_timestamp_hton (attest_timestamp), + .expiration_time = GNUNET_TIME_timestamp_hton (expiration_time), + .reserve_pub = *reserve_pub + }; + + TALER_json_hash (attributes, + &rap.h_attributes); + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_verify ( + TALER_SIGNATURE_EXCHANGE_RESERVE_ATTEST_DETAILS, + &rap, + &sig->eddsa_signature, + &pub->eddsa_pub)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + /* end of exchange_signatures.c */ diff --git a/src/util/util.c b/src/util/util.c index 2d10fd69d..f715456d8 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -217,6 +217,31 @@ TALER_denom_fee_check_currency ( } +/** + * Hash normalized @a j JSON object or array and + * store the result in @a hc. + * + * @param j JSON to hash + * @param[out] hc where to write the hash + */ +void +TALER_json_hash (const json_t *j, + struct GNUNET_HashCode *hc) +{ + char *cstr; + size_t clen; + + cstr = json_dumps (j, + JSON_COMPACT | JSON_SORT_KEYS); + GNUNET_assert (NULL != cstr); + clen = strlen (cstr); + GNUNET_CRYPTO_hash (cstr, + clen, + hc); + free (cstr); +} + + #ifdef __APPLE__ char * strchrnul (const char *s, diff --git a/src/util/wallet_signatures.c b/src/util/wallet_signatures.c index 64c9ebcba..4e4932a2b 100644 --- a/src/util/wallet_signatures.c +++ b/src/util/wallet_signatures.c @@ -23,6 +23,8 @@ #include "taler_signatures.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. @@ -109,6 +111,7 @@ struct TALER_DepositRequestPS }; +GNUNET_NETWORK_STRUCT_END void TALER_wallet_deposit_sign ( @@ -199,6 +202,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. @@ -233,6 +238,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, @@ -279,6 +285,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 @@ -304,6 +312,8 @@ struct TALER_RecoupRequestPS }; +GNUNET_NETWORK_STRUCT_END + enum GNUNET_GenericReturnValue TALER_wallet_recoup_verify ( @@ -387,6 +397,8 @@ TALER_wallet_recoup_refresh_sign ( } +GNUNET_NETWORK_STRUCT_BEGIN + /** * @brief Message signed by a coin to indicate that the coin should be * melted. @@ -438,6 +450,7 @@ struct TALER_RefreshMeltCoinAffirmationPS struct TALER_AmountNBO melt_fee; }; +GNUNET_NETWORK_STRUCT_END void TALER_wallet_melt_sign ( @@ -504,6 +517,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. @@ -538,6 +554,8 @@ struct TALER_WithdrawRequestPS }; +GNUNET_NETWORK_STRUCT_END + void TALER_wallet_withdraw_sign ( const struct TALER_DenominationHashP *h_denom_pub, @@ -621,6 +639,8 @@ TALER_wallet_account_setup_verify ( } +GNUNET_NETWORK_STRUCT_BEGIN + /** * Response by which a wallet requests a full * reserve history and indicates it is willing @@ -647,6 +667,9 @@ struct TALER_ReserveHistoryRequestPS }; +GNUNET_NETWORK_STRUCT_END + + enum GNUNET_GenericReturnValue TALER_wallet_reserve_history_verify ( const struct GNUNET_TIME_Timestamp ts, @@ -691,6 +714,8 @@ TALER_wallet_reserve_history_sign ( } +GNUNET_NETWORK_STRUCT_BEGIN + /** * Response by which a wallet requests an account status. */ @@ -709,6 +734,7 @@ struct TALER_ReserveStatusRequestPS }; +GNUNET_NETWORK_STRUCT_END enum GNUNET_GenericReturnValue TALER_wallet_reserve_status_verify ( @@ -748,6 +774,8 @@ TALER_wallet_reserve_status_sign ( } +GNUNET_NETWORK_STRUCT_BEGIN + /** * Message signed to create a purse (without reserve). */ @@ -787,6 +815,9 @@ struct TALER_PurseCreatePS }; +GNUNET_NETWORK_STRUCT_END + + void TALER_wallet_purse_create_sign ( struct GNUNET_TIME_Timestamp purse_expiration, @@ -877,6 +908,8 @@ TALER_wallet_purse_status_verify ( } +GNUNET_NETWORK_STRUCT_BEGIN + /** * Message signed to deposit a coin into a purse. */ @@ -916,6 +949,7 @@ struct TALER_PurseDepositPS struct GNUNET_HashCode h_exchange_base_url GNUNET_PACKED; }; +GNUNET_NETWORK_STRUCT_END void TALER_wallet_purse_deposit_sign ( @@ -977,6 +1011,8 @@ TALER_wallet_purse_deposit_verify ( } +GNUNET_NETWORK_STRUCT_BEGIN + /** * Message signed to merge a purse into a reserve. */ @@ -1006,6 +1042,7 @@ struct TALER_PurseMergePS }; +GNUNET_NETWORK_STRUCT_END void TALER_wallet_purse_merge_sign ( @@ -1067,6 +1104,8 @@ TALER_wallet_purse_merge_verify ( } +GNUNET_NETWORK_STRUCT_BEGIN + /** * Message signed by account to merge a purse into a reserve. */ @@ -1122,6 +1161,8 @@ struct TALER_AccountMergePS uint32_t flags GNUNET_PACKED; }; +GNUNET_NETWORK_STRUCT_END + void TALER_wallet_account_merge_sign ( @@ -1193,44 +1234,331 @@ TALER_wallet_account_merge_verify ( } +GNUNET_NETWORK_STRUCT_BEGIN + +/** + * Message signed by + */ +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 ( - // FIXME: add max amount (optional) - // timestamp, target account (optional) +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 ( - // FIXME: add max amount (optional), - // timestamp, target account (optional) +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; + + /** + * When was the request created. + */ + struct GNUNET_TIME_TimestampNBO request_timestamp; + + /** + * Which reserve's opening should be paid for? + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * Specifies how much of the coin's value should be spent on opening this + * reserve. + */ + struct TALER_AmountNBO coin_contribution; +}; + +GNUNET_NETWORK_STRUCT_END + + +void +TALER_wallet_reserve_open_deposit_sign ( + const struct TALER_Amount *coin_contribution, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct GNUNET_TIME_Timestamp request_timestamp, + 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), + .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp), + .reserve_pub = *reserve_pub }; + 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_ReservePublicKeyP *reserve_pub, + struct GNUNET_TIME_Timestamp request_timestamp, + 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), + .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp), + .reserve_pub = *reserve_pub + }; + + 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 + */ +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 + * origina ccount. + */ + 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 + */ +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. */ @@ -1253,6 +1581,7 @@ struct TALER_PurseContractPS struct TALER_ContractDiffiePublicP contract_pub; }; +GNUNET_NETWORK_STRUCT_END void TALER_wallet_econtract_upload_sign ( -- cgit v1.2.3