aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Blättler <blatc2@bfh.ch>2024-04-30 22:28:57 +0200
committerChristian Blättler <blatc2@bfh.ch>2024-04-30 22:28:57 +0200
commit079268ebddc6a5b0662d4481306d219e5e590dc7 (patch)
treeacf0cd631501d6c3b993682545438dee02e05fb1 /src
parent45350614812212716af26d8161f7360810cef8cb (diff)
work on tokens
Diffstat (limited to 'src')
-rw-r--r--src/include/taler_crypto_lib.h191
-rw-r--r--src/include/taler_json_lib.h13
-rw-r--r--src/json/json_helper.c128
-rw-r--r--src/json/json_pack.c1
-rw-r--r--src/util/merchant_signatures.c45
-rw-r--r--src/util/tokens.c203
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