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
|
||||
* orders.
|
||||
@ -1791,6 +1804,37 @@ TALER_denom_pub_verify (const struct TALER_DenominationPublicKey *denom_pub,
|
||||
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,
|
||||
* 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
|
||||
*/
|
||||
static void
|
||||
contract_encrypt (const struct NonceP *nonce,
|
||||
const void *key,
|
||||
size_t key_len,
|
||||
const void *data,
|
||||
size_t data_size,
|
||||
const char *salt,
|
||||
void **res,
|
||||
size_t *res_size)
|
||||
blob_encrypt (const struct NonceP *nonce,
|
||||
const void *key,
|
||||
size_t key_len,
|
||||
const void *data,
|
||||
size_t data_size,
|
||||
const char *salt,
|
||||
void **res,
|
||||
size_t *res_size)
|
||||
{
|
||||
size_t ciphertext_size;
|
||||
struct SymKeyP skey;
|
||||
@ -127,10 +127,13 @@ contract_encrypt (const struct NonceP *nonce,
|
||||
salt,
|
||||
&skey);
|
||||
ciphertext_size = crypto_secretbox_NONCEBYTES
|
||||
+ crypto_secretbox_MACBYTES + data_size;
|
||||
+ crypto_secretbox_MACBYTES
|
||||
+ data_size;
|
||||
*res_size = ciphertext_size;
|
||||
*res = GNUNET_malloc (ciphertext_size);
|
||||
memcpy (*res, nonce, crypto_secretbox_NONCEBYTES);
|
||||
memcpy (*res,
|
||||
nonce,
|
||||
crypto_secretbox_NONCEBYTES);
|
||||
GNUNET_assert (0 ==
|
||||
crypto_secretbox_easy (*res + crypto_secretbox_NONCEBYTES,
|
||||
data,
|
||||
@ -153,13 +156,13 @@ contract_encrypt (const struct NonceP *nonce,
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
contract_decrypt (const void *key,
|
||||
size_t key_len,
|
||||
const void *data,
|
||||
size_t data_size,
|
||||
const char *salt,
|
||||
void **res,
|
||||
size_t *res_size)
|
||||
blob_decrypt (const void *key,
|
||||
size_t key_len,
|
||||
const void *data,
|
||||
size_t data_size,
|
||||
const char *salt,
|
||||
void **res,
|
||||
size_t *res_size)
|
||||
{
|
||||
const struct NonceP *nonce;
|
||||
struct SymKeyP skey;
|
||||
@ -278,14 +281,14 @@ TALER_CRYPTO_contract_encrypt_for_merge (
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
|
||||
&nonce,
|
||||
sizeof (nonce));
|
||||
contract_encrypt (&nonce,
|
||||
&key,
|
||||
sizeof (key),
|
||||
hdr,
|
||||
sizeof (*hdr) + cbuf_size,
|
||||
MERGE_SALT,
|
||||
econtract,
|
||||
econtract_size);
|
||||
blob_encrypt (&nonce,
|
||||
&key,
|
||||
sizeof (key),
|
||||
hdr,
|
||||
sizeof (*hdr) + cbuf_size,
|
||||
MERGE_SALT,
|
||||
econtract,
|
||||
econtract_size);
|
||||
GNUNET_free (hdr);
|
||||
}
|
||||
|
||||
@ -316,13 +319,13 @@ TALER_CRYPTO_contract_decrypt_for_merge (
|
||||
return NULL;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
contract_decrypt (&key,
|
||||
sizeof (key),
|
||||
econtract,
|
||||
econtract_size,
|
||||
MERGE_SALT,
|
||||
&xhdr,
|
||||
&hdr_size))
|
||||
blob_decrypt (&key,
|
||||
sizeof (key),
|
||||
econtract,
|
||||
econtract_size,
|
||||
MERGE_SALT,
|
||||
&xhdr,
|
||||
&hdr_size))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return NULL;
|
||||
@ -407,6 +410,7 @@ TALER_CRYPTO_contract_encrypt_for_deposit (
|
||||
&key));
|
||||
cstr = json_dumps (contract_terms,
|
||||
JSON_COMPACT | JSON_SORT_KEYS);
|
||||
GNUNET_assert (NULL != cstr);
|
||||
clen = strlen (cstr);
|
||||
cbuf_size = compressBound (clen);
|
||||
xbuf = GNUNET_malloc (cbuf_size);
|
||||
@ -426,14 +430,14 @@ TALER_CRYPTO_contract_encrypt_for_deposit (
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
|
||||
&nonce,
|
||||
sizeof (nonce));
|
||||
contract_encrypt (&nonce,
|
||||
&key,
|
||||
sizeof (key),
|
||||
hdr,
|
||||
sizeof (*hdr) + cbuf_size,
|
||||
DEPOSIT_SALT,
|
||||
&xecontract,
|
||||
&xecontract_size);
|
||||
blob_encrypt (&nonce,
|
||||
&key,
|
||||
sizeof (key),
|
||||
hdr,
|
||||
sizeof (*hdr) + cbuf_size,
|
||||
DEPOSIT_SALT,
|
||||
&xecontract,
|
||||
&xecontract_size);
|
||||
GNUNET_free (hdr);
|
||||
/* prepend 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_size -= sizeof (*purse_pub);
|
||||
if (GNUNET_OK !=
|
||||
contract_decrypt (&key,
|
||||
sizeof (key),
|
||||
econtract,
|
||||
econtract_size,
|
||||
DEPOSIT_SALT,
|
||||
&xhdr,
|
||||
&hdr_size))
|
||||
blob_decrypt (&key,
|
||||
sizeof (key),
|
||||
econtract,
|
||||
econtract_size,
|
||||
DEPOSIT_SALT,
|
||||
&xhdr,
|
||||
&hdr_size))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return NULL;
|
||||
@ -538,3 +542,120 @@ TALER_CRYPTO_contract_decrypt_for_deposit (
|
||||
GNUNET_free (cstr);
|
||||
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,
|
||||
&ps,
|
||||
sizeof (ps));
|
||||
|
||||
GNUNET_log_skip (1, GNUNET_YES);
|
||||
GNUNET_assert (GNUNET_SYSERR ==
|
||||
TALER_denom_priv_create (&dk_priv,
|
||||
&dk_pub,
|
||||
TALER_DENOMINATION_INVALID));
|
||||
|
||||
GNUNET_log_skip (1, GNUNET_YES);
|
||||
GNUNET_assert (GNUNET_SYSERR ==
|
||||
TALER_denom_priv_create (&dk_priv,
|
||||
&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
|
||||
main (int argc,
|
||||
const char *const argv[])
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
GNUNET_log_setup ("test-crypto",
|
||||
"WARNING",
|
||||
NULL);
|
||||
if (0 != test_high_level ())
|
||||
return 1;
|
||||
if (0 != test_planchets (0))
|
||||
@ -499,6 +538,8 @@ main (int argc,
|
||||
return 5;
|
||||
if (0 != test_contracts ())
|
||||
return 6;
|
||||
if (0 != test_attributes ())
|
||||
return 7;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user