write KYC attribute encryption logic
This commit is contained in:
parent
509141b600
commit
c5ad98da98
@ -603,6 +603,19 @@ struct TALER_RefreshCommitmentP
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Symmetric key we use to encrypt KYC attributes
|
||||||
|
* in our database.
|
||||||
|
*/
|
||||||
|
struct TALER_AttributeEncryptionKeyP
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The key is a hash code.
|
||||||
|
*/
|
||||||
|
struct GNUNET_HashCode hash;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Token used for access control to the merchant's unclaimed
|
* Token used for access control to the merchant's unclaimed
|
||||||
* orders.
|
* orders.
|
||||||
@ -1791,6 +1804,37 @@ TALER_denom_pub_verify (const struct TALER_DenominationPublicKey *denom_pub,
|
|||||||
const struct TALER_CoinPubHashP *c_hash);
|
const struct TALER_CoinPubHashP *c_hash);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypts KYC attributes for storage in the database.
|
||||||
|
*
|
||||||
|
* @param key encryption key to use
|
||||||
|
* @param attr set of attributes to encrypt
|
||||||
|
* @param[out] enc_attr encrypted attribute data
|
||||||
|
* @param[out] enc_attr_size number of bytes in @a enc_attr
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
TALER_CRYPTO_kyc_attributes_encrypt (
|
||||||
|
const struct TALER_AttributeEncryptionKeyP *key,
|
||||||
|
const json_t *attr,
|
||||||
|
void **enc_attr,
|
||||||
|
size_t *enc_attr_size);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypts KYC attributes for storage in the database.
|
||||||
|
*
|
||||||
|
* @param key encryption key to use
|
||||||
|
* @param enc_attr encrypted attribute data
|
||||||
|
* @param enc_attr_size number of bytes in @a enc_attr
|
||||||
|
* @return set of decrypted attributes, NULL on failure
|
||||||
|
*/
|
||||||
|
json_t *
|
||||||
|
TALER_CRYPTO_kyc_attributes_decrypt (
|
||||||
|
const struct TALER_AttributeEncryptionKeyP *key,
|
||||||
|
const void *enc_attr,
|
||||||
|
size_t enc_attr_size);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a coin is valid; that is, whether the denomination key exists,
|
* Check if a coin is valid; that is, whether the denomination key exists,
|
||||||
* is not expired, and the signature is correct.
|
* is not expired, and the signature is correct.
|
||||||
|
@ -109,14 +109,14 @@ derive_key (const void *key_material,
|
|||||||
* @param[out] res_size size of the ciphertext
|
* @param[out] res_size size of the ciphertext
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
contract_encrypt (const struct NonceP *nonce,
|
blob_encrypt (const struct NonceP *nonce,
|
||||||
const void *key,
|
const void *key,
|
||||||
size_t key_len,
|
size_t key_len,
|
||||||
const void *data,
|
const void *data,
|
||||||
size_t data_size,
|
size_t data_size,
|
||||||
const char *salt,
|
const char *salt,
|
||||||
void **res,
|
void **res,
|
||||||
size_t *res_size)
|
size_t *res_size)
|
||||||
{
|
{
|
||||||
size_t ciphertext_size;
|
size_t ciphertext_size;
|
||||||
struct SymKeyP skey;
|
struct SymKeyP skey;
|
||||||
@ -127,10 +127,13 @@ contract_encrypt (const struct NonceP *nonce,
|
|||||||
salt,
|
salt,
|
||||||
&skey);
|
&skey);
|
||||||
ciphertext_size = crypto_secretbox_NONCEBYTES
|
ciphertext_size = crypto_secretbox_NONCEBYTES
|
||||||
+ crypto_secretbox_MACBYTES + data_size;
|
+ crypto_secretbox_MACBYTES
|
||||||
|
+ data_size;
|
||||||
*res_size = ciphertext_size;
|
*res_size = ciphertext_size;
|
||||||
*res = GNUNET_malloc (ciphertext_size);
|
*res = GNUNET_malloc (ciphertext_size);
|
||||||
memcpy (*res, nonce, crypto_secretbox_NONCEBYTES);
|
memcpy (*res,
|
||||||
|
nonce,
|
||||||
|
crypto_secretbox_NONCEBYTES);
|
||||||
GNUNET_assert (0 ==
|
GNUNET_assert (0 ==
|
||||||
crypto_secretbox_easy (*res + crypto_secretbox_NONCEBYTES,
|
crypto_secretbox_easy (*res + crypto_secretbox_NONCEBYTES,
|
||||||
data,
|
data,
|
||||||
@ -153,13 +156,13 @@ contract_encrypt (const struct NonceP *nonce,
|
|||||||
* @return #GNUNET_OK on success
|
* @return #GNUNET_OK on success
|
||||||
*/
|
*/
|
||||||
static enum GNUNET_GenericReturnValue
|
static enum GNUNET_GenericReturnValue
|
||||||
contract_decrypt (const void *key,
|
blob_decrypt (const void *key,
|
||||||
size_t key_len,
|
size_t key_len,
|
||||||
const void *data,
|
const void *data,
|
||||||
size_t data_size,
|
size_t data_size,
|
||||||
const char *salt,
|
const char *salt,
|
||||||
void **res,
|
void **res,
|
||||||
size_t *res_size)
|
size_t *res_size)
|
||||||
{
|
{
|
||||||
const struct NonceP *nonce;
|
const struct NonceP *nonce;
|
||||||
struct SymKeyP skey;
|
struct SymKeyP skey;
|
||||||
@ -278,14 +281,14 @@ TALER_CRYPTO_contract_encrypt_for_merge (
|
|||||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
|
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
|
||||||
&nonce,
|
&nonce,
|
||||||
sizeof (nonce));
|
sizeof (nonce));
|
||||||
contract_encrypt (&nonce,
|
blob_encrypt (&nonce,
|
||||||
&key,
|
&key,
|
||||||
sizeof (key),
|
sizeof (key),
|
||||||
hdr,
|
hdr,
|
||||||
sizeof (*hdr) + cbuf_size,
|
sizeof (*hdr) + cbuf_size,
|
||||||
MERGE_SALT,
|
MERGE_SALT,
|
||||||
econtract,
|
econtract,
|
||||||
econtract_size);
|
econtract_size);
|
||||||
GNUNET_free (hdr);
|
GNUNET_free (hdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,13 +319,13 @@ TALER_CRYPTO_contract_decrypt_for_merge (
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
contract_decrypt (&key,
|
blob_decrypt (&key,
|
||||||
sizeof (key),
|
sizeof (key),
|
||||||
econtract,
|
econtract,
|
||||||
econtract_size,
|
econtract_size,
|
||||||
MERGE_SALT,
|
MERGE_SALT,
|
||||||
&xhdr,
|
&xhdr,
|
||||||
&hdr_size))
|
&hdr_size))
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -407,6 +410,7 @@ TALER_CRYPTO_contract_encrypt_for_deposit (
|
|||||||
&key));
|
&key));
|
||||||
cstr = json_dumps (contract_terms,
|
cstr = json_dumps (contract_terms,
|
||||||
JSON_COMPACT | JSON_SORT_KEYS);
|
JSON_COMPACT | JSON_SORT_KEYS);
|
||||||
|
GNUNET_assert (NULL != cstr);
|
||||||
clen = strlen (cstr);
|
clen = strlen (cstr);
|
||||||
cbuf_size = compressBound (clen);
|
cbuf_size = compressBound (clen);
|
||||||
xbuf = GNUNET_malloc (cbuf_size);
|
xbuf = GNUNET_malloc (cbuf_size);
|
||||||
@ -426,14 +430,14 @@ TALER_CRYPTO_contract_encrypt_for_deposit (
|
|||||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
|
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
|
||||||
&nonce,
|
&nonce,
|
||||||
sizeof (nonce));
|
sizeof (nonce));
|
||||||
contract_encrypt (&nonce,
|
blob_encrypt (&nonce,
|
||||||
&key,
|
&key,
|
||||||
sizeof (key),
|
sizeof (key),
|
||||||
hdr,
|
hdr,
|
||||||
sizeof (*hdr) + cbuf_size,
|
sizeof (*hdr) + cbuf_size,
|
||||||
DEPOSIT_SALT,
|
DEPOSIT_SALT,
|
||||||
&xecontract,
|
&xecontract,
|
||||||
&xecontract_size);
|
&xecontract_size);
|
||||||
GNUNET_free (hdr);
|
GNUNET_free (hdr);
|
||||||
/* prepend purse_pub */
|
/* prepend purse_pub */
|
||||||
*econtract = GNUNET_malloc (xecontract_size + sizeof (*purse_pub));
|
*econtract = GNUNET_malloc (xecontract_size + sizeof (*purse_pub));
|
||||||
@ -481,13 +485,13 @@ TALER_CRYPTO_contract_decrypt_for_deposit (
|
|||||||
econtract += sizeof (*purse_pub);
|
econtract += sizeof (*purse_pub);
|
||||||
econtract_size -= sizeof (*purse_pub);
|
econtract_size -= sizeof (*purse_pub);
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
contract_decrypt (&key,
|
blob_decrypt (&key,
|
||||||
sizeof (key),
|
sizeof (key),
|
||||||
econtract,
|
econtract,
|
||||||
econtract_size,
|
econtract_size,
|
||||||
DEPOSIT_SALT,
|
DEPOSIT_SALT,
|
||||||
&xhdr,
|
&xhdr,
|
||||||
&hdr_size))
|
&hdr_size))
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -538,3 +542,120 @@ TALER_CRYPTO_contract_decrypt_for_deposit (
|
|||||||
GNUNET_free (cstr);
|
GNUNET_free (cstr);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Salt we use when encrypting KYC attributes.
|
||||||
|
*/
|
||||||
|
#define ATTRIBUTE_SALT "kyc-attributes"
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TALER_CRYPTO_kyc_attributes_encrypt (
|
||||||
|
const struct TALER_AttributeEncryptionKeyP *key,
|
||||||
|
const json_t *attr,
|
||||||
|
void **enc_attr,
|
||||||
|
size_t *enc_attr_size)
|
||||||
|
{
|
||||||
|
uLongf cbuf_size;
|
||||||
|
char *cstr;
|
||||||
|
uLongf clen;
|
||||||
|
void *xbuf;
|
||||||
|
int ret;
|
||||||
|
uint32_t belen;
|
||||||
|
struct NonceP nonce;
|
||||||
|
|
||||||
|
cstr = json_dumps (attr,
|
||||||
|
JSON_COMPACT | JSON_SORT_KEYS);
|
||||||
|
GNUNET_assert (NULL != cstr);
|
||||||
|
clen = strlen (cstr);
|
||||||
|
GNUNET_assert (clen <= UINT32_MAX);
|
||||||
|
cbuf_size = compressBound (clen);
|
||||||
|
xbuf = GNUNET_malloc (cbuf_size + sizeof (uint32_t));
|
||||||
|
belen = htonl ((uint32_t) clen);
|
||||||
|
memcpy (xbuf,
|
||||||
|
&belen,
|
||||||
|
sizeof (belen));
|
||||||
|
ret = compress (xbuf + 4,
|
||||||
|
&cbuf_size,
|
||||||
|
(const Bytef *) cstr,
|
||||||
|
clen);
|
||||||
|
GNUNET_assert (Z_OK == ret);
|
||||||
|
free (cstr);
|
||||||
|
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
|
||||||
|
&nonce,
|
||||||
|
sizeof (nonce));
|
||||||
|
blob_encrypt (&nonce,
|
||||||
|
key,
|
||||||
|
sizeof (*key),
|
||||||
|
xbuf,
|
||||||
|
cbuf_size + sizeof (uint32_t),
|
||||||
|
ATTRIBUTE_SALT,
|
||||||
|
enc_attr,
|
||||||
|
enc_attr_size);
|
||||||
|
GNUNET_free (xbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
json_t *
|
||||||
|
TALER_CRYPTO_kyc_attributes_decrypt (
|
||||||
|
const struct TALER_AttributeEncryptionKeyP *key,
|
||||||
|
const void *enc_attr,
|
||||||
|
size_t enc_attr_size)
|
||||||
|
{
|
||||||
|
void *xhdr;
|
||||||
|
size_t hdr_size;
|
||||||
|
char *cstr;
|
||||||
|
uLongf clen;
|
||||||
|
json_error_t json_error;
|
||||||
|
json_t *ret;
|
||||||
|
uint32_t belen;
|
||||||
|
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
blob_decrypt (key,
|
||||||
|
sizeof (*key),
|
||||||
|
enc_attr,
|
||||||
|
enc_attr_size,
|
||||||
|
ATTRIBUTE_SALT,
|
||||||
|
&xhdr,
|
||||||
|
&hdr_size))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memcpy (&belen,
|
||||||
|
xhdr,
|
||||||
|
sizeof (belen));
|
||||||
|
clen = ntohl (belen);
|
||||||
|
if (clen >= GNUNET_MAX_MALLOC_CHECKED)
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
GNUNET_free (xhdr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
cstr = GNUNET_malloc (clen + 1);
|
||||||
|
if (Z_OK !=
|
||||||
|
uncompress ((Bytef *) cstr,
|
||||||
|
&clen,
|
||||||
|
(const Bytef *) (xhdr + sizeof (uint32_t)),
|
||||||
|
hdr_size - sizeof (uint32_t)))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
GNUNET_free (cstr);
|
||||||
|
GNUNET_free (xhdr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
GNUNET_free (xhdr);
|
||||||
|
ret = json_loadb ((char *) cstr,
|
||||||
|
clen,
|
||||||
|
JSON_DECODE_ANY,
|
||||||
|
&json_error);
|
||||||
|
if (NULL == ret)
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
GNUNET_free (cstr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
GNUNET_free (cstr);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@ -150,12 +150,12 @@ test_planchets_rsa (uint8_t age)
|
|||||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
|
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
|
||||||
&ps,
|
&ps,
|
||||||
sizeof (ps));
|
sizeof (ps));
|
||||||
|
GNUNET_log_skip (1, GNUNET_YES);
|
||||||
GNUNET_assert (GNUNET_SYSERR ==
|
GNUNET_assert (GNUNET_SYSERR ==
|
||||||
TALER_denom_priv_create (&dk_priv,
|
TALER_denom_priv_create (&dk_priv,
|
||||||
&dk_pub,
|
&dk_pub,
|
||||||
TALER_DENOMINATION_INVALID));
|
TALER_DENOMINATION_INVALID));
|
||||||
|
GNUNET_log_skip (1, GNUNET_YES);
|
||||||
GNUNET_assert (GNUNET_SYSERR ==
|
GNUNET_assert (GNUNET_SYSERR ==
|
||||||
TALER_denom_priv_create (&dk_priv,
|
TALER_denom_priv_create (&dk_priv,
|
||||||
&dk_pub,
|
&dk_pub,
|
||||||
@ -481,12 +481,51 @@ test_contracts (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
test_attributes (void)
|
||||||
|
{
|
||||||
|
struct TALER_AttributeEncryptionKeyP key;
|
||||||
|
void *eattr;
|
||||||
|
size_t eattr_size;
|
||||||
|
json_t *c;
|
||||||
|
|
||||||
|
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
|
||||||
|
&key,
|
||||||
|
sizeof (key));
|
||||||
|
c = json_pack ("{s:s}", "test", "value");
|
||||||
|
GNUNET_assert (NULL != c);
|
||||||
|
TALER_CRYPTO_kyc_attributes_encrypt (&key,
|
||||||
|
c,
|
||||||
|
&eattr,
|
||||||
|
&eattr_size);
|
||||||
|
json_decref (c);
|
||||||
|
c = TALER_CRYPTO_kyc_attributes_decrypt (&key,
|
||||||
|
eattr,
|
||||||
|
eattr_size);
|
||||||
|
GNUNET_free (eattr);
|
||||||
|
if (NULL == c)
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
GNUNET_assert (0 ==
|
||||||
|
strcmp ("value",
|
||||||
|
json_string_value (json_object_get (c,
|
||||||
|
"test"))));
|
||||||
|
json_decref (c);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc,
|
main (int argc,
|
||||||
const char *const argv[])
|
const char *const argv[])
|
||||||
{
|
{
|
||||||
(void) argc;
|
(void) argc;
|
||||||
(void) argv;
|
(void) argv;
|
||||||
|
GNUNET_log_setup ("test-crypto",
|
||||||
|
"WARNING",
|
||||||
|
NULL);
|
||||||
if (0 != test_high_level ())
|
if (0 != test_high_level ())
|
||||||
return 1;
|
return 1;
|
||||||
if (0 != test_planchets (0))
|
if (0 != test_planchets (0))
|
||||||
@ -499,6 +538,8 @@ main (int argc,
|
|||||||
return 5;
|
return 5;
|
||||||
if (0 != test_contracts ())
|
if (0 != test_contracts ())
|
||||||
return 6;
|
return 6;
|
||||||
|
if (0 != test_attributes ())
|
||||||
|
return 7;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user