33constexpr std::string_view kMessageNonceTag =
"PureSign/Nonce/Message/";
34constexpr std::string_view kTopicNonceTag =
"PureSign/Nonce/Topic/";
35constexpr std::string_view kMessageBindingTag =
"PureSign/Binding/Message";
36constexpr std::string_view kTopicBindingTag =
"PureSign/Binding/Topic";
37constexpr std::string_view kMessageProofTag =
"PureSign/BPPP/Proof/Message/V1";
38constexpr std::string_view kTopicProofTag =
"PureSign/BPPP/Proof/Topic/V1";
43 static const TaggedHash kMessageBindingTaggedHash(kMessageBindingTag);
44 static const TaggedHash kTopicBindingTaggedHash(kTopicBindingTag);
45 return scope == Scope::Message ? kMessageBindingTaggedHash : kTopicBindingTaggedHash;
49 static const TaggedHash kMessageProofTaggedHash(kMessageProofTag);
50 static const TaggedHash kTopicProofTaggedHash(kTopicProofTag);
51 return scope == Scope::Message ? kMessageProofTaggedHash : kTopicProofTaggedHash;
54const UInt256& secp256k1_order() {
56 UInt256::from_hex(
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
60Status validate_puresign_field_alignment() {
67const unsigned char* nullable_data(std::span<const unsigned char> input) {
68 return input.empty() ? nullptr : input.data();
73 out = tag.digest(input);
77std::string_view proof_tag_for_scope(Scope
scope) {
78 return scope == Scope::Message ? kMessageProofTag : kTopicProofTag;
85Scalar32 derive_proof_nonce_seed(
const SecretKey& secret, Scope
scope, std::span<const unsigned char>
eval_input) {
86 std::array<unsigned char, 64> secret_bytes = secret.packed().to_bytes_be();
88 std::array digest_segments{
89 std::span<const unsigned char>(secret_bytes.data(), secret_bytes.size()),
92 out = proof_tagged_hash(
scope).digest_many(digest_segments);
99 "puresign_plusplus:validate_public_key_bundle:purify_pubkey");
101 "puresign_plusplus:validate_public_key_bundle:secp_context");
104 "puresign_plusplus:validate_public_key_bundle:bip340_pubkey");
117struct DerivedNonceData {
126Result<DerivedNonceData> derive_nonce_data(
const SecretKey& secret,
128 std::span<const unsigned char> input,
130 PURIFY_RETURN_IF_ERROR(validate_puresign_field_alignment(),
"derive_nonce_data:validate_puresign_field_alignment");
133 const std::string_view nonce_tag =
scope == Scope::Message ? kMessageNonceTag : kTopicNonceTag;
134 const TaggedHash& binding_hash = binding_tagged_hash(
scope);
136 DerivedNonceData out{};
138 out.signer_pubkey = signer.xonly_pubkey;
143 out.scalar = nonce_value.to_bytes_be();
144 if (std::all_of(out.scalar.begin(), out.scalar.end(), [](
unsigned char byte) { return byte == 0; })) {
149 "derive_nonce_data:secp_context");
156Result<DerivedNonceData> prepare_nonce_data_impl(
const SecretKey& secret,
158 std::span<const unsigned char> input,
160 if (
scope == Scope::Topic && input.empty()) {
164 "prepare_nonce_data_impl:derive_nonce_data");
168Result<bppp::PointBytes> commitment_point_from_scalar(
const FieldElement&
scalar,
175Result<bool> nonce_proof_matches_nonce(
const NonceProof& nonce_proof,
180 "nonce_proof_matches_nonce:secp_context");
183 "nonce_proof_matches_nonce:invalid_commitment_point");
186 return xonly == nonce_proof.nonce.xonly;
189Result<NonceProof> build_nonce_proof_from_template(
const SecretKey& secret,
191 const Nonce& expected_nonce,
193 const NativeBulletproofCircuitTemplate& circuit_template,
195 bppp::ExperimentalCircuitBackend* circuit_cache) {
197 "build_nonce_proof_from_template:prove_assignment_data");
199 "build_nonce_proof_from_template:partial_evaluate");
203 PURIFY_ASSIGN_OR_RETURN(
auto final_ok, circuit_template.final_evaluate(witness.assignment, witness.public_key),
204 "build_nonce_proof_from_template:final_evaluate");
209 "build_nonce_proof_from_template:instantiate");
211 "build_nonce_proof_from_template:validate_proof_cache_circuit");
213 PURIFY_ASSIGN_OR_RETURN(
auto commitment_point, commitment_point_from_scalar(witness.assignment.commitments.front(), secp_context),
214 "build_nonce_proof_from_template:commitment_point_from_scalar");
216 Bytes statement_binding = proof_statement_binding(
scope);
217 std::array<bppp::PointBytes, 1> public_commitments{commitment_point};
221 circuit, witness.assignment, proof_nonce, public_commitments, secp_context, statement_binding, circuit_cache),
222 "build_nonce_proof_from_template:prove_experimental_circuit_zk_norm_arg_with_public_commitments");
225 out.nonce = expected_nonce;
226 out.commitment_point = commitment_point;
227 out.proof = std::move(proof);
229 "build_nonce_proof_from_template:nonce_proof_matches_nonce");
236Result<NonceProof> build_nonce_proof(
const SecretKey& secret,
238 std::span<const unsigned char> input,
239 const Nonce& expected_nonce,
241 bppp::ExperimentalCircuitBackend* circuit_cache) {
242 const std::string_view nonce_tag =
scope == Scope::Message ? kMessageNonceTag : kTopicNonceTag;
244 "build_nonce_proof:verifier_circuit_template");
246 return build_nonce_proof_from_template(secret,
scope, expected_nonce,
eval_input, circuit_template, secp_context,
250Result<bool> verify_nonce_proof_with_circuit(
const PublicKey& public_key,
251 const NativeBulletproofCircuit& circuit,
252 const NonceProof& nonce_proof,
256 bppp::ExperimentalCircuitBackend* circuit_cache) {
263 Bytes statement_binding = proof_statement_binding(
scope);
264 std::array<bppp::PointBytes, 1> public_commitments{nonce_proof.commitment_point};
266 circuit, nonce_proof.proof, public_commitments, secp_context, statement_binding, circuit_cache);
274 "MessageProofCache::build:verifier_circuit_template");
276 "MessageProofCache::build:integrity_digest");
291 "TopicProofCache::build:verifier_circuit_template");
293 "TopicProofCache::build:integrity_digest");
312 : scope_(other.scope_), scalar_(other.scalar_), nonce_(other.nonce_),
313 signer_pubkey_(other.signer_pubkey_), binding_digest_(other.binding_digest_) {
318 if (
this != &other) {
320 scope_ = other.scope_;
321 scalar_ = other.scalar_;
322 nonce_ = other.nonce_;
323 signer_pubkey_ = other.signer_pubkey_;
324 binding_digest_ = other.binding_digest_;
334void PreparedNonce::clear() noexcept {
335 std::fill(scalar_.begin(), scalar_.end(),
static_cast<unsigned char>(0));
339 std::span<const unsigned char> message,
341 if (scope_ != Scope::Message) {
344 if (signer_pubkey_ != signer.xonly_pubkey) {
347 if (binding_digest_ !=
binding_digest(binding_tagged_hash(Scope::Message), message)) {
352 "PreparedNonce::sign_message:secp_context");
355 signer.seckey.data(), scalar_.data()) == 0) {
358 if (out.nonce().xonly != nonce_.xonly) {
361 if (
purify_bip340_verify(secp_context, out.bytes.data(), nullable_data(message), message.size(),
362 signer.xonly_pubkey.data()) == 0) {
369 std::span<const unsigned char> message,
371 if (scope_ != Scope::Topic) {
374 if (signer_pubkey_ != signer.xonly_pubkey) {
379 "PreparedNonce::sign_topic_message:secp_context");
382 signer.seckey.data(), scalar_.data()) == 0) {
384 "PreparedNonce::sign_topic_message:sign_with_fixed_nonce");
386 if (out.nonce().xonly != nonce_.xonly) {
389 if (
purify_bip340_verify(secp_context, out.bytes.data(), nullable_data(message), message.size(),
390 signer.xonly_pubkey.data()) == 0) {
401 std::span<const unsigned char> message,
406 "PreparedNonceWithProof::sign_message:sign_message_with_prepared");
407 if (signature.nonce().xonly != nonce_proof.
nonce.
xonly) {
414 std::span<const unsigned char> message,
419 "PreparedNonceWithProof::sign_topic_message:sign_with_prepared_topic");
420 if (signature.nonce().xonly != nonce_proof.
nonce.
xonly) {
431 return PublicKey{purify_key.public_key, bip340_key.xonly_pubkey};
444 PURIFY_ASSIGN_OR_RETURN(
const auto& nonce_data, prepare_nonce_data_impl(secret, Scope::Message, message, secp_context),
445 "prepare_message_nonce:prepare_nonce_data_impl");
447 nonce_data.signer_pubkey, nonce_data.binding_digest);
451 std::span<const unsigned char> message,
454 PURIFY_ASSIGN_OR_RETURN(
const auto& nonce_data, prepare_nonce_data_impl(secret, Scope::Message, message, secp_context),
455 "prepare_message_nonce_with_proof:prepare_nonce_data_impl");
457 nonce_data.nonce, nonce_data.signer_pubkey,
458 nonce_data.binding_digest);
461 "prepare_message_nonce_with_proof:build_nonce_proof");
470 "prepare_message_nonce_with_proof:validate_message_proof_cache");
472 "prepare_message_nonce_with_proof:prepare_nonce_data_impl");
474 nonce_data.nonce, nonce_data.signer_pubkey,
475 nonce_data.binding_digest);
478 build_nonce_proof_from_template(secret, Scope::Message, prepared.
public_nonce(),
480 circuit_cache !=
nullptr ? circuit_cache : &cache.
backend_cache),
481 "prepare_message_nonce_with_proof:build_nonce_proof_from_template");
487 PURIFY_ASSIGN_OR_RETURN(
const auto& nonce_data, prepare_nonce_data_impl(secret, Scope::Topic, topic, secp_context),
488 "prepare_topic_nonce:prepare_nonce_data_impl");
490 nonce_data.signer_pubkey, nonce_data.binding_digest);
494 std::span<const unsigned char> topic,
497 PURIFY_ASSIGN_OR_RETURN(
const auto& nonce_data, prepare_nonce_data_impl(secret, Scope::Topic, topic, secp_context),
498 "prepare_topic_nonce_with_proof:prepare_nonce_data_impl");
500 nonce_data.nonce, nonce_data.signer_pubkey,
501 nonce_data.binding_digest);
504 "prepare_topic_nonce_with_proof:build_nonce_proof");
513 "prepare_topic_nonce_with_proof:validate_topic_proof_cache");
515 "prepare_topic_nonce_with_proof:prepare_nonce_data_impl");
517 nonce_data.nonce, nonce_data.signer_pubkey,
518 nonce_data.binding_digest);
521 build_nonce_proof_from_template(secret, Scope::Topic, prepared.
public_nonce(),
523 circuit_cache !=
nullptr ? circuit_cache : &cache.
backend_cache),
524 "prepare_topic_nonce_with_proof:build_nonce_proof_from_template");
537 return std::move(prepared).sign_message(signer, message, secp_context);
541 std::span<const unsigned char> message,
544 return std::move(prepared).sign_message(secret, message, secp_context);
548 std::span<const unsigned char> topic,
557 return std::move(prepared).sign_topic_message(signer, message, secp_context);
561 std::span<const unsigned char> message,
564 return std::move(prepared).sign_topic_message(secret, message, secp_context);
571 "sign_message_with_proof:prepare_message_nonce_with_proof");
579 "sign_message_with_proof:prepare_message_nonce_with_proof");
584 std::span<const unsigned char> topic,
588 "sign_with_topic_proof:prepare_topic_nonce_with_proof");
597 "sign_with_topic_proof:prepare_topic_nonce_with_proof");
605 "verify_signature:secp_context");
622 "verify_message_nonce_proof:verifier_circuit");
623 return verify_nonce_proof_with_circuit(public_key, circuit, nonce_proof, Scope::Message, secp_context,
624 "verify_message_nonce_proof:verify_nonce_proof_with_circuit",
632 PURIFY_RETURN_IF_ERROR(validate_message_proof_cache(cache),
"verify_message_nonce_proof:validate_message_proof_cache");
634 "verify_message_nonce_proof:instantiate");
635 return verify_nonce_proof_with_circuit(public_key, circuit, nonce_proof, Scope::Message, secp_context,
636 "verify_message_nonce_proof:verify_nonce_proof_with_circuit",
637 circuit_cache !=
nullptr ? circuit_cache : &cache.
backend_cache);
649 "verify_topic_nonce_proof:verifier_circuit");
650 return verify_nonce_proof_with_circuit(public_key, circuit, nonce_proof, Scope::Topic, secp_context,
651 "verify_topic_nonce_proof:verify_nonce_proof_with_circuit",
659 PURIFY_RETURN_IF_ERROR(validate_topic_proof_cache(cache),
"verify_topic_nonce_proof:validate_topic_proof_cache");
661 "verify_topic_nonce_proof:instantiate");
662 return verify_nonce_proof_with_circuit(public_key, circuit, nonce_proof, Scope::Topic, secp_context,
663 "verify_topic_nonce_proof:verify_nonce_proof_with_circuit",
664 circuit_cache !=
nullptr ? circuit_cache : &cache.
backend_cache);
668 std::span<const unsigned char> message,
673 "verify_message_signature_with_proof:verify_signature");
688 "verify_message_signature_with_proof:verify_signature");
699 std::span<const unsigned char> message,
700 std::span<const unsigned char> topic,
705 "verify_topic_signature_with_proof:verify_signature");
716 std::span<const unsigned char> message,
721 "verify_topic_signature_with_proof:verify_signature");
783 std::span<const unsigned char> topic,
791 std::span<const unsigned char> message,
814 std::span<const unsigned char> message,
833 std::span<const unsigned char> topic,
856 return std::move(prepared).sign_message(signer, message, secp_context);
862 return std::move(prepared).sign_message(secret_, message, secp_context);
866 std::span<const unsigned char> topic,
876 return std::move(prepared).sign_topic_message(signer, message, secp_context);
882 return std::move(prepared).sign_topic_message(secret_, message, secp_context);
889 "KeyPair::sign_message_with_proof:prepare_message_nonce_with_proof");
897 "KeyPair::sign_message_with_proof:prepare_message_nonce_with_proof");
902 std::span<const unsigned char> topic,
906 "KeyPair::sign_with_topic_proof:prepare_topic_nonce_with_proof");
915 "KeyPair::sign_with_topic_proof:prepare_topic_nonce_with_proof");
Purify result carrier that either holds a value or an error.
Result< NativeBulletproofCircuit > instantiate(const UInt512 &pubkey) const
Result< Bytes > integrity_digest() const
Returns a stable digest of the packed base circuit plus late-bound expressions.
Move-only packed Purify secret stored in dedicated heap memory.
Result< SecretKey > clone() const
Creates a second owned copy of this secret key.
Reusable BIP340-style tagged SHA-256 helper.
Common interface for reusable experimental BPPP backend state.
Result< PreparedNonce > prepare_message_nonce(std::span< const unsigned char > message, purify_secp_context *secp_context) const
Deterministically prepares a message-bound nonce.
Result< PreparedNonce > prepare_topic_nonce(std::span< const unsigned char > topic, purify_secp_context *secp_context) const
Deterministically prepares a topic-bound nonce.
Result< ProvenSignature > sign_message_with_proof(std::span< const unsigned char > message, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache=nullptr) const
Signs a message and returns the signature bundled with its BPPP nonce proof.
const PublicKey & public_key() const noexcept
Returns the public key bundle associated with this signer.
Result< Signature > sign_with_prepared_topic(std::span< const unsigned char > message, PreparedNonce &&prepared, purify_secp_context *secp_context) const
Signs a message using an already prepared topic-bound nonce.
static Result< KeyPair > from_secret(const SecretKey &secret, purify_secp_context *secp_context)
Derives a PureSign++ signing key pair from one packed Purify secret.
Result< PreparedNonceWithProof > prepare_message_nonce_with_proof(std::span< const unsigned char > message, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache=nullptr) const
Deterministically prepares a message-bound nonce together with its BPPP proof.
Result< ProvenSignature > sign_with_prepared_topic_proof(std::span< const unsigned char > message, PreparedNonceWithProof &&prepared, purify_secp_context *secp_context) const
Signs a message using an already prepared topic-bound nonce proof bundle.
Result< Signature > sign_message_with_prepared(std::span< const unsigned char > message, PreparedNonce &&prepared, purify_secp_context *secp_context) const
Signs a message using an already prepared message-bound nonce.
Result< ProvenSignature > sign_with_topic_proof(std::span< const unsigned char > message, std::span< const unsigned char > topic, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache=nullptr) const
Signs a message with a topic-bound nonce proof.
Result< Signature > sign_message(std::span< const unsigned char > message, purify_secp_context *secp_context) const
Signs a message with a deterministically derived message-bound nonce.
Result< PreparedNonceWithProof > prepare_topic_nonce_with_proof(std::span< const unsigned char > topic, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache=nullptr) const
Deterministically prepares a topic-bound nonce together with its BPPP proof.
Result< Signature > sign_with_topic(std::span< const unsigned char > message, std::span< const unsigned char > topic, purify_secp_context *secp_context) const
Signs a message using a topic-bound deterministic nonce.
Result< ProvenSignature > sign_message_with_prepared_proof(std::span< const unsigned char > message, PreparedNonceWithProof &&prepared, purify_secp_context *secp_context) const
Signs a message using an already prepared message-bound nonce proof bundle.
const NonceProof & proof() const noexcept
Returns the public nonce proof carried by this bundle.
Result< ProvenSignature > sign_message(const SecretKey &secret, std::span< const unsigned char > message, purify_secp_context *secp_context) &&
Consumes this message-bound prepared proof bundle and signs the message.
static PreparedNonceWithProof from_parts(PreparedNonce prepared, NonceProof proof)
Bundles a prepared nonce with its matching BPPP-backed public nonce proof.
Result< ProvenSignature > sign_topic_message(const SecretKey &secret, std::span< const unsigned char > message, purify_secp_context *secp_context) &&
Consumes this topic-bound prepared proof bundle and signs the message.
Move-only prepared nonce bound to either a message or a topic.
Result< Signature > sign_message(const Bip340Key &signer, std::span< const unsigned char > message, purify_secp_context *secp_context) &&
Consumes this message-bound nonce and signs the matching message.
const Nonce & public_nonce() const noexcept
Returns the public nonce corresponding to this prepared secret nonce scalar.
PreparedNonce & operator=(const PreparedNonce &)=delete
PreparedNonce(const PreparedNonce &)=delete
Result< Signature > sign_topic_message(const Bip340Key &signer, std::span< const unsigned char > message, purify_secp_context *secp_context) &&
Consumes this topic-bound nonce and signs a message under that topic binding.
Scalar32 scalar() const
Explicitly exports the secret nonce scalar.
static PreparedNonce from_parts(Scope scope, const Scalar32 &scalar, const Nonce &nonce, const XOnly32 &signer_pubkey, const XOnly32 &binding_digest)
Builds a prepared nonce from already-derived nonce components.
#define PURIFY_RETURN_IF_ERROR(expr, context)
Evaluates an expected-like expression and returns the wrapped error on failure.
#define PURIFY_ASSIGN_OR_RETURN(lhs, expr, context)
Evaluates an expected-like expression, binds the value to lhs, and propagates errors.
GeneratorBytes base_generator(purify_secp_context *secp_context)
Returns the serialized secp256k1 base generator used as the blind generator.
Result< bool > verify_experimental_circuit_zk_norm_arg_with_public_commitments(const NativeBulletproofCircuit &circuit, const ExperimentalCircuitZkNormArgProof &proof, std::span< const PointBytes > public_commitments, purify_secp_context *secp_context, std::span< const unsigned char > statement_binding={}, ExperimentalCircuitBackend *cache=nullptr)
Verifies an experimental masked circuit proof against explicit public commitment points.
Result< ExperimentalCircuitZkNormArgProof > prove_experimental_circuit_zk_norm_arg_with_public_commitments(const NativeBulletproofCircuit &circuit, const BulletproofAssignmentData &assignment, const ScalarBytes &nonce, std::span< const PointBytes > public_commitments, purify_secp_context *secp_context, std::span< const unsigned char > statement_binding={}, ExperimentalCircuitBackend *cache=nullptr)
Produces an experimental masked circuit proof bound to explicit public commitment points.
Result< PointBytes > pedersen_commit_char(const ScalarBytes &blind, const ScalarBytes &value, purify_secp_context *secp_context)
Computes a Pedersen commitment to an arbitrary 32-byte scalar value using Purify's default generators...
ScalarBytes scalar_bytes(const FieldElement &value)
Serializes a Purify field element into the scalar encoding expected by the BPPP bridge.
const UInt256 & secp256k1_order()
Bytes tagged_eval_input(std::string_view tag, std::span< const unsigned char > input)
Status validate_topic_proof_cache(const CacheLike &cache, std::string_view nonce_tag)
void secure_clear_bytes(void *data, std::size_t size) noexcept
Status validate_message_proof_cache(const CacheLike &cache, std::string_view nonce_tag)
Bytes copy_bytes(std::span< const unsigned char > input)
Status validate_proof_cache_circuit(const CircuitLike &circuit, const char *context)
Result< PublicKey > derive_public_key(const SecretKey &secret, purify_secp_context *secp_context)
Result< PreparedNonce > prepare_message_nonce(const SecretKey &secret, std::span< const unsigned char > message, purify_secp_context *secp_context)
Result< Signature > sign_message_with_prepared(const SecretKey &secret, std::span< const unsigned char > message, PreparedNonce &&prepared, purify_secp_context *secp_context)
Result< bool > verify_topic_nonce_proof(const PublicKey &public_key, std::span< const unsigned char > topic, const NonceProof &nonce_proof, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache)
Result< PreparedNonce > prepare_topic_nonce(const SecretKey &secret, std::span< const unsigned char > topic, purify_secp_context *secp_context)
Result< PreparedNonceWithProof > prepare_message_nonce_with_proof(const SecretKey &secret, std::span< const unsigned char > message, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache)
Result< ProvenSignature > sign_message_with_proof(const SecretKey &secret, std::span< const unsigned char > message, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache)
Result< Signature > sign_with_prepared_topic(const SecretKey &secret, std::span< const unsigned char > message, PreparedNonce &&prepared, purify_secp_context *secp_context)
Result< bool > verify_message_nonce_proof(const PublicKey &public_key, std::span< const unsigned char > message, const NonceProof &nonce_proof, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache)
Result< ProvenSignature > sign_message_with_prepared_proof(const SecretKey &secret, std::span< const unsigned char > message, PreparedNonceWithProof &&prepared, purify_secp_context *secp_context)
Result< ProvenSignature > sign_with_topic_proof(const SecretKey &secret, std::span< const unsigned char > message, std::span< const unsigned char > topic, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache)
Result< MessageProofCache > build_message_proof_cache(std::span< const unsigned char > message)
Result< bool > verify_topic_signature_with_proof(const PublicKey &public_key, std::span< const unsigned char > message, std::span< const unsigned char > topic, const ProvenSignature &signature, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache)
Result< PreparedNonceWithProof > prepare_topic_nonce_with_proof(const SecretKey &secret, std::span< const unsigned char > topic, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache)
Result< Signature > sign_with_topic(const SecretKey &secret, std::span< const unsigned char > message, std::span< const unsigned char > topic, purify_secp_context *secp_context)
Result< ProvenSignature > sign_with_prepared_topic_proof(const SecretKey &secret, std::span< const unsigned char > message, PreparedNonceWithProof &&prepared, purify_secp_context *secp_context)
Result< bool > verify_signature(const PublicKey &public_key, std::span< const unsigned char > message, const Signature &signature, purify_secp_context *secp_context)
Result< Signature > sign_message(const SecretKey &secret, std::span< const unsigned char > message, purify_secp_context *secp_context)
Result< TopicProofCache > build_topic_proof_cache(std::span< const unsigned char > topic)
Result< bool > verify_message_signature_with_proof(const PublicKey &public_key, std::span< const unsigned char > message, const ProvenSignature &signature, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache)
std::array< unsigned char, 32 > Scalar32
std::array< unsigned char, 32 > XOnly32
Status require_secp_context(const purify_secp_context *context, const char *error_context)
constexpr Unexpected< Error > unexpected_error(ErrorCode code, const char *context=nullptr)
Constructs an unexpected Error value from a machine-readable code.
const UInt256 & prime_p()
Returns the Purify base-field modulus.
Result< NativeBulletproofCircuitTemplate > verifier_circuit_template(const Bytes &message)
Builds a reusable public-key-agnostic verifier-circuit template for a message.
Result< BulletproofWitnessData > prove_assignment_data(const Bytes &message, const SecretKey &secret)
Computes the native Purify witness for a message and secret.
Result< NativeBulletproofCircuit > verifier_circuit(const Bytes &message, const UInt512 &pubkey)
Builds the native verifier circuit for a message and public key.
Bytes bytes_from_ascii(std::string_view input)
Encodes an ASCII string as a byte vector.
Status validate_public_key(const UInt512 &packed)
Validates the packed public-key encoding range.
Result< Bip340Key > derive_bip340_key(const SecretKey &secret, purify_secp_context *secp_context)
Derives a canonical BIP340 signing keypair from an owned Purify secret.
Result< GeneratedKey > derive_key(const SecretKey &secret)
Derives the packed public key corresponding to a packed secret.
std::vector< unsigned char > Bytes
Dynamically sized byte string used for messages, serialized witnesses, and proofs.
Result< FieldElement > eval(const SecretKey &secret, const Bytes &message)
Evaluates the Purify PRF for an owned secret key and message.
BigUInt< 4 > UInt256
256-bit unsigned integer used for field elements and curve orders.
Expected< void, Error > Status
Expected-returning convenience alias for Purify status-only APIs.
Experimental BPPP-backed PureSign proof(R) helpers.
Narrow C ABI exposing secp256k1 scalar and HMAC helpers to the C++ headers.
int purify_bip340_xonly_from_point(purify_secp_context *context, const unsigned char point33[33], unsigned char xonly32[32], int *parity_out)
Converts a compressed secp256k1 point into its x-only public key encoding.
int purify_bip340_nonce_from_scalar(purify_secp_context *context, unsigned char scalar32[32], unsigned char xonly_nonce32[32])
Canonicalizes a valid secp256k1 nonce scalar for BIP340 and derives its x-only public nonce.
int purify_bip340_sign_with_fixed_nonce(purify_secp_context *context, unsigned char sig64[64], const unsigned char *msg, size_t msglen, const unsigned char seckey32[32], const unsigned char nonce32[32])
Signs a message with a caller-supplied BIP340 nonce scalar.
int purify_bip340_validate_signature(purify_secp_context *context, const unsigned char sig64[64])
Returns nonzero when the 64-byte BIP340 signature has a syntactically valid encoding.
int purify_bip340_validate_xonly_pubkey(purify_secp_context *context, const unsigned char xonly_pubkey32[32])
Returns nonzero when the x-only public key encoding parses successfully.
int purify_bip340_verify(purify_secp_context *context, const unsigned char sig64[64], const unsigned char *msg, size_t msglen, const unsigned char xonly_pubkey32[32])
Verifies a BIP340 signature against a serialized x-only public key.
static BigUInt from_hex(std::string_view hex)
Parses a hexadecimal string with the precondition that the value fits exactly.
Canonical BIP340 keypair derived deterministically from a packed Purify secret.
Cacheable message-bound nonce-proof template for the BPPP-backed PureSign++ proof(R) flow.
bppp::ExperimentalCircuitCache backend_cache
NativeBulletproofCircuitTemplate circuit_template
static Result< MessageProofCache > build(std::span< const unsigned char > message)
Builds a reusable verifier template for one exact message.
Public BIP340 nonce point in x-only form.
static Result< PublicKey > from_secret(const SecretKey &secret, purify_secp_context *secp_context)
Derives both public identities from one packed Purify secret.
Result< bool > verify_message_nonce_proof(std::span< const unsigned char > message, const NonceProof &nonce_proof, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache=nullptr) const
Verifies a message-bound BPPP nonce proof against this public key.
Result< bool > verify_topic_nonce_proof(std::span< const unsigned char > topic, const NonceProof &nonce_proof, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache=nullptr) const
Verifies a topic-bound BPPP nonce proof against this public key.
Result< bool > verify_signature(std::span< const unsigned char > message, const Signature &signature, purify_secp_context *secp_context) const
Verifies a plain BIP340 signature against this bundle's x-only public key.
Result< bool > verify_message_signature_with_proof(std::span< const unsigned char > message, const ProvenSignature &signature, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache=nullptr) const
Verifies a message signature bundled with its BPPP nonce proof.
Result< bool > verify_topic_signature_with_proof(std::span< const unsigned char > message, std::span< const unsigned char > topic, const ProvenSignature &signature, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache=nullptr) const
Verifies a topic-bound signature bundled with its BPPP nonce proof.
Standard 64-byte BIP340 signature.
Nonce nonce() const
Returns the x-only public nonce encoded in the first 32 signature bytes.
Cacheable topic-bound nonce-proof template for the BPPP-backed PureSign++ proof(R) flow.
bppp::ExperimentalCircuitCache backend_cache
NativeBulletproofCircuitTemplate circuit_template
static Result< TopicProofCache > build(std::span< const unsigned char > topic)
Builds a reusable verifier template for one exact topic.