package fr.acinq.secp256k1; public class Secp256k1CFunctions { /** * All flags' lower 8 bits indicate what they're for. Do not use directly. */ public static int SECP256K1_FLAGS_TYPE_MASK = ((1 << 8) - 1); public static final int SECP256K1_FLAGS_TYPE_CONTEXT = (1 << 0); public static final int SECP256K1_FLAGS_TYPE_COMPRESSION = (1 << 1); /** * The higher bits contain the actual data. Do not use directly. */ public static final int SECP256K1_FLAGS_BIT_CONTEXT_VERIFY = (1 << 8); public static final int SECP256K1_FLAGS_BIT_CONTEXT_SIGN = (1 << 9); public static final int SECP256K1_FLAGS_BIT_COMPRESSION = (1 << 8); /** * Flags to pass to secp256k1_context_create, secp256k1_context_preallocated_size, and * secp256k1_context_preallocated_create. */ public static final int SECP256K1_CONTEXT_VERIFY = (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY); public static final int SECP256K1_CONTEXT_SIGN = (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN); public static final int SECP256K1_CONTEXT_NONE = (SECP256K1_FLAGS_TYPE_CONTEXT); /** * Flag to pass to secp256k1_ec_pubkey_serialize. */ public static final int SECP256K1_EC_COMPRESSED = (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION); public static final int SECP256K1_EC_UNCOMPRESSED = (SECP256K1_FLAGS_TYPE_COMPRESSION); /** * A musig2 public nonce is simply two elliptic curve points. */ public static final int SECP256K1_MUSIG_PUBLIC_NONCE_SIZE = 66; /** * A musig2 private nonce is basically two scalars, but should be treated as an opaque blob. */ public static final int SECP256K1_MUSIG_SECRET_NONCE_SIZE = 132; /** * When aggregating public keys, we cache information in an opaque blob (must not be interpreted). */ public static final int SECP256K1_MUSIG_KEYAGG_CACHE_SIZE = 197; /** * When creating partial signatures and aggregating them, session data is kept in an opaque blob (must not be interpreted). */ public static final int SECP256K1_MUSIG_SESSION_SIZE = 133; public static native long secp256k1_context_create(int flags); public static native void secp256k1_context_destroy(long ctx); public static native int secp256k1_ec_seckey_verify(long ctx, byte[] seckey); public static native byte[] secp256k1_ec_pubkey_parse(long ctx, byte[] pubkey); public static native byte[] secp256k1_ec_pubkey_create(long ctx, byte[] seckey); public static native byte[] secp256k1_ecdsa_sign(long ctx, byte[] msg, byte[] seckey); public static native int secp256k1_ecdsa_verify(long ctx, byte[] sig, byte[] msg, byte[] pubkey); public static native int secp256k1_ecdsa_signature_normalize(long ctx, byte[] sigin, byte[] sigout); public static native byte[] secp256k1_ec_privkey_negate(long ctx, byte[] privkey); public static native byte[] secp256k1_ec_pubkey_negate(long ctx, byte[] pubkey); public static native byte[] secp256k1_ec_privkey_tweak_add(long ctx, byte[] seckey, byte[] tweak); public static native byte[] secp256k1_ec_pubkey_tweak_add(long ctx, byte[] pubkey, byte[] tweak); public static native byte[] secp256k1_ec_privkey_tweak_mul(long ctx, byte[] seckey, byte[] tweak); public static native byte[] secp256k1_ec_pubkey_tweak_mul(long ctx, byte[] pubkey, byte[] tweak); public static native byte[] secp256k1_ec_pubkey_combine(long ctx, byte[][] pubkeys); public static native byte[] secp256k1_ecdh(long ctx, byte[] seckey, byte[] pubkey); public static native byte[] secp256k1_ecdsa_recover(long ctx, byte[] sig, byte[] msg32, int recid); public static native byte[] secp256k1_compact_to_der(long ctx, byte[] sig); public static native byte[] secp256k1_schnorrsig_sign(long ctx, byte[] msg, byte[] seckey, byte[] aux_rand32); public static native int secp256k1_schnorrsig_verify(long ctx, byte[] sig, byte[] msg, byte[] pubkey); public static native byte[] secp256k1_musig_nonce_gen(long ctx, byte[] session_id32, byte[] seckey, byte[] pubkey, byte[] msg32, byte[] keyagg_cache, byte[] extra_input32); public static native byte[] secp256k1_musig_nonce_agg(long ctx, byte[][] nonces); public static native byte[] secp256k1_musig_pubkey_agg(long ctx, byte[][] pubkeys, byte[] keyagg_cache); public static native byte[] secp256k1_musig_pubkey_ec_tweak_add(long ctx, byte[] keyagg_cache, byte[] tweak32); public static native byte[] secp256k1_musig_pubkey_xonly_tweak_add(long ctx, byte[] keyagg_cache, byte[] tweak32); public static native byte[] secp256k1_musig_nonce_process(long ctx, byte[] aggnonce, byte[] msg32, byte[] keyagg_cache); public static native byte[] secp256k1_musig_partial_sign(long ctx, byte[] secnonce, byte[] privkey, byte[] keyagg_cache, byte[] session); public static native int secp256k1_musig_partial_sig_verify(long ctx, byte[] psig, byte[] pubnonce, byte[] pubkey, byte[] keyagg_cache, byte[] session); public static native byte[] secp256k1_musig_partial_sig_agg(long ctx, byte[] session, byte[][] psigs); /** * Creates key shares * * To generate a key, each participant generates a share for each other * participant. For example, in the case of 2 particpants, Alice and Bob, they * each generate 2 shares, distribute 1 share to each other using a secure * channel, and keep 1 for themselves. * * Each participant must transmit shares over secure channels to each other * participant. * * Each call to this function must have a UNIQUE and uniformly RANDOM seed32 * that must NOT BE REUSED in subsequent calls to this function and * must be KEPT SECRET (even from other participants). * * @param ctx pointer to a context object (not secp256k1_context_static) * @param seed32 32-byte random seed as explained above. Must be unique to this call to secp256k1_frost_shares_gen * and must be uniformly random. * @param threshold the minimum number of signers required to produce a signature * @param total_signers the total number of participants * @param ids33 array of 33-byte participant IDs * * @return * [0] shares: pointer to the key shares * [1] vss_commitment: pointer to the VSS commitment * [2] pok64: pointer to the proof of knowledge */ public static native byte[][][] secp256k1_frost_shares_gen(long ctx, byte[] seed32, int threshold, int total_signers, byte[][] ids33); /** * Aggregates shares * * As part of the key generation protocol, each participant receives a share * from each participant, including a share they "receive" from themselves. * This function verifies those shares against their VSS commitments, * aggregates the shares, and then aggregates the commitments to each * participant's first polynomial coefficient to derive the aggregate public * key. * * If this function returns an error, `secp256k1_frost_share_verify` can be * called on each share to determine which participants submitted faulty * shares. * * @param ctx pointer to a context object (not secp256k1_context_static) * @param shares all key generation shares for the partcipant's index * @param vss_commitments coefficient commitments of all participants ordered by the x-only pubkeys of the participants * @param totalShareCount the total number of shares * @param threshold the minimum number of shares required to produce a signature * @param id33 the 33-byte ID of the participant whose shares are being aggregated * * @return * [0] agg_share: the aggregated share * [1] agg_pk: the aggregated x-only public key */ public static native byte[][] secp256k1_frost_share_agg(long ctx, byte[][] shares, byte[][][] vss_commitments, int totalShareCount, int threshold, byte[] id33); /** * Verifies a share received during a key generation session * * The signature is verified against the VSS commitment received with the * share. This is only useful for purposes of determining which share(s) are * invalid if share_agg returns an error. * * @param ctx pointer to a context object (not secp256k1_context_static) * @param threshold the minimum number of signers required to produce a signature * @param id33 the 33-byte participant ID of the share recipient * @param share pointer to a key generation share * @param vss_commitment the VSS commitment associated with the share * * @return 0 if the arguments are invalid or the share does not verify, 1 otherwise */ public static native int secp256k1_frost_share_verify(long ctx, int threshold, byte[] id33, byte[] share, byte[][] vss_commitment); /** * Computes a public verification share used for verifying partial signatures * * @param ctx pointer to a context object (not secp256k1_context_static) * @param threshold the minimum number of signers required to produce a signature * @param id33 the 33-byte participant ID of the participant whose partial signature will be verified with * the pubshare * @param vss_commitments coefficient commitments of all participants * @param totalSignersCount the total number of participants * * @return pubshare: pointer to a struct to store the public verification share */ public static native byte[] secp256k1_frost_compute_pubshare(long ctx, int threshold, byte[] id33, byte[][][] vss_commitments, int totalSignersCount); /** * Initializes a tweak cache used for applying tweaks to a FROST key * * @param ctx pointer to a context object (not secp256k1_context_static) * @param public_key the aggregated x-only public key that is the output of `secp256k1_frost_share_agg` * * @return tweak_cache: pointer to a frost_tweak_cache struct that is required for key tweaking */ public static native byte[] secp256k1_frost_pubkey_tweak(long ctx, byte[] public_key); /** * Apply ordinary "EC" tweaking to a public key in a given tweak_cache by * adding the generator multiplied with `tweak32` to it. This is useful for * deriving child keys from an aggregate public key via BIP32. * * The tweaking method is the same as `secp256k1_ec_pubkey_tweak_add`. So after * the following pseudocode buf and buf2 have identical contents (absent * earlier failures). * * secp256k1_frost_share_agg(..., xonly_agg_pk, ...) * secp256k1_frost_pubkey_tweak(..., tweak_cache, xonly_agg_pk) * secp256k1_frost_pubkey_ec_tweak_add(..., output_pk, tweak_cache, tweak32) * secp256k1_ec_pubkey_serialize(..., buf, output_pk) * secp256k1_frost_pubkey_get(..., ec_agg_pk, xonly_agg_pk) * secp256k1_ec_pubkey_tweak_add(..., ec_agg_pk, tweak32) * secp256k1_ec_pubkey_serialize(..., buf2, ec_agg_pk) * * This function is required if you want to _sign_ for a tweaked aggregate key. * On the other hand, if you are only computing a public key, but not intending * to create a signature for it, you can just use * `secp256k1_ec_pubkey_tweak_add`. * * @param ctx pointer to a context object (not secp256k1_context_static) * @param tweakCache pointer to a `frost_tweak_cache` struct initialized by `frost_pubkey_tweak` * @param tweak32 pointer to a 32-byte tweak. If the tweak is invalid according to `secp256k1_ec_seckey_verify`, * this function returns 0. For uniformly random 32-byte arrays the chance of being invalid * is negligible (around 1 in 2^128). * * @return output_pubkey: pointer to a public key to store the result. Will be set * to an invalid value if this function returns 0. If you * do not need it, this arg can be NULL. */ public static native byte[] secp256k1_frost_pubkey_ec_tweak_add(long ctx, byte[] tweakCache, byte[] tweak32); /** * Apply x-only tweaking to a public key in a given tweak_cache by adding the * generator multiplied with `tweak32` to it. This is useful for creating * Taproot outputs. * * The tweaking method is the same as `secp256k1_xonly_pubkey_tweak_add`. So in * the following pseudocode xonly_pubkey_tweak_add_check (absent earlier * failures) returns 1. * * secp256k1_frost_share_agg(..., agg_pk, ...) * secp256k1_frost_pubkey_tweak(..., tweak_cache, agg_pk) * secp256k1_frost_pubkey_xonly_tweak_add(..., output_pk, tweak_cache, tweak32) * secp256k1_xonly_pubkey_serialize(..., buf, output_pk) * secp256k1_xonly_pubkey_tweak_add_check(..., buf, ..., agg_pk, tweak32) * * This function is required if you want to _sign_ for a tweaked aggregate key. * On the other hand, if you are only computing a public key, but not intending * to create a signature for it, you can just use * `secp256k1_xonly_pubkey_tweak_add`. * * @param ctx pointer to a context object (not secp256k1_context_static) * @param tweakCache pointer to a `frost_tweak_cache` struct initialized by `frost_pubkey_tweak` * @param tweak32 pointer to a 32-byte tweak. If the tweak is invalid according to secp256k1_ec_seckey_verify, * this function returns 0. For uniformly random 32-byte arrays the * chance of being invalid is negligible (around 1 in 2^128). * * @return * [0] output_pubkey: pointer to a public key to store the result. Will be set to an invalid value if this * function returns 0. If you do not need it, this arg can be NULL. * [1] tweak_cache: pointer to a `frost_tweak_cache` struct initialized by `frost_pubkey_tweak` */ public static native byte[][] secp256k1_frost_pubkey_xonly_tweak_add(long ctx, byte[] tweakCache, byte[] tweak32); /** * Starts a signing session by generating a nonce * * This function outputs a secret nonce that will be required for signing and a * corresponding public nonce that is intended to be sent to other signers. * * FROST, like MuSig, differs from regular Schnorr signing in that * implementers _must_ take special care to not reuse a nonce. This can be * ensured by following these rules: * * 1. Each call to this function must have a UNIQUE session_id32 that must NOT BE * REUSED in subsequent calls to this function. * If you do not provide a seckey, session_id32 _must_ be UNIFORMLY RANDOM * AND KEPT SECRET (even from other signers). If you do provide a seckey, * session_id32 can instead be a counter (that must never repeat!). However, * it is recommended to always choose session_id32 uniformly at random. * 2. If you already know the seckey, message or aggregate public key, they * can be optionally provided to derive the nonce and increase * misuse-resistance. The extra_input32 argument can be used to provide * additional data that does not repeat in normal scenarios, such as the * current time. * 3. Avoid copying (or serializing) the secnonce. This reduces the possibility * that it is used more than once for signing. * * Remember that nonce reuse will leak the secret key! * Note that using the same agg_share for multiple FROST sessions is fine. * * @param ctx pointer to a context object (not secp256k1_context_static) * @param sessionId32 a 32-byte session_id32 as explained above. Must be unique to this call to * secp256k1_frost_nonce_gen and must be uniformly random unless you really know what you * are doing. * @param share the aggregated share that will later be used for signing, if already known (can be NULL) * @param msg32 the 32-byte message that will later be signed, if already known (can be NULL) * @param publicKey the FROST-aggregated public key (can be NULL) * @param extraInput32 an optional 32-byte array that is input to the nonce derivation function (can be NULL) * @return * [0] secnonce: pointer to a structure to store the secret nonce * [1] pubnonce: pointer to a structure to store the public nonce */ public static native byte[][] secp256k1_frost_nonce_gen(long ctx, byte[] sessionId32, byte[] share, byte[] msg32, byte[] publicKey, byte[] extraInput32); /** * Takes the public nonces of all signers and computes a session that is * required for signing and verification of partial signatures. The participant * IDs can be sorted before combining, but the corresponding pubnonces must be * resorted as well. All signers must use the same sorting of pubnonces, * otherwise signing will fail. * * @param ctx pointer to a context object (not secp256k1_context_static) * @param pubnonces array of pointers to public nonces sent by the signers * @param msg32 the 32-byte message to sign * @param publicKey the FROST-aggregated public key * @param id33 the 33-byte ID of the participant who will use the session for signing * @param ids33 array of the 33-byte participant IDs of the signers * @param tweakCache pointer to frost_tweak_cache struct (can be NULL) * @param adaptor optional pointer to an adaptor point encoded as a public key if this signing session is part * of an adaptor signature protocol (can be NULL) * * @return session: pointer to a struct to store the session */ public static native byte[] secp256k1_frost_nonce_process(long ctx, byte[][] pubnonces, byte[] msg32, byte[] publicKey, byte[] id33, byte[][] ids33, byte[] tweakCache, byte[] adaptor); /** * Produces a partial signature * * This function overwrites the given secnonce with zeros and will abort if given a * secnonce that is all zeros. This is a best effort attempt to protect against nonce * reuse. However, this is of course easily defeated if the secnonce has been * copied (or serialized). Remember that nonce reuse will leak the secret key! * * @param ctx pointer to a context object (not secp256k1_context_static) * @param secnonce (IS ALSO OUTPUT)pointer to the secnonce struct created in frost_nonce_gen that has been never used in a * partial_sign call before * @param share the aggregated share * @param session pointer to the session that was created with frost_nonce_process * @param tweak_cache pointer to frost_tweak_cache struct (can be NULL) * * @return * partial_sig: pointer to struct to store the partial signature * TODO: [1] secnonce: pointer to the secnonce struct created in frost_nonce_gen that has been never used in a * partial_sign call before * */ public static native byte[] secp256k1_frost_partial_sign(long ctx, byte[] secnonce, byte[] share, byte[] session, byte[] tweak_cache); /** * Verifies an individual signer's partial signature * * The signature is verified for a specific signing session. In order to avoid * accidentally verifying a signature from a different or non-existing signing * session, you must ensure the following: * 1. The `tweak_cache` argument is identical to the one used to create the * `session` with `frost_nonce_process`. * 2. The `pubshare` argument must be the output of * `secp256k1_frost_compute_pubshare` for the signer's ID. * 3. The `pubnonce` argument must be identical to the one sent by the * signer and used to create the `session` with `frost_nonce_process`. * * This function can be used to assign blame for a failed signature. * * @param ctx pointer to a context object (not secp256k1_context_static) * @param partialSig pointer to partial signature to verify, sent by the signer associated with `pubnonce` and `pubkey` * @param publicNonce public nonce of the signer in the signing session * @param publicShare public verification share of the signer in the signing session that is the output of * `secp256k1_frost_compute_pubshare` * @param session pointer to the session that was created with `frost_nonce_process` * @param tweakCache pointer to frost_tweak_cache struct (can be NULL) * * @return 0 if the arguments are invalid or the partial signature does not verify, 1 otherwise */ public static native int secp256k1_frost_partial_sig_verify(long ctx, byte[] partialSig, byte[] publicNonce, byte[] publicShare, byte[] session, byte[] tweakCache); /** * Aggregates partial signatures * * @param ctx pointer to a context object (not secp256k1_context_static) * @param session pointer to the session that was created with frost_nonce_process * @param partialSignatures array of pointers to partial signatures to aggregate * @param n_sigs number of elements in the partial_sigs array. Must be greater than 0. * * @return sig64: complete (but possibly invalid) Schnorr signature */ public static native byte[] secp256k1_frost_partial_sig_agg(long ctx, byte[] session, byte[][] partialSignatures, int n_sigs); }