Compare commits
14 Commits
e3d5672cbd
...
9c66f27034
Author | SHA1 | Date | |
---|---|---|---|
9c66f27034 | |||
777a4c07cf | |||
ce71db2c0b | |||
4931e30948 | |||
|
9d5549d6ba | ||
|
74facbead4 | ||
|
269425672c | ||
|
90664b555c | ||
|
890c962817 | ||
|
21c9dae382 | ||
b7e20eb71e | |||
2d1583f96b | |||
20cd46f63d | |||
|
e2deb89a3d |
@ -1 +1 @@
|
|||||||
Subproject commit 02132ededc12a0a1cfd81f0ca76c384304e15259
|
Subproject commit 1ec4596bf4925ee24fc06d3e74d2a553b8239870
|
@ -8,11 +8,19 @@ PartOf=taler-exchange.target
|
|||||||
[Service]
|
[Service]
|
||||||
User=taler-exchange-httpd
|
User=taler-exchange-httpd
|
||||||
Type=simple
|
Type=simple
|
||||||
# Depending on the configuration, the service suicides and then
|
|
||||||
# needs to be restarted.
|
# Depending on the configuration, the service process kills itself and then
|
||||||
|
# needs to be restarted. Thus no significant delay on restarts.
|
||||||
Restart=always
|
Restart=always
|
||||||
# Do not dally on restarts.
|
|
||||||
RestartSec=1ms
|
RestartSec=1ms
|
||||||
|
|
||||||
|
# Disable the service if more than 5 restarts are encountered within 5s.
|
||||||
|
# These are usually the systemd defaults, but can be overwritten, thus we set
|
||||||
|
# them here explicitly, as the exchange code assumes StartLimitInterval
|
||||||
|
# to be >=5s.
|
||||||
|
StartLimitBurst=5
|
||||||
|
StartLimitInterval=5s
|
||||||
|
|
||||||
ExecStart=/usr/bin/taler-exchange-httpd -c /etc/taler/taler.conf
|
ExecStart=/usr/bin/taler-exchange-httpd -c /etc/taler/taler.conf
|
||||||
StandardOutput=journal
|
StandardOutput=journal
|
||||||
StandardError=journal
|
StandardError=journal
|
||||||
|
@ -248,12 +248,15 @@ TALER_BANK_credit_history (struct GNUNET_CURL_Context *ctx,
|
|||||||
{
|
{
|
||||||
if ( (0 < num_results) &&
|
if ( (0 < num_results) &&
|
||||||
(! GNUNET_TIME_relative_is_zero (timeout)) )
|
(! GNUNET_TIME_relative_is_zero (timeout)) )
|
||||||
|
/* 0 == start_row is implied, go with timeout into future */
|
||||||
GNUNET_snprintf (url,
|
GNUNET_snprintf (url,
|
||||||
sizeof (url),
|
sizeof (url),
|
||||||
"history/incoming?delta=%lld&long_poll_ms=%llu",
|
"history/incoming?delta=%lld&long_poll_ms=%llu",
|
||||||
(long long) num_results,
|
(long long) num_results,
|
||||||
tms);
|
tms);
|
||||||
else
|
else
|
||||||
|
/* Going back from current transaction or have no timeout;
|
||||||
|
hence timeout makes no sense */
|
||||||
GNUNET_snprintf (url,
|
GNUNET_snprintf (url,
|
||||||
sizeof (url),
|
sizeof (url),
|
||||||
"history/incoming?delta=%lld",
|
"history/incoming?delta=%lld",
|
||||||
@ -263,6 +266,7 @@ TALER_BANK_credit_history (struct GNUNET_CURL_Context *ctx,
|
|||||||
{
|
{
|
||||||
if ( (0 < num_results) &&
|
if ( (0 < num_results) &&
|
||||||
(! GNUNET_TIME_relative_is_zero (timeout)) )
|
(! GNUNET_TIME_relative_is_zero (timeout)) )
|
||||||
|
/* going forward from num_result */
|
||||||
GNUNET_snprintf (url,
|
GNUNET_snprintf (url,
|
||||||
sizeof (url),
|
sizeof (url),
|
||||||
"history/incoming?delta=%lld&start=%llu&long_poll_ms=%llu",
|
"history/incoming?delta=%lld&start=%llu&long_poll_ms=%llu",
|
||||||
@ -270,6 +274,8 @@ TALER_BANK_credit_history (struct GNUNET_CURL_Context *ctx,
|
|||||||
(unsigned long long) start_row,
|
(unsigned long long) start_row,
|
||||||
tms);
|
tms);
|
||||||
else
|
else
|
||||||
|
/* going backwards or have no timeout;
|
||||||
|
hence timeout makes no sense */
|
||||||
GNUNET_snprintf (url,
|
GNUNET_snprintf (url,
|
||||||
sizeof (url),
|
sizeof (url),
|
||||||
"history/incoming?delta=%lld&start=%llu",
|
"history/incoming?delta=%lld&start=%llu",
|
||||||
|
@ -80,6 +80,11 @@
|
|||||||
*/
|
*/
|
||||||
#define UNIX_BACKLOG 50
|
#define UNIX_BACKLOG 50
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How often will we try to connect to the database before giving up?
|
||||||
|
*/
|
||||||
|
#define MAX_DB_RETRIES 5
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Above what request latency do we start to log?
|
* Above what request latency do we start to log?
|
||||||
*/
|
*/
|
||||||
@ -1965,11 +1970,20 @@ exchange_serve_process_config (void)
|
|||||||
GNUNET_free (attr_enc_key_str);
|
GNUNET_free (attr_enc_key_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL ==
|
for (unsigned int i = 0; i<MAX_DB_RETRIES; i++)
|
||||||
(TEH_plugin = TALER_EXCHANGEDB_plugin_load (TEH_cfg)))
|
{
|
||||||
|
TEH_plugin = TALER_EXCHANGEDB_plugin_load (TEH_cfg);
|
||||||
|
if (NULL != TEH_plugin)
|
||||||
|
break;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||||
|
"Failed to connect to DB, will try again %u times\n",
|
||||||
|
MAX_DB_RETRIES - i);
|
||||||
|
sleep (1);
|
||||||
|
}
|
||||||
|
if (NULL == TEH_plugin)
|
||||||
{
|
{
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
"Failed to initialize DB subsystem\n");
|
"Failed to initialize DB subsystem. Giving up.\n");
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
return GNUNET_OK;
|
return GNUNET_OK;
|
||||||
|
@ -28,22 +28,6 @@
|
|||||||
#include "taler-exchange-httpd_responses.h"
|
#include "taler-exchange-httpd_responses.h"
|
||||||
#include "taler-exchange-httpd_keys.h"
|
#include "taler-exchange-httpd_keys.h"
|
||||||
|
|
||||||
/**
|
|
||||||
* Clients have to prove that the public keys for all age groups larger than
|
|
||||||
* the allowed maximum age group are derived by scalar multiplication from this
|
|
||||||
* Edx25519 public key (in Crockford Base32 encoding):
|
|
||||||
*
|
|
||||||
* DZJRF6HXN520505XDAWM8NMH36QV9J3VH77265WQ09EBQ76QSKCG
|
|
||||||
*
|
|
||||||
* The private key was chosen randomly and then deleted.
|
|
||||||
*/
|
|
||||||
static struct GNUNET_CRYPTO_Edx25519PublicKey publishedBaseKey = {
|
|
||||||
.q_y = { 0x6f, 0xe5, 0x87, 0x9a, 0x3d, 0xa9, 0x44, 0x20,
|
|
||||||
0x80, 0xbd, 0x6a, 0xb9, 0x44, 0x56, 0x91, 0x19,
|
|
||||||
0xaf, 0xb4, 0xc8, 0x7b, 0x89, 0xce, 0x23, 0x17,
|
|
||||||
0x97, 0x20, 0x5c, 0xbb, 0x9c, 0xd7, 0xcc, 0xd9},
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* State for an /age-withdraw/$ACH/reveal operation.
|
* State for an /age-withdraw/$ACH/reveal operation.
|
||||||
*/
|
*/
|
||||||
@ -360,17 +344,15 @@ denomination_is_valid (
|
|||||||
connection,
|
connection,
|
||||||
result);
|
result);
|
||||||
|
|
||||||
/* Does the denomination exist? */
|
|
||||||
if (NULL == dks)
|
if (NULL == dks)
|
||||||
{
|
{
|
||||||
|
/* The denomination doesn't exist */
|
||||||
GNUNET_assert (result != NULL);
|
GNUNET_assert (result != NULL);
|
||||||
/* Note: a HTTP-response has been queued and result has been set by
|
/* Note: a HTTP-response has been queued and result has been set by
|
||||||
* TEH_keys_denominations_by_hash2 */
|
* TEH_keys_denominations_by_hash2 */
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is the denomation still and already valid? */
|
|
||||||
|
|
||||||
if (GNUNET_TIME_absolute_is_past (dks->meta.expire_withdraw.abs_time))
|
if (GNUNET_TIME_absolute_is_past (dks->meta.expire_withdraw.abs_time))
|
||||||
{
|
{
|
||||||
/* This denomination is past the expiration time for withdraws */
|
/* This denomination is past the expiration time for withdraws */
|
||||||
@ -582,6 +564,7 @@ verify_commitment_and_max_age (
|
|||||||
for (uint32_t i = 0; i < num_coins; i++)
|
for (uint32_t i = 0; i < num_coins; i++)
|
||||||
{
|
{
|
||||||
/* FIXME:oec: Calculate new coins and blinded hashes */
|
/* FIXME:oec: Calculate new coins and blinded hashes */
|
||||||
|
/*TALER_age_restriction_commit_from_base(); */
|
||||||
}
|
}
|
||||||
|
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
|
@ -234,12 +234,10 @@ TEH_handler_csr_withdraw (struct TEH_RequestContext *rc,
|
|||||||
.cipher = TALER_DENOMINATION_CS
|
.cipher = TALER_DENOMINATION_CS
|
||||||
};
|
};
|
||||||
struct GNUNET_JSON_Specification spec[] = {
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
GNUNET_JSON_spec_fixed ("nonce",
|
GNUNET_JSON_spec_fixed_auto ("nonce",
|
||||||
&nonce,
|
&nonce),
|
||||||
sizeof (struct TALER_CsNonce)),
|
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
|
||||||
GNUNET_JSON_spec_fixed ("denom_pub_hash",
|
&denom_pub_hash),
|
||||||
&denom_pub_hash,
|
|
||||||
sizeof (struct TALER_DenominationHashP)),
|
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
struct TEH_DenominationKey *dk;
|
struct TEH_DenominationKey *dk;
|
||||||
@ -333,17 +331,11 @@ TEH_handler_csr_withdraw (struct TEH_RequestContext *rc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
return TALER_MHD_REPLY_JSON_PACK (
|
||||||
json_t *csr_obj;
|
rc->connection,
|
||||||
|
MHD_HTTP_OK,
|
||||||
csr_obj = GNUNET_JSON_PACK (
|
TALER_JSON_pack_exchange_withdraw_values ("ewv",
|
||||||
TALER_JSON_pack_exchange_withdraw_values ("ewv",
|
&ewv));
|
||||||
&ewv));
|
|
||||||
GNUNET_assert (NULL != csr_obj);
|
|
||||||
return TALER_MHD_reply_json_steal (rc->connection,
|
|
||||||
csr_obj,
|
|
||||||
MHD_HTTP_OK);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -738,7 +738,7 @@ free_denom_cb (void *cls,
|
|||||||
* @param value the `struct HelperSignkey` to release
|
* @param value the `struct HelperSignkey` to release
|
||||||
* @return #GNUNET_OK (continue to iterate)
|
* @return #GNUNET_OK (continue to iterate)
|
||||||
*/
|
*/
|
||||||
static int
|
static enum GNUNET_GenericReturnValue
|
||||||
free_esign_cb (void *cls,
|
free_esign_cb (void *cls,
|
||||||
const struct GNUNET_PeerIdentity *pid,
|
const struct GNUNET_PeerIdentity *pid,
|
||||||
void *value)
|
void *value)
|
||||||
@ -3616,6 +3616,7 @@ TEH_keys_management_get_keys_handler (const struct TEH_RequestHandler *rh,
|
|||||||
if ( (GNUNET_is_zero (&denom_rsa_sm_pub)) &&
|
if ( (GNUNET_is_zero (&denom_rsa_sm_pub)) &&
|
||||||
(GNUNET_is_zero (&denom_cs_sm_pub)) )
|
(GNUNET_is_zero (&denom_cs_sm_pub)) )
|
||||||
{
|
{
|
||||||
|
/* Either IPC failed, or neither helper had any denominations configured. */
|
||||||
return TALER_MHD_reply_with_error (connection,
|
return TALER_MHD_reply_with_error (connection,
|
||||||
MHD_HTTP_BAD_GATEWAY,
|
MHD_HTTP_BAD_GATEWAY,
|
||||||
TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE,
|
TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE,
|
||||||
@ -3628,7 +3629,6 @@ TEH_keys_management_get_keys_handler (const struct TEH_RequestHandler *rh,
|
|||||||
TALER_EC_EXCHANGE_SIGNKEY_HELPER_UNAVAILABLE,
|
TALER_EC_EXCHANGE_SIGNKEY_HELPER_UNAVAILABLE,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
// then a secmod helper is not yet running and we should return an MHD_HTTP_BAD_GATEWAY!
|
|
||||||
GNUNET_assert (NULL != fbc.denoms);
|
GNUNET_assert (NULL != fbc.denoms);
|
||||||
GNUNET_assert (NULL != fbc.signkeys);
|
GNUNET_assert (NULL != fbc.signkeys);
|
||||||
GNUNET_CONTAINER_multihashmap_iterate (ksh->helpers->denom_keys,
|
GNUNET_CONTAINER_multihashmap_iterate (ksh->helpers->denom_keys,
|
||||||
|
@ -757,7 +757,7 @@ continue_with_shard (void *cls)
|
|||||||
shard_end - latest_row_off);
|
shard_end - latest_row_off);
|
||||||
GNUNET_assert (NULL == hh);
|
GNUNET_assert (NULL == hh);
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
"Requesting credit history staring from %llu\n",
|
"Requesting credit history starting from %llu\n",
|
||||||
(unsigned long long) latest_row_off);
|
(unsigned long long) latest_row_off);
|
||||||
hh_start_time = GNUNET_TIME_absolute_get ();
|
hh_start_time = GNUNET_TIME_absolute_get ();
|
||||||
hh_returned_data = false;
|
hh_returned_data = false;
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
* @brief taler-specific crypto functions
|
* @brief taler-specific crypto functions
|
||||||
* @author Sree Harsha Totakura <sreeharsha@totakura.in>
|
* @author Sree Harsha Totakura <sreeharsha@totakura.in>
|
||||||
* @author Christian Grothoff <christian@grothoff.org>
|
* @author Christian Grothoff <christian@grothoff.org>
|
||||||
|
* @author Özgür Kesim <oec-taler@kesim.org>
|
||||||
*/
|
*/
|
||||||
#if ! defined (__TALER_UTIL_LIB_H_INSIDE__)
|
#if ! defined (__TALER_UTIL_LIB_H_INSIDE__)
|
||||||
#error "Only <taler_util.h> can be included directly."
|
#error "Only <taler_util.h> can be included directly."
|
||||||
@ -5926,4 +5927,42 @@ void
|
|||||||
TALER_age_commitment_proof_free (
|
TALER_age_commitment_proof_free (
|
||||||
struct TALER_AgeCommitmentProof *p);
|
struct TALER_AgeCommitmentProof *p);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief For age-withdraw, clients have to prove that the public keys for all
|
||||||
|
* age groups larger than the allowed maximum age group are derived by scalar
|
||||||
|
* multiplication from this Edx25519 public key (in Crockford Base32 encoding):
|
||||||
|
*
|
||||||
|
* DZJRF6HXN520505XDAWM8NMH36QV9J3VH77265WQ09EBQ76QSKCG
|
||||||
|
*
|
||||||
|
* Its private key was chosen randomly and then deleted.
|
||||||
|
*/
|
||||||
|
extern struct
|
||||||
|
#ifndef AGE_RESTRICTION_WITH_ECDSA
|
||||||
|
GNUNET_CRYPTO_Edx25519PublicKey
|
||||||
|
#else
|
||||||
|
GNUNET_CRYPTO_EcdsaPublicKey
|
||||||
|
#endif
|
||||||
|
TALER_age_commitment_base_public_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Similiar to TALER_age_restriction_commit, but takes the coin's
|
||||||
|
* private key as seed input and calculates the public keys in the slots larger
|
||||||
|
* than the given age as derived from TALER_age_commitment_base_public_key.
|
||||||
|
*
|
||||||
|
* See https://docs.taler.net/core/api-exchange.html#withdraw-with-age-restriction
|
||||||
|
*
|
||||||
|
* @param mask The age mask, defining the age groups
|
||||||
|
* @param max_age The maximum age for this coin.
|
||||||
|
* @param coin_priv The private key of the coin from which we derive the age restriction
|
||||||
|
* @param[out] comm_proof The commitment and proof for age restriction for age @a max_age
|
||||||
|
*/
|
||||||
|
enum GNUNET_GenericReturnValue
|
||||||
|
TALER_age_restriction_commit_from_base (
|
||||||
|
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
|
||||||
|
const struct TALER_AgeMask *mask,
|
||||||
|
uint8_t max_age,
|
||||||
|
struct TALER_AgeCommitmentProof *comm_proof);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -168,9 +168,10 @@ handle_reserves_get_finished (void *cls,
|
|||||||
rs.hr.ec = TALER_JSON_get_error_code (j);
|
rs.hr.ec = TALER_JSON_get_error_code (j);
|
||||||
rs.hr.hint = TALER_JSON_get_error_hint (j);
|
rs.hr.hint = TALER_JSON_get_error_hint (j);
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
"Unexpected response code %u/%d for reserves get\n",
|
"Unexpected response code %u/%d for GET %s\n",
|
||||||
(unsigned int) response_code,
|
(unsigned int) response_code,
|
||||||
(int) rs.hr.ec);
|
(int) rs.hr.ec,
|
||||||
|
rgh->url);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (NULL != rgh->cb)
|
if (NULL != rgh->cb)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
Copyright (C) 2022 Taler Systems SA
|
Copyright (C) 2022-2023 Taler Systems SA
|
||||||
|
|
||||||
TALER is free software; you can redistribute it and/or modify it under the
|
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
|
terms of the GNU General Public License as published by the Free Software
|
||||||
@ -24,6 +24,19 @@
|
|||||||
#include <gnunet/gnunet_json_lib.h>
|
#include <gnunet/gnunet_json_lib.h>
|
||||||
#include <gcrypt.h>
|
#include <gcrypt.h>
|
||||||
|
|
||||||
|
struct
|
||||||
|
#ifndef AGE_RESTRICTION_WITH_ECDSA
|
||||||
|
GNUNET_CRYPTO_Edx25519PublicKey
|
||||||
|
#else
|
||||||
|
GNUNET_CRYPTO_EcdsaPublicKey
|
||||||
|
#endif
|
||||||
|
TALER_age_commitment_base_public_key = {
|
||||||
|
.q_y = { 0x6f, 0xe5, 0x87, 0x9a, 0x3d, 0xa9, 0x44, 0x20,
|
||||||
|
0x80, 0xbd, 0x6a, 0xb9, 0x44, 0x56, 0x91, 0x19,
|
||||||
|
0xaf, 0xb4, 0xc8, 0x7b, 0x89, 0xce, 0x23, 0x17,
|
||||||
|
0x97, 0x20, 0x5c, 0xbb, 0x9c, 0xd7, 0xcc, 0xd9},
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
TALER_age_commitment_hash (
|
TALER_age_commitment_hash (
|
||||||
const struct TALER_AgeCommitment *commitment,
|
const struct TALER_AgeCommitment *commitment,
|
||||||
@ -82,36 +95,78 @@ get_age_group (
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef AGE_RESTRICTION_WITH_ECDSA
|
||||||
|
/* @brief Helper function to generate a ECDSA private key
|
||||||
|
*
|
||||||
|
* @param seed Input seed
|
||||||
|
* @param size Size of the seed in bytes
|
||||||
|
* @param[out] pkey ECDSA private key
|
||||||
|
* @return GNUNET_OK on success
|
||||||
|
*/
|
||||||
|
static enum GNUNET_GenericReturnValue
|
||||||
|
ecdsa_create_from_seed (
|
||||||
|
const void *seed,
|
||||||
|
size_t seed_size,
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPrivateKey *key)
|
||||||
|
{
|
||||||
|
enum GNUNET_GenericReturnValue ret;
|
||||||
|
ret = GNUNET_CRYPTO_kdf (key,
|
||||||
|
sizeof (*key),
|
||||||
|
&seed,
|
||||||
|
seed_size,
|
||||||
|
"age commitment",
|
||||||
|
sizeof ("age commitment") - 1,
|
||||||
|
NULL, 0);
|
||||||
|
if (GNUNET_OK != ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* See GNUNET_CRYPTO_ecdsa_key_create */
|
||||||
|
key->d[0] &= 248;
|
||||||
|
key->d[31] &= 127;
|
||||||
|
key->d[31] |= 64;
|
||||||
|
|
||||||
|
return GNUNET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
enum GNUNET_GenericReturnValue
|
enum GNUNET_GenericReturnValue
|
||||||
TALER_age_restriction_commit (
|
TALER_age_restriction_commit (
|
||||||
const struct TALER_AgeMask *mask,
|
const struct TALER_AgeMask *mask,
|
||||||
const uint8_t age,
|
const uint8_t age,
|
||||||
const struct GNUNET_HashCode *seed,
|
const struct GNUNET_HashCode *seed,
|
||||||
struct TALER_AgeCommitmentProof *new)
|
struct TALER_AgeCommitmentProof *ncp)
|
||||||
{
|
{
|
||||||
struct GNUNET_HashCode seed_i;
|
struct GNUNET_HashCode seed_i;
|
||||||
uint8_t num_pub = __builtin_popcount (mask->bits) - 1;
|
uint8_t num_pub;
|
||||||
uint8_t num_priv = get_age_group (mask, age);
|
uint8_t num_priv;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
|
GNUNET_assert (NULL != mask);
|
||||||
GNUNET_assert (NULL != seed);
|
GNUNET_assert (NULL != seed);
|
||||||
GNUNET_assert (NULL != new);
|
GNUNET_assert (NULL != ncp);
|
||||||
GNUNET_assert (mask->bits & 1); /* fist bit must have been set */
|
GNUNET_assert (mask->bits & 1); /* fist bit must have been set */
|
||||||
|
|
||||||
|
num_pub = __builtin_popcount (mask->bits) - 1;
|
||||||
|
num_priv = get_age_group (mask, age);
|
||||||
|
|
||||||
GNUNET_assert (31 > num_priv);
|
GNUNET_assert (31 > num_priv);
|
||||||
GNUNET_assert (num_priv <= num_pub);
|
GNUNET_assert (num_priv <= num_pub);
|
||||||
|
|
||||||
seed_i = *seed;
|
seed_i = *seed;
|
||||||
new->commitment.mask.bits = mask->bits;
|
ncp->commitment.mask.bits = mask->bits;
|
||||||
new->commitment.num = num_pub;
|
ncp->commitment.num = num_pub;
|
||||||
new->proof.num = num_priv;
|
ncp->proof.num = num_priv;
|
||||||
new->proof.keys = NULL;
|
ncp->proof.keys = NULL;
|
||||||
|
|
||||||
new->commitment.keys = GNUNET_new_array (
|
ncp->commitment.keys = GNUNET_new_array (
|
||||||
num_pub,
|
num_pub,
|
||||||
struct TALER_AgeCommitmentPublicKeyP);
|
struct TALER_AgeCommitmentPublicKeyP);
|
||||||
|
|
||||||
if (0 < num_priv)
|
if (0 < num_priv)
|
||||||
new->proof.keys = GNUNET_new_array (
|
ncp->proof.keys = GNUNET_new_array (
|
||||||
num_priv,
|
num_priv,
|
||||||
struct TALER_AgeCommitmentPrivateKeyP);
|
struct TALER_AgeCommitmentPrivateKeyP);
|
||||||
|
|
||||||
@ -126,47 +181,33 @@ TALER_age_restriction_commit (
|
|||||||
|
|
||||||
/* Only save the private keys for age groups less than num_priv */
|
/* Only save the private keys for age groups less than num_priv */
|
||||||
if (i < num_priv)
|
if (i < num_priv)
|
||||||
pkey = &new->proof.keys[i];
|
pkey = &ncp->proof.keys[i];
|
||||||
|
|
||||||
#ifndef AGE_RESTRICTION_WITH_ECDSA
|
#ifndef AGE_RESTRICTION_WITH_ECDSA
|
||||||
GNUNET_CRYPTO_edx25519_key_create_from_seed (&seed_i,
|
GNUNET_CRYPTO_edx25519_key_create_from_seed (&seed_i,
|
||||||
sizeof(seed_i),
|
sizeof(seed_i),
|
||||||
&pkey->priv);
|
&pkey->priv);
|
||||||
GNUNET_CRYPTO_edx25519_key_get_public (&pkey->priv,
|
GNUNET_CRYPTO_edx25519_key_get_public (&pkey->priv,
|
||||||
&new->commitment.keys[i].pub);
|
&ncp->commitment.keys[i].pub);
|
||||||
|
#else
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
ecdsa_create_from_seed (&seed_i,
|
||||||
|
sizeof(seed_i),
|
||||||
|
&pkey->priv))
|
||||||
|
{
|
||||||
|
GNUNET_free (ncp->commitment.keys);
|
||||||
|
GNUNET_free (ncp->proof.keys);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
GNUNET_CRYPTO_ecdsa_key_get_public (&pkey->priv,
|
||||||
|
&ncp->commitment.keys[i].pub);
|
||||||
|
#endif
|
||||||
|
|
||||||
seed_i.bits[0] += 1;
|
seed_i.bits[0] += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GNUNET_OK;
|
return GNUNET_OK;
|
||||||
#else
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
GNUNET_CRYPTO_kdf (pkey,
|
|
||||||
sizeof (*pkey),
|
|
||||||
&salti,
|
|
||||||
sizeof (salti),
|
|
||||||
"age commitment",
|
|
||||||
strlen ("age commitment"),
|
|
||||||
NULL, 0))
|
|
||||||
goto FAIL;
|
|
||||||
|
|
||||||
/* See GNUNET_CRYPTO_ecdsa_key_create */
|
|
||||||
pkey->priv.d[0] &= 248;
|
|
||||||
pkey->priv.d[31] &= 127;
|
|
||||||
pkey->priv.d[31] |= 64;
|
|
||||||
|
|
||||||
GNUNET_CRYPTO_ecdsa_key_get_public (&pkey->priv,
|
|
||||||
&new->commitment.keys[i].pub);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return GNUNET_OK;
|
|
||||||
|
|
||||||
FAIL:
|
|
||||||
GNUNET_free (new->commitment.keys);
|
|
||||||
if (NULL != new->proof.keys)
|
|
||||||
GNUNET_free (new->proof.keys);
|
|
||||||
return GNUNET_SYSERR;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -216,33 +257,30 @@ TALER_age_commitment_derive (
|
|||||||
&newacp->proof.keys[i].priv);
|
&newacp->proof.keys[i].priv);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
char label[sizeof(uint64_t) + 1] = {0};
|
|
||||||
|
|
||||||
/* Because GNUNET_CRYPTO_ecdsa_public_key_derive expects char * (and calls
|
|
||||||
* strlen on it), we must avoid 0's in the label. */
|
|
||||||
uint64_t nz_salt = salt | 0x8040201008040201;
|
|
||||||
memcpy (label, &nz_salt, sizeof(nz_salt));
|
|
||||||
|
|
||||||
/* 1. Derive the public keys */
|
|
||||||
for (size_t i = 0; i < orig->commitment.num; i++)
|
|
||||||
{
|
{
|
||||||
GNUNET_CRYPTO_ecdsa_public_key_derive (
|
const char *label = GNUNET_h2s (salt);
|
||||||
&orig->commitment.keys[i].pub,
|
|
||||||
label,
|
|
||||||
"age commitment derive",
|
|
||||||
&newacp->commitment.keys[i].pub);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 2. Derive the private keys */
|
/* 1. Derive the public keys */
|
||||||
for (size_t i = 0; i < orig->proof.num; i++)
|
for (size_t i = 0; i < orig->commitment.num; i++)
|
||||||
{
|
{
|
||||||
struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
|
GNUNET_CRYPTO_ecdsa_public_key_derive (
|
||||||
priv = GNUNET_CRYPTO_ecdsa_private_key_derive (
|
&orig->commitment.keys[i].pub,
|
||||||
&orig->proof.keys[i].priv,
|
label,
|
||||||
label,
|
"age commitment derive",
|
||||||
"age commitment derive");
|
&newacp->commitment.keys[i].pub);
|
||||||
newacp->proof.keys[i].priv = *priv;
|
}
|
||||||
GNUNET_free (priv);
|
|
||||||
|
/* 2. Derive the private keys */
|
||||||
|
for (size_t i = 0; i < orig->proof.num; i++)
|
||||||
|
{
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
|
||||||
|
priv = GNUNET_CRYPTO_ecdsa_private_key_derive (
|
||||||
|
&orig->proof.keys[i].priv,
|
||||||
|
label,
|
||||||
|
"age commitment derive");
|
||||||
|
newacp->proof.keys[i].priv = *priv;
|
||||||
|
GNUNET_free (priv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -546,4 +584,106 @@ TALER_age_mask_to_string (
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum GNUNET_GenericReturnValue
|
||||||
|
TALER_age_restriction_commit_from_base (
|
||||||
|
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
|
||||||
|
const struct TALER_AgeMask *mask,
|
||||||
|
uint8_t max_age,
|
||||||
|
struct TALER_AgeCommitmentProof *ncp)
|
||||||
|
{
|
||||||
|
struct GNUNET_HashCode seed_i = {0};
|
||||||
|
uint8_t num_pub;
|
||||||
|
uint8_t num_priv;
|
||||||
|
|
||||||
|
GNUNET_assert (NULL != mask);
|
||||||
|
GNUNET_assert (NULL != coin_priv);
|
||||||
|
GNUNET_assert (NULL != ncp);
|
||||||
|
GNUNET_assert (mask->bits & 1); /* fist bit must have been set */
|
||||||
|
|
||||||
|
num_pub = __builtin_popcount (mask->bits) - 1;
|
||||||
|
num_priv = get_age_group (mask, max_age);
|
||||||
|
|
||||||
|
GNUNET_assert (31 > num_priv);
|
||||||
|
GNUNET_assert (num_priv <= num_pub);
|
||||||
|
|
||||||
|
ncp->commitment.mask.bits = mask->bits;
|
||||||
|
ncp->commitment.num = num_pub;
|
||||||
|
ncp->proof.num = num_priv;
|
||||||
|
ncp->proof.keys = NULL;
|
||||||
|
|
||||||
|
ncp->commitment.keys = GNUNET_new_array (
|
||||||
|
num_pub,
|
||||||
|
struct TALER_AgeCommitmentPublicKeyP);
|
||||||
|
|
||||||
|
if (0 < num_priv)
|
||||||
|
ncp->proof.keys = GNUNET_new_array (
|
||||||
|
num_priv,
|
||||||
|
struct TALER_AgeCommitmentPrivateKeyP);
|
||||||
|
|
||||||
|
/* Create as many private keys as allow with max_age and derive the
|
||||||
|
* corresponding public keys. The rest of the needed public keys are created
|
||||||
|
* by scalar mulitplication with the TALER_age_commitment_base_public_key. */
|
||||||
|
for (size_t i = 0; i < num_pub; i++)
|
||||||
|
{
|
||||||
|
enum GNUNET_GenericReturnValue ret;
|
||||||
|
const char *label = i < num_priv ? "age-commitment" : "age-factor";
|
||||||
|
|
||||||
|
ret = GNUNET_CRYPTO_kdf (&seed_i, sizeof(seed_i),
|
||||||
|
coin_priv, sizeof(*coin_priv),
|
||||||
|
label, strlen (label),
|
||||||
|
&i, sizeof(i),
|
||||||
|
NULL, 0);
|
||||||
|
GNUNET_assert (GNUNET_OK == ret);
|
||||||
|
|
||||||
|
/* Only generate and save the private keys and public keys for age groups
|
||||||
|
* less than num_priv */
|
||||||
|
if (i < num_priv)
|
||||||
|
{
|
||||||
|
struct TALER_AgeCommitmentPrivateKeyP *pkey = &ncp->proof.keys[i];
|
||||||
|
|
||||||
|
#ifndef AGE_RESTRICTION_WITH_ECDSA
|
||||||
|
GNUNET_CRYPTO_edx25519_key_create_from_seed (&seed_i,
|
||||||
|
sizeof(seed_i),
|
||||||
|
&pkey->priv);
|
||||||
|
GNUNET_CRYPTO_edx25519_key_get_public (&pkey->priv,
|
||||||
|
&ncp->commitment.keys[i].pub);
|
||||||
|
#else
|
||||||
|
if (GNUNET_OK != ecdsa_create_from_seed (&seed_i,
|
||||||
|
sizeof(seed_i),
|
||||||
|
&pkey->priv))
|
||||||
|
{
|
||||||
|
GNUNET_free (ncp->commitment.keys);
|
||||||
|
GNUNET_free (ncp->proof.keys);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
GNUNET_CRYPTO_ecdsa_key_get_public (&pkey->priv,
|
||||||
|
&ncp->commitment.keys[i].pub);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* For all indices larger than num_priv, derive a public key from
|
||||||
|
* TALER_age_commitment_base_public_key by scalar multiplication */
|
||||||
|
#ifndef AGE_RESTRICTION_WITH_ECDSA
|
||||||
|
GNUNET_CRYPTO_edx25519_public_key_derive (
|
||||||
|
&TALER_age_commitment_base_public_key,
|
||||||
|
&seed_i,
|
||||||
|
sizeof(seed_i),
|
||||||
|
&ncp->commitment.keys[i].pub);
|
||||||
|
#else
|
||||||
|
|
||||||
|
GNUNET_CRYPTO_ecdsa_public_key_derive (
|
||||||
|
&TALER_age_commitment_base_public_key,
|
||||||
|
GNUNET_h2s (&seed_i),
|
||||||
|
"age withdraw",
|
||||||
|
&ncp->commitment.keys[i].pub);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GNUNET_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* end util/age_restriction.c */
|
/* end util/age_restriction.c */
|
||||||
|
Loading…
Reference in New Issue
Block a user