gateway2/Tongsuo-8.4.0/crypto/zkp/bulletproofs/bulletproofs_prn.c
2026-07-11 13:40:57 +08:00

506 lines
14 KiB
C

/*
* Copyright 2023 The Tongsuo Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include <crypto/bn.h>
#include <crypto/ec/ec_local.h>
#include <openssl/ec.h>
#include <openssl/asn1.h>
#include <openssl/bio.h>
#include <openssl/bulletproofs.h>
#include "range_proof.h"
#include "r1cs.h"
/* Number of octets per line */
#define ASN1_BUF_PRINT_WIDTH 127
/* Maximum indent */
#define ASN1_PRINT_MAX_INDENT 128
DEFINE_STACK_OF(BIGNUM)
DEFINE_STACK_OF(EC_POINT)
DEFINE_STACK_OF(BP_VARIABLE)
static int bp_bio_printf(BIO *bio, int indent, const char *format, ...)
{
va_list args;
int ret;
if (!BIO_indent(bio, indent, ASN1_PRINT_MAX_INDENT))
return 0;
va_start(args, format);
ret = BIO_vprintf(bio, format, args);
va_end(args);
return ret;
}
static int bp_buf_print(BIO *bp, const unsigned char *buf, size_t buflen,
int indent)
{
size_t i;
for (i = 0; i < buflen; i++) {
if ((i % ASN1_BUF_PRINT_WIDTH) == 0) {
if (i > 0 && BIO_puts(bp, "\n") <= 0)
return 0;
if (!BIO_indent(bp, indent, ASN1_PRINT_MAX_INDENT))
return 0;
}
/*
* Use colon separators for each octet for compatibility as
* this function is used to print out key components.
*/
if (BIO_printf(bp, "%02x%s", buf[i],
(i == buflen - 1) ? "" : ":") <= 0)
return 0;
}
if (BIO_write(bp, "\n", 1) <= 0)
return 0;
return 1;
}
static int bp_point_print(BIO *bp, const EC_GROUP *group, const EC_POINT *point,
const char *name, int indent, BN_CTX *bn_ctx)
{
int ret = 0;
size_t point_len;
unsigned char *p = NULL;
if (bp == NULL || group == NULL || point == NULL || bn_ctx == NULL)
return ret;
point_len = EC_POINT_point2oct(group, EC_GROUP_get0_generator(group),
POINT_CONVERSION_COMPRESSED, NULL, 0, bn_ctx);
p = OPENSSL_zalloc(point_len);
if (p == NULL)
goto end;
if (!BIO_indent(bp, indent, ASN1_PRINT_MAX_INDENT))
goto end;
if (name != NULL)
BIO_printf(bp, "%s", name);
if (EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED,
p, point_len, bn_ctx) == 0)
goto end;
if (!bp_buf_print(bp, p, point_len, 0))
goto end;
ret = 1;
end:
OPENSSL_free(p);
return ret;
}
static int bp_bn_print(BIO *bp, const char *name, const BIGNUM *num,
unsigned char *ign, int indent)
{
int n, rv = 0;
const char *neg;
unsigned char *buf = NULL, *tmp = NULL;
int buflen;
if (num == NULL)
return 1;
neg = BN_is_negative(num) ? "-" : "";
if (!BIO_indent(bp, indent, ASN1_PRINT_MAX_INDENT))
return 0;
if (BN_is_zero(num)) {
if (name != NULL)
BIO_printf(bp, "%s: ", name);
if (BIO_printf(bp, "0\n") <= 0)
return 0;
return 1;
}
if (BN_num_bytes(num) <= BN_BYTES) {
if (name != NULL)
BIO_printf(bp, "%s: ", name);
if (BIO_printf(bp, "%s%lu (%s0x%lx)\n", neg,
(unsigned long)bn_get_words(num)[0], neg,
(unsigned long)bn_get_words(num)[0]) <= 0)
return 0;
return 1;
}
buflen = BN_num_bytes(num) + 1;
buf = tmp = OPENSSL_malloc(buflen);
if (buf == NULL)
goto err;
buf[0] = 0;
if (name != NULL)
BIO_printf(bp, "%s: ", name);
BIO_printf(bp, "%s", neg);
n = BN_bn2bin(num, buf + 1);
if (buf[1] & 0x80)
n++;
else
tmp++;
if (bp_buf_print(bp, tmp, n, 0) == 0)
goto err;
rv = 1;
err:
OPENSSL_clear_free(buf, buflen);
return rv;
}
static int bp_inner_product_proof_print(BIO *bp,
const bp_inner_product_proof_t *ip_proof,
const EC_GROUP *group, BN_CTX *bn_ctx,
int indent)
{
int ret = 0, i, n;
EC_POINT *L, *R;
if (bp == NULL || ip_proof == NULL || group == NULL || bn_ctx == NULL)
return ret;
bp_bio_printf(bp, indent, "inner proof:\n");
indent += 4;
n = sk_EC_POINT_num(ip_proof->sk_L);
bp_bio_printf(bp, indent, "n: %zu\n", n);
bp_bio_printf(bp, indent, "L[n]:\n");
for (i = 0; i < n; i++) {
L = sk_EC_POINT_value(ip_proof->sk_L, i);
if (L == NULL)
goto end;
bp_bio_printf(bp, indent + 4, "[%zu]: ", i);
if (!bp_point_print(bp, group, L, NULL, 0, bn_ctx))
goto end;
}
bp_bio_printf(bp, indent, "R[n]:\n");
for (i = 0; i < n; i++) {
R = sk_EC_POINT_value(ip_proof->sk_R, i);
if (R == NULL)
goto end;
bp_bio_printf(bp, indent + 4, "[%zu]: ", i);
if (!bp_point_print(bp, group, R, NULL, 0, bn_ctx))
goto end;
}
if (!bp_bn_print(bp, "a", ip_proof->a, NULL, indent)
|| !bp_bn_print(bp, "b", ip_proof->b, NULL, indent))
goto end;
ret = 1;
end:
return ret;
}
#ifndef OPENSSL_NO_STDIO
int BP_PUB_PARAM_print_fp(FILE *fp, const BP_PUB_PARAM *pp, int indent)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
ERR_raise(ERR_LIB_ZKP_BP, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
ret = BP_PUB_PARAM_print(b, pp, indent);
BIO_free(b);
return ret;
}
int BP_WITNESS_print_fp(FILE *fp, const BP_WITNESS *witness, int indent, int flag)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
ERR_raise(ERR_LIB_ZKP_BP, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
ret = BP_WITNESS_print(b, witness, indent, flag);
BIO_free(b);
return ret;
}
int BP_RANGE_PROOF_print_fp(FILE *fp, const BP_RANGE_PROOF *proof, int indent)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
ERR_raise(ERR_LIB_ZKP_BP, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
ret = BP_RANGE_PROOF_print(b, proof, indent);
BIO_free(b);
return ret;
}
int BP_R1CS_PROOF_print_fp(FILE *fp, const BP_R1CS_PROOF *proof, int indent)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
ERR_raise(ERR_LIB_ZKP_BP, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
ret = BP_R1CS_PROOF_print(b, proof, indent);
BIO_free(b);
return ret;
}
#endif
int BP_PUB_PARAM_print(BIO *bp, const BP_PUB_PARAM *pp, int indent)
{
int ret = 0, i, n, curve_id;
BN_CTX *bn_ctx = NULL;
EC_POINT *G, *H;
EC_GROUP *group = NULL;
if (pp == NULL)
return 0;
curve_id = EC_GROUP_get_curve_name(pp->group);
bp_bio_printf(bp, indent, "Bulletproofs Public Parameter: \n");
bp_bio_printf(bp, indent, "curve: %s (%d)\n", OSSL_EC_curve_nid2name(curve_id),
curve_id);
bp_bio_printf(bp, indent, "gens_capacity: %zu\n", pp->gens_capacity);
bp_bio_printf(bp, indent, "party_capacity: %zu\n", pp->party_capacity);
group = pp->group;
bn_ctx = BN_CTX_new();
if (bn_ctx == NULL)
goto end;
bp_bio_printf(bp, indent, "G[n]:\n");
n = pp->gens_capacity * pp->party_capacity;
for (i = 0; i < n; i++) {
G = sk_EC_POINT_value(pp->sk_G, i);
if (G == NULL)
goto end;
bp_bio_printf(bp, indent + 4, "[%zu]: ", i);
if (!bp_point_print(bp, group, G, NULL, 0, bn_ctx))
goto end;
}
bp_bio_printf(bp, indent, "H[n]:\n");
for (i = 0; i < n; i++) {
H = sk_EC_POINT_value(pp->sk_H, i);
if (H == NULL)
goto end;
bp_bio_printf(bp, indent + 4, "[%zu]: ", i);
if (!bp_point_print(bp, group, H, NULL, 0, bn_ctx))
goto end;
}
if (!bp_point_print(bp, group, pp->U, "U: ", indent, bn_ctx)
|| !bp_point_print(bp, group, pp->H, "H: ", indent, bn_ctx))
goto end;
ret = 1;
end:
BN_CTX_free(bn_ctx);
return ret;
}
int BP_WITNESS_print(BIO *bp, const BP_WITNESS *witness, int indent, int flag)
{
int ret = 0, i, n, curve_id;
BN_CTX *bn_ctx = NULL;
BP_VARIABLE *var;
BIGNUM *v, *r;
EC_GROUP *group = NULL;
if (witness == NULL)
return 0;
group = witness->group;
curve_id = EC_GROUP_get_curve_name(group);
bp_bio_printf(bp, indent, "Witness: \n");
bp_bio_printf(bp, indent, "curve: %s (%d)\n", OSSL_EC_curve_nid2name(curve_id),
curve_id);
bn_ctx = BN_CTX_new();
if (bn_ctx == NULL)
goto end;
bp_bio_printf(bp, indent, "H: ");
if (!bp_point_print(bp, group, witness->H, NULL, 0, bn_ctx))
goto end;
bp_bio_printf(bp, indent, "V[n]:\n");
n = sk_BP_VARIABLE_num(witness->sk_V);
for (i = 0; i < n; i++) {
var = sk_BP_VARIABLE_value(witness->sk_V, i);
if (var == NULL)
goto end;
if (var->name != NULL)
bp_bio_printf(bp, indent + 4, "[%s]: ", var->name);
else
bp_bio_printf(bp, indent + 4, "[%zu]: ", i);
if (!bp_point_print(bp, group, var->point, NULL, 0, bn_ctx))
goto end;
}
n = sk_BIGNUM_num(witness->sk_v);
if (n != 0 && flag == 1) {
bp_bio_printf(bp, indent, "v[n]:\n");
for (i = 0; i < n; i++) {
var = sk_BP_VARIABLE_value(witness->sk_V, i);
v = sk_BIGNUM_value(witness->sk_v, i);
if (v == NULL)
goto end;
if (var->name != NULL)
bp_bio_printf(bp, indent + 4, "[%s]: ", var->name);
else
bp_bio_printf(bp, indent + 4, "[%zu]: ", i);
if (!bp_bn_print(bp, NULL, v, NULL, 0))
goto end;
}
bp_bio_printf(bp, indent, "r[n]:\n");
for (i = 0; i < n; i++) {
r = sk_BIGNUM_value(witness->sk_r, i);
if (r == NULL)
goto end;
bp_bio_printf(bp, indent + 4, "[%zu]: ", i);
if (!bp_bn_print(bp, NULL, r, NULL, 0))
goto end;
}
}
ret = 1;
end:
BN_CTX_free(bn_ctx);
return ret;
}
int BP_RANGE_PROOF_print(BIO *bp, const BP_RANGE_PROOF *proof, int indent)
{
int ret = 0, curve_id;
BN_CTX *bn_ctx = NULL;
EC_GROUP *group = NULL;
if (proof == NULL)
return 0;
bp_bio_printf(bp, indent, "Range Proof: \n");
curve_id = EC_POINT_get_curve_name(proof->A);
if (curve_id <= 0)
goto end;
group = EC_GROUP_new_by_curve_name_ex(NULL, NULL, curve_id);
if (group == NULL)
goto end;
bn_ctx = BN_CTX_new();
if (bn_ctx == NULL)
goto end;
if (!bp_point_print(bp, group, proof->A, "A: ", indent, bn_ctx)
|| !bp_point_print(bp, group, proof->S, "S: ", indent, bn_ctx)
|| !bp_point_print(bp, group, proof->T1, "T1: ", indent, bn_ctx)
|| !bp_point_print(bp, group, proof->T2, "T2: ", indent, bn_ctx)
|| !bp_bn_print(bp, "taux", proof->taux, NULL, indent)
|| !bp_bn_print(bp, "mu", proof->mu, NULL, indent)
|| !bp_bn_print(bp, "tx", proof->tx, NULL, indent))
goto end;
if (proof->ip_proof != NULL) {
ret = bp_inner_product_proof_print(bp, proof->ip_proof, group, bn_ctx, indent);
} else {
bp_bio_printf(bp, indent, "inner proof: not found\n");
}
ret = 1;
end:
BN_CTX_free(bn_ctx);
EC_GROUP_free(group);
return ret;
}
int BP_R1CS_PROOF_print(BIO *bp, const BP_R1CS_PROOF *proof, int indent)
{
int ret = 0, curve_id;
BN_CTX *bn_ctx = NULL;
EC_GROUP *group = NULL;
if (proof == NULL)
return 0;
bp_bio_printf(bp, indent, "R1CS Proof: \n");
curve_id = EC_POINT_get_curve_name(proof->AI1);
if (curve_id <= 0)
goto end;
group = EC_GROUP_new_by_curve_name_ex(NULL, NULL, curve_id);
if (group == NULL)
goto end;
bn_ctx = BN_CTX_new();
if (bn_ctx == NULL)
goto end;
if (!bp_point_print(bp, group, proof->AI1, "AI1: ", indent, bn_ctx)
|| !bp_point_print(bp, group, proof->AO1, "AO1: ", indent, bn_ctx)
|| !bp_point_print(bp, group, proof->S1, "S1: ", indent, bn_ctx)
|| !bp_point_print(bp, group, proof->AI2, "AI2: ", indent, bn_ctx)
|| !bp_point_print(bp, group, proof->AO2, "AO2: ", indent, bn_ctx)
|| !bp_point_print(bp, group, proof->S2, "S2: ", indent, bn_ctx)
|| !bp_point_print(bp, group, proof->T1, "T1: ", indent, bn_ctx)
|| !bp_point_print(bp, group, proof->T3, "T3: ", indent, bn_ctx)
|| !bp_point_print(bp, group, proof->T4, "T4: ", indent, bn_ctx)
|| !bp_point_print(bp, group, proof->T5, "T5: ", indent, bn_ctx)
|| !bp_point_print(bp, group, proof->T6, "T6: ", indent, bn_ctx)
|| !bp_bn_print(bp, "taux", proof->taux, NULL, indent)
|| !bp_bn_print(bp, "mu", proof->mu, NULL, indent)
|| !bp_bn_print(bp, "tx", proof->tx, NULL, indent))
goto end;
if (proof->ip_proof != NULL) {
ret = bp_inner_product_proof_print(bp, proof->ip_proof, group, bn_ctx, indent);
} else {
bp_bio_printf(bp, indent, "inner proof: not found\n");
}
ret = 1;
end:
BN_CTX_free(bn_ctx);
EC_GROUP_free(group);
return ret;
}