diff options
author | Christian Blättler <blatc2@bfh.ch> | 2024-04-30 22:28:57 +0200 |
---|---|---|
committer | Christian Blättler <blatc2@bfh.ch> | 2024-04-30 22:28:57 +0200 |
commit | 079268ebddc6a5b0662d4481306d219e5e590dc7 (patch) | |
tree | acf0cd631501d6c3b993682545438dee02e05fb1 /src | |
parent | 45350614812212716af26d8161f7360810cef8cb (diff) |
work on tokens
Diffstat (limited to 'src')
-rw-r--r-- | src/include/taler_crypto_lib.h | 191 | ||||
-rw-r--r-- | src/include/taler_json_lib.h | 13 | ||||
-rw-r--r-- | src/json/json_helper.c | 128 | ||||
-rw-r--r-- | src/json/json_pack.c | 1 | ||||
-rw-r--r-- | src/util/merchant_signatures.c | 45 | ||||
-rw-r--r-- | src/util/tokens.c | 203 |
6 files changed, 505 insertions, 76 deletions
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index 5e5a15b71..0b5af6b9a 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -20,6 +20,7 @@ * @author Christian Grothoff <christian@grothoff.org> * @author Özgür Kesim <oec-taler@kesim.org> */ +#include <gnunet/gnunet_common.h> #if ! defined (__TALER_UTIL_LIB_H_INSIDE__) #error "Only <taler_util.h> can be included directly." #endif @@ -2293,10 +2294,11 @@ struct TALER_TokenIssueSignatureP /** * Blinded signature created using merchants token issue private key. + * TODO: Rename to TALER_BlindedTokenIssueSignatureP */ struct TALER_TokenIssueBlindSignatureP { - struct GNUNET_CRYPTO_BlindedSignature signature; + struct GNUNET_CRYPTO_BlindedSignature *signature; }; @@ -2311,6 +2313,15 @@ struct TALER_TokenUsePublicKeyP /** + * Has of the public key of a token. + */ +struct TALER_TokenUsePublicKeyHashP +{ + struct GNUNET_HashCode hash; +}; + + +/** * The private key of a token. An EdDSA private key generated by the wallet. * Used to create @struct TALER_TokenUseSignatureP confirm the usage of a token. */ @@ -2328,6 +2339,36 @@ struct TALER_TokenUseSignatureP struct GNUNET_CRYPTO_EddsaSignature signature; }; + +/** + * Master key material for the deriviation of tokens and + * blinding factors during token envelope creation. + */ +struct TALER_TokenUseMasterSecretP +{ + + /** + * Key material. + */ + uint32_t key_data[8]; + +}; + + +/** + * Inputs needed from the merchant for blind signing tokens. + */ +struct TALER_TokenUseMerchantValues +{ + + /** + * Input values. + */ + struct GNUNET_CRYPTO_BlindingInputValues *blinding_inputs; +}; + + + /** * The blinded token use public key of a token. Ready to be signed by the merchant. */ @@ -2349,6 +2390,125 @@ void TALER_token_issue_sig_free (struct TALER_TokenIssueSignatureP *issue_sig); +/** + * Free internals of @a issue_sig, but not @a issue_sig itself. + * + * @param[in] issue_sig signature to free + */ +void +TALER_blinded_issue_sig_free (struct TALER_TokenIssueBlindSignatureP *issue_sig); + + +/** + * Setup secret seed information for fresh tokens to be + * issued. + * + * @param[out] master value to initialize + */ +void +TALER_token_use_setup_random (struct TALER_TokenUseMasterSecretP *master); + + +/** + * Create private key for a token. + * + * @param master secret to derive token use private key from + * @param alg_values includes algorithm specific values + * @param[out] token_priv private key to initialize + */ +void +TALER_token_use_setup_priv ( + const struct TALER_TokenUseMasterSecretP *master, + const struct TALER_TokenUseMerchantValues *alg_values, + struct TALER_TokenUsePrivateKeyP *token_priv); + + +/** + * Create a token use blinding secret @a bks given the wallets + * @a master secret and the alg_values from the merchant. + * + * @param master secret to derive blindings from + * @param alg_values withdraw values containing cipher and additional CS values + * @param[out] bks blinding secrets + */ +void +TALER_token_use_blinding_secret_create ( + const struct TALER_TokenUseMasterSecretP *master, + const struct TALER_TokenUseMerchantValues *alg_values, + union GNUNET_CRYPTO_BlindingSecretP *bks); + + +/** + * Return the alg value singleton for creation of + * blinding secrets for RSA. + * + * @return singleton to use for RSA blinding + */ +const struct TALER_TokenUseMerchantValues * +TALER_token_bling_input_rsa_singleton (); + + +/** + * Make a (deep) copy of the given @a bi_src to + * @a bi_dst. + * + * @param[out] bi_dst target to copy to + * @param bi_src blinding input values to copy + */ +void +TALER_token_blind_input_copy (struct TALER_TokenUseMerchantValues *bi_dst, + const struct TALER_TokenUseMerchantValues *bi_src); + + +/** + * Issue a new token by blindly signing a token envelope with + * the token issue private key. + * + * @param issue_priv private key to use for signing + * @param envelope token envelope to sign over + * @param[out] issue_sig where to write the signature + * @return #GNUNET_OK on success + */ +enum GNUNET_GenericReturnValue +TALER_token_issue_sign (const struct TALER_TokenIssuePrivateKeyP *issue_priv, + const struct TALER_TokenEnvelopeP *envelope, + struct TALER_TokenIssueBlindSignatureP *issue_sig); + + +/** + * Verify a token issue signature made by the merchant. + * + * @param use_pub token use public key + * @param issue_pub public key of the token issue + * @param ub_sig signature to verify + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_token_issue_verify (const struct TALER_TokenUsePublicKeyP *use_pub, + const struct TALER_TokenIssuePublicKeyP *issue_pub, + const struct TALER_TokenIssueSignatureP *ub_sig); + +/** + * Unblind blinded signature. + * + * @param[out] issue_sig where to write the unblinded signature + * @param blinded_sig the blinded signature + * @param secret blinding secret to use + * @param use_pub_hash token use public key hash for verification of the signature + * @param alg_values algorithm specific values + * @param issue_pub public key used for signing + * @return #GNUNET_OK on success or #GNUNET_SYSERR on failure + */ +enum GNUNET_GenericReturnValue +TALER_token_issue_sig_unblind ( + struct TALER_TokenIssueSignatureP *issue_sig, + const struct TALER_TokenIssueBlindSignatureP *blinded_sig, + const union GNUNET_CRYPTO_BlindingSecretP *secret, + const struct TALER_TokenUsePublicKeyHashP *use_pub_hash, + const struct TALER_TokenUseMerchantValues *alg_values, + const struct TALER_TokenIssuePublicKeyP *issue_pub); + + /* **************** AML officer signatures **************** */ /** @@ -3924,35 +4084,6 @@ TALER_merchant_refund_verify ( const struct TALER_MerchantSignatureP *merchant_sig); -/** - * Issue a new token by signing a token envelope, that contains the - * blinded public key provided by the wallet. - * - * @param envelope the token envelope to sign - * @param issue_priv token issue private key to sign with - * @param[out] blind_sig where to write the blinded issue signature - */ -void -TALER_merchant_token_issue_sign ( - const struct TALER_TokenEnvelopeP *envelope, - const struct TALER_TokenIssuePrivateKeyP *issue_priv, - struct TALER_TokenIssueBlindSignatureP *blind_sig); - - -/** - * Verify a token issue signature. - * - * @param use_pub token use public key - * @param issue_pub token issue public key - * @param ub_sig unblinded signature - */ -enum GNUNET_GenericReturnValue -TALER_merchant_token_issue_verify ( - const struct TALER_TokenUsePublicKeyP *use_pub, - const struct TALER_TokenIssuePublicKeyP *issue_pub, - const struct TALER_TokenIssueSignatureP *ub_sig); - - /* ********************* exchange deposit signing ************************* */ /** diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h index 22e44fdf0..c00fdbcf0 100644 --- a/src/include/taler_json_lib.h +++ b/src/include/taler_json_lib.h @@ -629,6 +629,19 @@ TALER_JSON_spec_token_issue_sig (const char *field, /** * Generate line in parser specification for a + * blinded token issue signature. + * + * @param field name of the field + * @param[out] sig the blinded signature to initialize + * @return corresponding field spec + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_blinded_token_issue_sig ( + const char *field, + struct TALER_TokenIssueBlindSignatureP *sig); + +/** + * Generate line in parser specification for a * token envelope. * * @param field name of the field diff --git a/src/json/json_helper.c b/src/json/json_helper.c index 40b9c78d5..9870f252e 100644 --- a/src/json/json_helper.c +++ b/src/json/json_helper.c @@ -661,6 +661,134 @@ TALER_JSON_spec_token_issue_sig (const char *field, } +/** + * Parse given JSON object to blinded token issue signature. + * + * @param cls closure, NULL + * @param root the json object representing data + * @param[out] spec where to write the data + * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error + */ +static enum GNUNET_GenericReturnValue +parse_blinded_token_issue_sig (void *cls, + json_t *root, + struct GNUNET_JSON_Specification *spec) +{ + struct TALER_TokenIssueBlindSignatureP *issue_sig = spec->ptr; + struct GNUNET_CRYPTO_BlindedSignature *blinded_sig; + const char *cipher; + struct GNUNET_JSON_Specification dspec[] = { + GNUNET_JSON_spec_string ("cipher", + &cipher), + GNUNET_JSON_spec_end () + }; + const char *emsg; + unsigned int eline; + + (void) cls; + if (GNUNET_OK != + GNUNET_JSON_parse (root, + dspec, + &emsg, + &eline)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + blinded_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature); + blinded_sig->cipher = string_to_cipher (cipher); + blinded_sig->rc = 1; + switch (blinded_sig->cipher) + { + case GNUNET_CRYPTO_BSA_INVALID: + break; + case GNUNET_CRYPTO_BSA_RSA: + { + struct GNUNET_JSON_Specification ispec[] = { + GNUNET_JSON_spec_rsa_signature ( + "blinded_rsa_signature", + &blinded_sig->details.blinded_rsa_signature), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (root, + ispec, + &emsg, + &eline)) + { + GNUNET_break_op (0); + GNUNET_free (blinded_sig); + return GNUNET_SYSERR; + } + issue_sig->signature = blinded_sig; + return GNUNET_OK; + } + case GNUNET_CRYPTO_BSA_CS: + { + struct GNUNET_JSON_Specification ispec[] = { + GNUNET_JSON_spec_uint32 ("b", + &blinded_sig->details.blinded_cs_answer.b), + GNUNET_JSON_spec_fixed_auto ("s", + &blinded_sig->details.blinded_cs_answer. + s_scalar), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (root, + ispec, + &emsg, + &eline)) + { + GNUNET_break_op (0); + GNUNET_free (blinded_sig); + return GNUNET_SYSERR; + } + issue_sig->signature = blinded_sig; + return GNUNET_OK; + } + } + GNUNET_break_op (0); + GNUNET_free (blinded_sig); + return GNUNET_SYSERR; +} + + +/** + * Cleanup data left from parsing blinded token sisue sig. + * + * @param cls closure, NULL + * @param[out] spec where to free the data + */ +static void +clean_blinded_token_issue_sig (void *cls, + struct GNUNET_JSON_Specification *spec) +{ + struct TALER_TokenIssueBlindSignatureP *issue_sig = spec->ptr; + + (void) cls; + TALER_blinded_issue_sig_free (issue_sig); +} + + +struct GNUNET_JSON_Specification +TALER_JSON_spec_blinded_token_issue_sig ( + const char *field, + struct TALER_TokenIssueBlindSignatureP *sig) +{ + struct GNUNET_JSON_Specification ret = { + .parser = &parse_blinded_token_issue_sig, + .cleaner = &clean_blinded_token_issue_sig, + .field = field, + .ptr = sig + }; + + sig->signature = NULL; + return ret; +} + + struct GNUNET_JSON_Specification TALER_JSON_spec_token_envelope (const char *field, struct TALER_TokenEnvelopeP *env) diff --git a/src/json/json_pack.c b/src/json/json_pack.c index 427ac3e85..82eb91cc8 100644 --- a/src/json/json_pack.c +++ b/src/json/json_pack.c @@ -272,7 +272,6 @@ TALER_JSON_pack_blinded_planchet ( const char *name, const struct TALER_BlindedPlanchet *blinded_planchet) { - const struct GNUNET_CRYPTO_BlindedMessage *bm; struct GNUNET_JSON_PackSpec ps = { .field_name = name, }; diff --git a/src/util/merchant_signatures.c b/src/util/merchant_signatures.c index 06708f4b4..4dca3c652 100644 --- a/src/util/merchant_signatures.c +++ b/src/util/merchant_signatures.c @@ -346,49 +346,4 @@ TALER_merchant_contract_sign ( merch_sig); } - -// NB: "TALER_merchant_contract_verify" not (yet?) needed / not defined. - - -GNUNET_NETWORK_STRUCT_BEGIN - -/** - * Message blindly signed by merchant to issue a new token. - */ -struct TALER_TokenIssueRequestPS -{ - - // TODO: Implement this struct - -}; - -GNUNET_NETWORK_STRUCT_END - - -void -TALER_merchant_token_issue_sign ( - const struct TALER_TokenEnvelopeP *envelope, - const struct TALER_TokenIssuePrivateKeyP *issue_priv, - struct TALER_TokenIssueBlindSignatureP *blind_sig) -{ - -} - - -/** - * Verify a token issue signature. - * - * @param use_pub token use public key - * @param issue_pub token issue public key - * @param ub_sig unblinded signature - */ -enum GNUNET_GenericReturnValue -TALER_merchant_token_issue_verify ( - const struct TALER_TokenUsePublicKeyP *use_pub, - const struct TALER_TokenIssuePublicKeyP *issue_pub, - const struct TALER_TokenIssueSignatureP *ub_sig) -{ - return GNUNET_NO; -} - /* end of merchant_signatures.c */ diff --git a/src/util/tokens.c b/src/util/tokens.c index 3086d8777..481eb6d20 100644 --- a/src/util/tokens.c +++ b/src/util/tokens.c @@ -31,3 +31,206 @@ TALER_token_issue_sig_free (struct TALER_TokenIssueSignatureP *issue_sig) issue_sig->signature = NULL; } } + + +void +TALER_blinded_issue_sig_free ( + struct TALER_TokenIssueBlindSignatureP *issue_sig) +{ + if (NULL != issue_sig->signature) + { + GNUNET_CRYPTO_blinded_sig_decref (issue_sig->signature); + issue_sig->signature = NULL; + } +} + + +void +TALER_token_use_setup_random (struct TALER_TokenUseMasterSecretP *master) +{ + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, + master, + sizeof (*master)); +} + + +void +TALER_token_use_setup_priv ( + const struct TALER_TokenUseMasterSecretP *master, + const struct TALER_TokenUseMerchantValues *alg_values, + struct TALER_TokenUsePrivateKeyP *token_priv) +{ + /* TODO: Maybe extract common code between this + function and TALER_planchet_setup_coin_priv (). */ + const struct GNUNET_CRYPTO_BlindingInputValues *bi + = alg_values->blinding_inputs; + + switch (bi->cipher) + { + case GNUNET_CRYPTO_BSA_INVALID: + GNUNET_break (0); + memset (token_priv, + 0, + sizeof (*token_priv)); + return; + case GNUNET_CRYPTO_BSA_RSA: + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (token_priv, + sizeof (*token_priv), + "token", + strlen ("token"), + master, + sizeof(*master), + NULL, + 0)); + return; + case GNUNET_CRYPTO_BSA_CS: + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (token_priv, + sizeof (*token_priv), + "token", + strlen ("token"), + master, + sizeof(*master), + &bi->details.cs_values, + sizeof(bi->details.cs_values), + NULL, + 0)); + return; + } + GNUNET_assert (0); +} + + +void +TALER_token_use_blinding_secret_create ( + const struct TALER_TokenUseMasterSecretP *master, + const struct TALER_TokenUseMerchantValues *alg_values, + union GNUNET_CRYPTO_BlindingSecretP *bks) +{ + /* TODO: Extract common code between this + function and TALER_planchet_blinding_secret_create (). */ + const struct GNUNET_CRYPTO_BlindingInputValues *bi = + alg_values->blinding_inputs; + + switch (bi->cipher) + { + case GNUNET_CRYPTO_BSA_INVALID: + GNUNET_break (0); + return; + case GNUNET_CRYPTO_BSA_RSA: + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (&bks->rsa_bks, + sizeof (bks->rsa_bks), + "bks", + strlen ("bks"), + master, + sizeof(*master), + NULL, + 0)); + return; + case GNUNET_CRYPTO_BSA_CS: + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (&bks->nonce, + sizeof (bks->nonce), + "bseed", + strlen ("bseed"), + master, + sizeof(*master), + &bi->details.cs_values, + sizeof(bi->details.cs_values), + NULL, + 0)); + return; + } + GNUNET_assert (0); +} + + +const struct TALER_TokenUseMerchantValues * +TALER_token_bling_input_rsa_singleton () +{ + static struct GNUNET_CRYPTO_BlindingInputValues bi = { + .cipher = GNUNET_CRYPTO_BSA_RSA + }; + static struct TALER_TokenUseMerchantValues alg_values = { + .blinding_inputs = &bi + }; + return &alg_values; +} + + +void +TALER_token_blind_input_copy (struct TALER_TokenUseMerchantValues *bi_dst, + const struct TALER_TokenUseMerchantValues *bi_src) +{ + if (bi_src == TALER_token_bling_input_rsa_singleton ()) + { + *bi_dst = *bi_src; + return; + } + bi_dst->blinding_inputs + = GNUNET_CRYPTO_blinding_input_values_incref (bi_src->blinding_inputs); +} + + +enum GNUNET_GenericReturnValue +TALER_token_issue_sign (const struct TALER_TokenIssuePrivateKeyP *issue_priv, + const struct TALER_TokenEnvelopeP *envelope, + struct TALER_TokenIssueBlindSignatureP *issue_sig) +{ + issue_sig->signature + = GNUNET_CRYPTO_blind_sign (issue_priv->private_key, + "tk", /* TODO: What is a good value here? */ + envelope->blinded_pub); + if (NULL == issue_sig->signature) + return GNUNET_SYSERR; + return GNUNET_OK; +} + +enum GNUNET_GenericReturnValue +TALER_token_issue_verify (const struct TALER_TokenUsePublicKeyP *use_pub, + const struct TALER_TokenIssuePublicKeyP *issue_pub, + const struct TALER_TokenIssueSignatureP *ub_sig) +{ + struct GNUNET_HashCode h_use_pub; + + GNUNET_CRYPTO_hash (&use_pub->public_key, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), + &h_use_pub); + + if (GNUNET_OK != + GNUNET_CRYPTO_blind_sig_verify (issue_pub->public_key, + ub_sig->signature, + &h_use_pub, + sizeof (h_use_pub))) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + +enum GNUNET_GenericReturnValue +TALER_token_issue_sig_unblind ( + struct TALER_TokenIssueSignatureP *issue_sig, + const struct TALER_TokenIssueBlindSignatureP *blinded_sig, + const union GNUNET_CRYPTO_BlindingSecretP *secret, + const struct TALER_TokenUsePublicKeyHashP *use_pub_hash, + const struct TALER_TokenUseMerchantValues *alg_values, + const struct TALER_TokenIssuePublicKeyP *issue_pub) +{ + issue_sig->signature + = GNUNET_CRYPTO_blind_sig_unblind (blinded_sig->signature, + secret, + &use_pub_hash->hash, + sizeof (use_pub_hash->hash), + alg_values->blinding_inputs, + issue_pub->public_key); + if (NULL == issue_sig->signature) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +}
\ No newline at end of file |