diff --git a/jni/src/main/java/fr/acinq/secp256k1/Secp256k1CFunctions.java b/jni/src/main/java/fr/acinq/secp256k1/Secp256k1CFunctions.java index 42ececc..7ae8da8 100644 --- a/jni/src/main/java/fr/acinq/secp256k1/Secp256k1CFunctions.java +++ b/jni/src/main/java/fr/acinq/secp256k1/Secp256k1CFunctions.java @@ -107,26 +107,278 @@ public class Secp256k1CFunctions { public static native byte[] secp256k1_musig_partial_sig_agg(long ctx, byte[] session, byte[][] psigs); - public static native byte[][][] secp256k1_frost_shares_gen(long ctx, byte[] pok64, byte[] seed32, int threshold, int total_signers, byte[][] ids33); + /** + * 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 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_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 + * 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); public static native byte[] secp256k1_frost_partial_sig_aggregate(long ctx, byte[] session, byte[][] partialSignatures);