2016-07-01 15:51:07 +00:00
|
|
|
/**********************************************************************
|
|
|
|
* Copyright (c) 2016 Andrew Poelstra *
|
|
|
|
* Distributed under the MIT software license, see the accompanying *
|
|
|
|
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
#ifndef _SECP256K1_SURJECTION_IMPL_H_
|
|
|
|
#define _SECP256K1_SURJECTION_IMPL_H_
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "eckey.h"
|
|
|
|
#include "group.h"
|
|
|
|
#include "scalar.h"
|
|
|
|
#include "hash.h"
|
|
|
|
|
2019-04-30 22:46:05 +00:00
|
|
|
SECP256K1_INLINE static void secp256k1_surjection_genmessage(unsigned char *msg32, const secp256k1_generator *ephemeral_input_tags, size_t n_input_tags, const secp256k1_generator *ephemeral_output_tag) {
|
2016-07-01 15:51:07 +00:00
|
|
|
/* compute message */
|
|
|
|
size_t i;
|
|
|
|
unsigned char pk_ser[33];
|
|
|
|
size_t pk_len = sizeof(pk_ser);
|
|
|
|
secp256k1_sha256 sha256_en;
|
|
|
|
|
|
|
|
secp256k1_sha256_initialize(&sha256_en);
|
|
|
|
for (i = 0; i < n_input_tags; i++) {
|
2019-04-30 22:46:05 +00:00
|
|
|
pk_ser[0] = 2 + (ephemeral_input_tags[i].data[63] & 1);
|
|
|
|
memcpy(&pk_ser[1], &ephemeral_input_tags[i].data[0], 32);
|
2016-07-01 15:51:07 +00:00
|
|
|
secp256k1_sha256_write(&sha256_en, pk_ser, pk_len);
|
|
|
|
}
|
2019-04-30 22:46:05 +00:00
|
|
|
pk_ser[0] = 2 + (ephemeral_output_tag->data[63] & 1);
|
|
|
|
memcpy(&pk_ser[1], &ephemeral_output_tag->data[0], 32);
|
2016-07-01 15:51:07 +00:00
|
|
|
secp256k1_sha256_write(&sha256_en, pk_ser, pk_len);
|
|
|
|
secp256k1_sha256_finalize(&sha256_en, msg32);
|
|
|
|
}
|
|
|
|
|
|
|
|
SECP256K1_INLINE static int secp256k1_surjection_genrand(secp256k1_scalar *s, size_t ns, const secp256k1_scalar *blinding_key) {
|
|
|
|
size_t i;
|
|
|
|
unsigned char sec_input[36];
|
|
|
|
secp256k1_sha256 sha256_en;
|
|
|
|
|
|
|
|
/* compute s values */
|
|
|
|
secp256k1_scalar_get_b32(&sec_input[4], blinding_key);
|
|
|
|
for (i = 0; i < ns; i++) {
|
|
|
|
int overflow = 0;
|
|
|
|
sec_input[0] = i;
|
|
|
|
sec_input[1] = i >> 8;
|
|
|
|
sec_input[2] = i >> 16;
|
|
|
|
sec_input[3] = i >> 24;
|
|
|
|
|
|
|
|
secp256k1_sha256_initialize(&sha256_en);
|
|
|
|
secp256k1_sha256_write(&sha256_en, sec_input, 36);
|
|
|
|
secp256k1_sha256_finalize(&sha256_en, sec_input);
|
|
|
|
secp256k1_scalar_set_b32(&s[i], sec_input, &overflow);
|
|
|
|
if (overflow == 1) {
|
|
|
|
memset(sec_input, 0, 32);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
memset(sec_input, 0, 32);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-04-30 22:46:05 +00:00
|
|
|
SECP256K1_INLINE static int secp256k1_surjection_compute_public_keys(secp256k1_gej *pubkeys, size_t n_pubkeys, const secp256k1_generator *input_tags, size_t n_input_tags, const unsigned char *used_tags, const secp256k1_generator *output_tag, size_t input_index, size_t *ring_input_index) {
|
2016-07-01 15:51:07 +00:00
|
|
|
size_t i;
|
|
|
|
size_t j = 0;
|
|
|
|
for (i = 0; i < n_input_tags; i++) {
|
|
|
|
if (used_tags[i / 8] & (1 << (i % 8))) {
|
|
|
|
secp256k1_ge tmpge;
|
2019-04-30 22:46:05 +00:00
|
|
|
secp256k1_generator_load(&tmpge, &input_tags[i]);
|
|
|
|
secp256k1_ge_neg(&tmpge, &tmpge);
|
2016-07-01 15:51:07 +00:00
|
|
|
secp256k1_gej_set_ge(&pubkeys[j], &tmpge);
|
2019-04-30 22:46:05 +00:00
|
|
|
|
|
|
|
secp256k1_generator_load(&tmpge, output_tag);
|
|
|
|
secp256k1_gej_add_ge_var(&pubkeys[j], &pubkeys[j], &tmpge, NULL);
|
2016-07-01 15:51:07 +00:00
|
|
|
if (ring_input_index != NULL && input_index == i) {
|
|
|
|
*ring_input_index = j;
|
|
|
|
}
|
|
|
|
j++;
|
2019-04-30 23:04:08 +00:00
|
|
|
if (j > n_pubkeys || j > SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS) {
|
2016-07-01 15:51:07 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|