mirror of
https://github.com/XRPLF/rippled.git
synced 2026-06-06 02:07:07 +00:00
Copying over pedersen commitment from crypto lib (#6238)
This commit is contained in:
@@ -378,23 +378,6 @@ verifyClawbackEqualityProof(
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
std::vector<Buffer>
|
||||
getEqualityProofs(Slice const& zkp)
|
||||
{
|
||||
if (zkp.size() % ecEqualityProofLength != 0)
|
||||
return {};
|
||||
auto const count = zkp.size() / ecEqualityProofLength;
|
||||
|
||||
std::vector<Buffer> zkps;
|
||||
zkps.reserve(count);
|
||||
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
zkps.emplace_back(
|
||||
zkp.data() + (i * ecEqualityProofLength), ecEqualityProofLength);
|
||||
|
||||
return zkps;
|
||||
}
|
||||
|
||||
NotTEC
|
||||
checkEncryptedAmountFormat(STObject const& object)
|
||||
{
|
||||
@@ -419,6 +402,42 @@ checkEncryptedAmountFormat(STObject const& object)
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
TER
|
||||
verifyPedersenLinkage(
|
||||
Slice const& proof,
|
||||
Slice const& encAmt,
|
||||
Slice const& pubKeySlice,
|
||||
Slice const& pcmSlice,
|
||||
uint256 const& contextHash)
|
||||
{
|
||||
if (proof.length() != ecPedersenProofLength)
|
||||
return tecINTERNAL;
|
||||
|
||||
secp256k1_pubkey c1;
|
||||
secp256k1_pubkey c2;
|
||||
|
||||
if (!makeEcPair(encAmt, c1, c2))
|
||||
return tecINTERNAL;
|
||||
|
||||
secp256k1_pubkey pubKey;
|
||||
std::memcpy(pubKey.data, pubKeySlice.data(), ecPubKeyLength);
|
||||
|
||||
secp256k1_pubkey pcm;
|
||||
std::memcpy(pcm.data, pcmSlice.data(), ecPubKeyLength);
|
||||
|
||||
if (secp256k1_elgamal_pedersen_link_verify(
|
||||
secp256k1Context(),
|
||||
proof.data(),
|
||||
&c1,
|
||||
&c2,
|
||||
&pubKey,
|
||||
&pcm,
|
||||
contextHash.data()) != 1)
|
||||
return tecBAD_PROOF;
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
// The following functions belong to the mpt-crypto library,
|
||||
// they will be finally removed and we will use conan2 to manage the dependency.
|
||||
int
|
||||
@@ -1246,4 +1265,271 @@ secp256k1_elgamal_verify_encryption(
|
||||
return 1; // Success: Encryption is valid
|
||||
}
|
||||
|
||||
void
|
||||
get_h_generator(secp256k1_context const* ctx, secp256k1_pubkey* h)
|
||||
{
|
||||
unsigned char h_scalar[32] = {0};
|
||||
h_scalar[31] = 0x03;
|
||||
if (!secp256k1_ec_pubkey_create(ctx, h, h_scalar))
|
||||
{
|
||||
fprintf(stderr, "ABORT: secp256k1_ec_pubkey_create failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
build_link_challenge_hash(
|
||||
secp256k1_context const* ctx,
|
||||
unsigned char hash_input[290],
|
||||
secp256k1_pubkey const* c1,
|
||||
secp256k1_pubkey const* c2,
|
||||
secp256k1_pubkey const* pk,
|
||||
secp256k1_pubkey const* pcm,
|
||||
secp256k1_pubkey const* T1,
|
||||
secp256k1_pubkey const* T2,
|
||||
secp256k1_pubkey const* T3,
|
||||
unsigned char const* context_id)
|
||||
{
|
||||
char const* domain_sep = "MPT_ELGAMAL_PEDERSEN_LINK";
|
||||
size_t offset = 0, len;
|
||||
memset(hash_input, 0, 290);
|
||||
memcpy(hash_input + offset, domain_sep, 25);
|
||||
offset += 27;
|
||||
|
||||
secp256k1_pubkey const* points[] = {c1, c2, pk, pcm, T1, T2, T3};
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
len = 33;
|
||||
secp256k1_ec_pubkey_serialize(
|
||||
ctx, hash_input + offset, &len, points[i], SECP256K1_EC_COMPRESSED);
|
||||
offset += 33;
|
||||
}
|
||||
memcpy(hash_input + offset, context_id, 32);
|
||||
}
|
||||
|
||||
int
|
||||
secp256k1_elgamal_pedersen_link_prove(
|
||||
secp256k1_context const* ctx,
|
||||
unsigned char* proof,
|
||||
secp256k1_pubkey const* c1,
|
||||
secp256k1_pubkey const* c2,
|
||||
secp256k1_pubkey const* pk,
|
||||
secp256k1_pubkey const* pcm,
|
||||
uint64_t amount,
|
||||
unsigned char const* r,
|
||||
unsigned char const* rho,
|
||||
unsigned char const* context_id)
|
||||
{
|
||||
unsigned char km[32], kr[32], krho[32], e[32], sm[32], sr[32], srho[32],
|
||||
m_sc[32] = {0};
|
||||
secp256k1_pubkey T1, T2, T3, H, mG, rPk, rhoH;
|
||||
size_t len = 33;
|
||||
|
||||
if (!generate_random_scalar(ctx, km) || !generate_random_scalar(ctx, kr) ||
|
||||
!generate_random_scalar(ctx, krho))
|
||||
return 0;
|
||||
if (!secp256k1_ec_pubkey_create(ctx, &T1, kr))
|
||||
return 0;
|
||||
if (!secp256k1_ec_pubkey_create(ctx, &mG, km))
|
||||
return 0;
|
||||
rPk = *pk;
|
||||
if (!secp256k1_ec_pubkey_tweak_mul(ctx, &rPk, kr))
|
||||
return 0;
|
||||
secp256k1_pubkey const* add_t2[2] = {&mG, &rPk};
|
||||
if (!secp256k1_ec_pubkey_combine(ctx, &T2, add_t2, 2))
|
||||
return 0;
|
||||
get_h_generator(ctx, &H);
|
||||
rhoH = H;
|
||||
if (!secp256k1_ec_pubkey_tweak_mul(ctx, &rhoH, krho))
|
||||
return 0;
|
||||
secp256k1_pubkey const* add_t3[2] = {&mG, &rhoH};
|
||||
if (!secp256k1_ec_pubkey_combine(ctx, &T3, add_t3, 2))
|
||||
return 0;
|
||||
|
||||
unsigned char hash_input[290];
|
||||
build_link_challenge_hash(
|
||||
ctx, hash_input, c1, c2, pk, pcm, &T1, &T2, &T3, context_id);
|
||||
SHA256(hash_input, 290, e);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
m_sc[31 - i] = (amount >> (i * 8)) & 0xFF;
|
||||
|
||||
memcpy(sm, m_sc, 32);
|
||||
if (!secp256k1_ec_seckey_tweak_mul(ctx, sm, e))
|
||||
return 0;
|
||||
if (!secp256k1_ec_seckey_tweak_add(ctx, sm, km))
|
||||
return 0;
|
||||
memcpy(sr, r, 32);
|
||||
if (!secp256k1_ec_seckey_tweak_mul(ctx, sr, e))
|
||||
return 0;
|
||||
if (!secp256k1_ec_seckey_tweak_add(ctx, sr, kr))
|
||||
return 0;
|
||||
memcpy(srho, rho, 32);
|
||||
if (!secp256k1_ec_seckey_tweak_mul(ctx, srho, e))
|
||||
return 0;
|
||||
if (!secp256k1_ec_seckey_tweak_add(ctx, srho, krho))
|
||||
return 0;
|
||||
|
||||
len = 33;
|
||||
secp256k1_ec_pubkey_serialize(
|
||||
ctx, proof, &len, &T1, SECP256K1_EC_COMPRESSED);
|
||||
len = 33;
|
||||
secp256k1_ec_pubkey_serialize(
|
||||
ctx, proof + 33, &len, &T2, SECP256K1_EC_COMPRESSED);
|
||||
len = 33;
|
||||
secp256k1_ec_pubkey_serialize(
|
||||
ctx, proof + 66, &len, &T3, SECP256K1_EC_COMPRESSED);
|
||||
memcpy(proof + 99, sm, 32);
|
||||
memcpy(proof + 131, sr, 32);
|
||||
memcpy(proof + 163, srho, 32);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* --- Verifier Implementation --- */
|
||||
|
||||
int
|
||||
secp256k1_elgamal_pedersen_link_verify(
|
||||
secp256k1_context const* ctx,
|
||||
unsigned char const* proof,
|
||||
secp256k1_pubkey const* c1,
|
||||
secp256k1_pubkey const* c2,
|
||||
secp256k1_pubkey const* pk,
|
||||
secp256k1_pubkey const* pcm,
|
||||
unsigned char const* context_id)
|
||||
{
|
||||
secp256k1_pubkey T1_p, T2_p, T3_p;
|
||||
secp256k1_pubkey lhs, rhs, H, mG, term2;
|
||||
unsigned char sm[32], sr[32], srho[32], e[32], e_neg[32];
|
||||
unsigned char hash_input[290];
|
||||
|
||||
if (!secp256k1_ec_pubkey_parse(ctx, &T1_p, proof, 33))
|
||||
return 0;
|
||||
if (!secp256k1_ec_pubkey_parse(ctx, &T2_p, proof + 33, 33))
|
||||
return 0;
|
||||
if (!secp256k1_ec_pubkey_parse(ctx, &T3_p, proof + 66, 33))
|
||||
return 0;
|
||||
|
||||
memcpy(sm, proof + 99, 32);
|
||||
memcpy(sr, proof + 131, 32);
|
||||
memcpy(srho, proof + 163, 32);
|
||||
|
||||
if (secp256k1_ec_seckey_verify(ctx, sm) != 1)
|
||||
return 0;
|
||||
if (secp256k1_ec_seckey_verify(ctx, sr) != 1)
|
||||
return 0;
|
||||
if (secp256k1_ec_seckey_verify(ctx, srho) != 1)
|
||||
return 0;
|
||||
|
||||
build_link_challenge_hash(
|
||||
ctx, hash_input, c1, c2, pk, pcm, &T1_p, &T2_p, &T3_p, context_id);
|
||||
SHA256(hash_input, sizeof(hash_input), e);
|
||||
if (secp256k1_ec_seckey_verify(ctx, e) != 1)
|
||||
return 0;
|
||||
|
||||
memcpy(e_neg, e, 32);
|
||||
if (!secp256k1_ec_seckey_negate(ctx, e_neg))
|
||||
return 0;
|
||||
|
||||
#define COMBINE2(out, A, B) \
|
||||
do \
|
||||
{ \
|
||||
secp256k1_pubkey _sum; \
|
||||
const secp256k1_pubkey* _pts[2] = {(A), (B)}; \
|
||||
if (!secp256k1_ec_pubkey_combine(ctx, &_sum, _pts, 2)) \
|
||||
return 0; \
|
||||
(out) = _sum; \
|
||||
} while (0)
|
||||
|
||||
#define EQ_PUBKEY(A, B) \
|
||||
do \
|
||||
{ \
|
||||
unsigned char _a[33], _b[33]; \
|
||||
size_t _l = 33; \
|
||||
if (!secp256k1_ec_pubkey_serialize( \
|
||||
ctx, _a, &_l, (A), SECP256K1_EC_COMPRESSED)) \
|
||||
return 0; \
|
||||
_l = 33; \
|
||||
if (!secp256k1_ec_pubkey_serialize( \
|
||||
ctx, _b, &_l, (B), SECP256K1_EC_COMPRESSED)) \
|
||||
return 0; \
|
||||
if (memcmp(_a, _b, 33) != 0) \
|
||||
return 0; \
|
||||
} while (0)
|
||||
|
||||
/* Eq 1 */
|
||||
if (!secp256k1_ec_pubkey_create(ctx, &lhs, sr))
|
||||
return 0;
|
||||
rhs = *c1;
|
||||
if (!secp256k1_ec_pubkey_tweak_mul(ctx, &rhs, e_neg))
|
||||
return 0;
|
||||
COMBINE2(lhs, &lhs, &rhs);
|
||||
EQ_PUBKEY(&lhs, &T1_p);
|
||||
|
||||
/* Eq 2 */
|
||||
if (!secp256k1_ec_pubkey_create(ctx, &mG, sm))
|
||||
return 0;
|
||||
term2 = *pk;
|
||||
if (!secp256k1_ec_pubkey_tweak_mul(ctx, &term2, sr))
|
||||
return 0;
|
||||
COMBINE2(lhs, &mG, &term2);
|
||||
rhs = *c2;
|
||||
if (!secp256k1_ec_pubkey_tweak_mul(ctx, &rhs, e_neg))
|
||||
return 0;
|
||||
COMBINE2(lhs, &lhs, &rhs);
|
||||
EQ_PUBKEY(&lhs, &T2_p);
|
||||
|
||||
/* Eq 3 */
|
||||
get_h_generator(ctx, &H);
|
||||
term2 = H;
|
||||
if (!secp256k1_ec_pubkey_tweak_mul(ctx, &term2, srho))
|
||||
return 0;
|
||||
COMBINE2(lhs, &mG, &term2);
|
||||
rhs = *pcm;
|
||||
if (!secp256k1_ec_pubkey_tweak_mul(ctx, &rhs, e_neg))
|
||||
return 0;
|
||||
COMBINE2(lhs, &lhs, &rhs);
|
||||
EQ_PUBKEY(&lhs, &T3_p);
|
||||
|
||||
#undef COMBINE2
|
||||
#undef EQ_PUBKEY
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
secp256k1_mpt_pedersen_commit(
|
||||
secp256k1_context const* ctx,
|
||||
secp256k1_pubkey* commitment,
|
||||
uint64_t amount,
|
||||
unsigned char const* rho)
|
||||
{
|
||||
secp256k1_pubkey mG, rH, H;
|
||||
unsigned char m_scalar[32] = {0};
|
||||
|
||||
// 1. Calculate m * G
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
m_scalar[31 - i] = (amount >> (i * 8)) & 0xFF;
|
||||
}
|
||||
if (!secp256k1_ec_pubkey_create(ctx, &mG, m_scalar))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 2. Calculate rho * H
|
||||
get_h_generator(ctx, &H);
|
||||
rH = H;
|
||||
if (!secp256k1_ec_pubkey_tweak_mul(ctx, &rH, rho))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 3. Combine: mG + rH
|
||||
secp256k1_pubkey const* points[2] = {&mG, &rH};
|
||||
if (!secp256k1_ec_pubkey_combine(ctx, commitment, points, 2))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
@@ -12,16 +12,6 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
size_t
|
||||
expectedProofLength(std::shared_ptr<SLE const> const& issuance)
|
||||
{
|
||||
auto const equalityProofLength = getEqualityProofLength(
|
||||
issuance->isFieldPresent(sfAuditorElGamalPublicKey));
|
||||
|
||||
// todo: add pederson and range proof length
|
||||
return equalityProofLength;
|
||||
}
|
||||
|
||||
NotTEC
|
||||
ConfidentialConvertBack::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
@@ -74,9 +64,10 @@ verifyProofs(
|
||||
bool const hasAuditor = issuance->isFieldPresent(sfAuditorElGamalPublicKey);
|
||||
if (hasAuditor)
|
||||
{
|
||||
auditor.emplace(EncryptedAmountInfo{
|
||||
(*issuance)[sfAuditorElGamalPublicKey],
|
||||
tx[sfAuditorEncryptedAmount]});
|
||||
auditor.emplace(
|
||||
EncryptedAmountInfo{
|
||||
(*issuance)[sfAuditorElGamalPublicKey],
|
||||
tx[sfAuditorEncryptedAmount]});
|
||||
}
|
||||
|
||||
if (auto const ter = verifyRevealedAmount(
|
||||
|
||||
Reference in New Issue
Block a user