grin_core/libtx/
aggsig.rs

1// Copyright 2021 The Grin Developers
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Aggregated Signature functions used in the creation of Grin transactions.
16//! This module interfaces into the underlying
17//! [Rust Aggsig library](https://github.com/mimblewimble/rust-secp256k1-zkp/blob/master/src/aggsig.rs)
18
19use crate::libtx::error::Error;
20use keychain::{BlindingFactor, Identifier, Keychain, SwitchCommitmentType};
21use util::secp::key::{PublicKey, SecretKey};
22use util::secp::pedersen::Commitment;
23use util::secp::{self, aggsig, Message, Secp256k1, Signature};
24
25/// Creates a new secure nonce (as a SecretKey), guaranteed to be usable during
26/// aggsig creation.
27///
28/// # Arguments
29///
30/// * `secp` - A Secp256k1 Context initialized for Signing
31///
32/// # Example
33///
34/// ```
35/// # extern crate grin_core as core;
36/// use core::libtx::aggsig;
37/// use util::secp::{ContextFlag, Secp256k1};
38/// let secp = Secp256k1::with_caps(ContextFlag::SignOnly);
39/// let secret_nonce = aggsig::create_secnonce(&secp).unwrap();
40/// ```
41/// # Remarks
42///
43/// The resulting SecretKey is guaranteed to have Jacobi symbol 1.
44
45pub fn create_secnonce(secp: &Secp256k1) -> Result<SecretKey, Error> {
46	let nonce = aggsig::export_secnonce_single(secp)?;
47	Ok(nonce)
48}
49
50/// Calculates a partial signature given the signer's secure key,
51/// the sum of all public nonces and (optionally) the sum of all public keys.
52///
53/// # Arguments
54///
55/// * `secp` - A Secp256k1 Context initialized for Signing
56/// * `sec_key` - The signer's secret key
57/// * `sec_nonce` - The signer's secret nonce (the public version of which
58/// was added to the `nonce_sum` total)
59/// * `nonce_sum` - The sum of the public nonces of all signers participating
60/// in the full signature. This value is encoded in e.
61/// * `pubkey_sum` - (Optional) The sum of the public keys of all signers participating
62/// in the full signature. If included, this value is encoded in e.
63/// * `msg` - The message to sign.
64///
65/// # Example
66///
67/// ```
68/// # extern crate grin_core as core;
69/// # extern crate rand;
70/// use rand::thread_rng;
71/// use core::libtx::aggsig;
72/// use util::secp::key::{PublicKey, SecretKey};
73/// use util::secp::{ContextFlag, Secp256k1, Message};
74///
75/// let secp = Secp256k1::with_caps(ContextFlag::SignOnly);
76/// let secret_nonce = aggsig::create_secnonce(&secp).unwrap();
77/// let secret_key = SecretKey::new(&secp, &mut thread_rng());
78/// let pub_nonce_sum = PublicKey::from_secret_key(&secp, &secret_nonce).unwrap();
79/// // ... Add all other participating nonces
80/// let pub_key_sum = PublicKey::from_secret_key(&secp, &secret_key).unwrap();
81/// // ... Add all other participating keys
82/// let mut msg_bytes = [0; 32];
83/// // ... Encode message
84/// let message = Message::from_slice(&msg_bytes).unwrap();
85/// let sig_part = aggsig::calculate_partial_sig(
86///     &secp,
87///     &secret_key,
88///     &secret_nonce,
89///     &pub_nonce_sum,
90///     Some(&pub_key_sum),
91///     &message,
92///).unwrap();
93/// ```
94
95pub fn calculate_partial_sig(
96	secp: &Secp256k1,
97	sec_key: &SecretKey,
98	sec_nonce: &SecretKey,
99	nonce_sum: &PublicKey,
100	pubkey_sum: Option<&PublicKey>,
101	msg: &secp::Message,
102) -> Result<Signature, Error> {
103	//Now calculate signature using message M=fee, nonce in e=nonce_sum
104	let sig = aggsig::sign_single(
105		secp,
106		&msg,
107		sec_key,
108		Some(sec_nonce),
109		None,
110		Some(nonce_sum),
111		pubkey_sum,
112		Some(nonce_sum),
113	)?;
114	Ok(sig)
115}
116
117/// Verifies a partial signature from a public key. All nonce and public
118/// key sum values must be identical to those provided in the call to
119/// [`calculate_partial_sig`](fn.calculate_partial_sig.html). Returns
120/// `Result::Ok` if the signature is valid, or a Signature
121/// [ErrorKind](../enum.ErrorKind.html) otherwise
122///
123/// # Arguments
124///
125/// * `secp` - A Secp256k1 Context initialized for Validation
126/// * `sig` - The signature to validate, created via a call to
127/// [`calculate_partial_sig`](fn.calculate_partial_sig.html)
128/// * `pub_nonce_sum` - The sum of the public nonces of all signers participating
129/// in the full signature. This value is encoded in e.
130/// * `pubkey` - Corresponding Public Key of the private key used to sign the message.
131/// * `pubkey_sum` - (Optional) The sum of the public keys of all signers participating
132/// in the full signature. If included, this value is encoded in e.
133/// * `msg` - The message to verify.
134///
135/// # Example
136///
137/// ```
138/// # extern crate grin_core as core;
139/// # extern crate rand;
140/// use rand::thread_rng;
141/// use core::libtx::aggsig;
142/// use util::secp::key::{PublicKey, SecretKey};
143/// use util::secp::{ContextFlag, Secp256k1, Message};
144///
145/// let secp = Secp256k1::with_caps(ContextFlag::Full);
146/// let secret_nonce = aggsig::create_secnonce(&secp).unwrap();
147/// let secret_key = SecretKey::new(&secp, &mut thread_rng());
148/// let pub_nonce_sum = PublicKey::from_secret_key(&secp, &secret_nonce).unwrap();
149/// // ... Add all other participating nonces
150/// let pub_key_sum = PublicKey::from_secret_key(&secp, &secret_key).unwrap();
151/// // ... Add all other participating keys
152/// let mut msg_bytes = [0; 32];
153/// // ... Encode message
154/// let message = Message::from_slice(&msg_bytes).unwrap();
155/// let sig_part = aggsig::calculate_partial_sig(
156///     &secp,
157///     &secret_key,
158///     &secret_nonce,
159///     &pub_nonce_sum,
160///     Some(&pub_key_sum),
161///     &message,
162///).unwrap();
163///
164/// // Now verify the signature, ensuring the same values used to create
165/// // the signature are provided:
166/// let public_key = PublicKey::from_secret_key(&secp, &secret_key).unwrap();
167///
168/// let result = aggsig::verify_partial_sig(
169///     &secp,
170///     &sig_part,
171///     &pub_nonce_sum,
172///     &public_key,
173///     Some(&pub_key_sum),
174///     &message,
175///);
176/// ```
177
178pub fn verify_partial_sig(
179	secp: &Secp256k1,
180	sig: &Signature,
181	pub_nonce_sum: &PublicKey,
182	pubkey: &PublicKey,
183	pubkey_sum: Option<&PublicKey>,
184	msg: &secp::Message,
185) -> Result<(), Error> {
186	if !verify_single(
187		secp,
188		sig,
189		&msg,
190		Some(&pub_nonce_sum),
191		pubkey,
192		pubkey_sum,
193		true,
194	) {
195		return Err(Error::Signature("Signature validation error".to_string()));
196	}
197	Ok(())
198}
199
200/// Creates a single-signer aggsig signature from a key id. Generally,
201/// this function is used to create transaction kernel signatures for
202/// coinbase outputs.
203/// Returns `Ok(Signature)` if the signature is valid, or a Signature
204/// [ErrorKind](../enum.ErrorKind.html) otherwise
205///
206/// # Arguments
207///
208/// * `secp` - A Secp256k1 Context initialized for Signing
209/// * `k` - The Keychain implementation being used
210/// * `msg` - The message to sign (fee|lockheight).
211/// * `key_id` - The keychain key id corresponding to the private key
212/// with which to sign the message
213/// * `blind_sum` - (Optional) The sum of all blinding factors in the transaction
214/// in the case of a coinbase transaction this will simply be the corresponding
215/// public key.
216///
217/// # Example
218///
219/// ```
220/// # extern crate grin_core as core;
221/// use core::consensus::reward;
222/// use util::secp::key::{PublicKey, SecretKey};
223/// use util::secp::{ContextFlag, Secp256k1};
224/// use core::libtx::{aggsig, proof};
225/// use core::core::transaction::KernelFeatures;
226/// use core::core::{Output, OutputFeatures};
227/// use keychain::{Keychain, ExtKeychain, SwitchCommitmentType};
228/// use std::convert::TryInto;
229///
230/// let secp = Secp256k1::with_caps(ContextFlag::Commit);
231/// let keychain = ExtKeychain::from_random_seed(false).unwrap();
232/// let fees = 10_000;
233/// let value = reward(fees);
234/// let key_id = ExtKeychain::derive_key_id(1, 1, 0, 0, 0);
235/// let switch = SwitchCommitmentType::Regular;
236/// let commit = keychain.commit(value, &key_id, switch).unwrap();
237/// let builder = proof::ProofBuilder::new(&keychain);
238/// let proof = proof::create(&keychain, &builder, value, &key_id, switch, commit, None).unwrap();
239/// let output = Output::new(OutputFeatures::Coinbase, commit, proof);
240/// let height = 20;
241/// let over_commit = secp.commit_value(reward(fees)).unwrap();
242/// let out_commit = output.commitment();
243/// let features = KernelFeatures::HeightLocked{fee: 1.into(), lock_height: height};
244/// let msg = features.kernel_sig_msg().unwrap();
245/// let excess = secp.commit_sum(vec![out_commit], vec![over_commit]).unwrap();
246/// let pubkey = excess.to_pubkey(&secp).unwrap();
247/// let sig = aggsig::sign_from_key_id(&secp, &keychain, &msg, value, &key_id, None, Some(&pubkey)).unwrap();
248/// ```
249
250pub fn sign_from_key_id<K>(
251	secp: &Secp256k1,
252	k: &K,
253	msg: &Message,
254	value: u64,
255	key_id: &Identifier,
256	s_nonce: Option<&SecretKey>,
257	blind_sum: Option<&PublicKey>,
258) -> Result<Signature, Error>
259where
260	K: Keychain,
261{
262	let skey = k.derive_key(value, key_id, SwitchCommitmentType::Regular)?; // TODO: proper support for different switch commitment schemes
263	let sig = aggsig::sign_single(secp, &msg, &skey, s_nonce, None, None, blind_sum, None)?;
264	Ok(sig)
265}
266
267/// Simple verification a single signature from a commitment. The public
268/// key used to verify the signature is derived from the commit.
269/// Returns `Ok(())` if the signature is valid, or a Signature
270/// [ErrorKind](../enum.ErrorKind.html) otherwise
271///
272/// # Arguments
273///
274/// * `secp` - A Secp256k1 Context initialized for Verification
275/// * `sig` - The Signature to verify
276/// * `msg` - The message to sign (fee|lockheight).
277/// * `commit` - The commitment to verify. The actual public key used
278/// during verification is derived from this commit.
279///
280/// # Example
281///
282/// ```
283/// # extern crate grin_core as core;
284/// use core::consensus::reward;
285/// use core::libtx::{aggsig, proof};
286/// use util::secp::key::{PublicKey, SecretKey};
287/// use util::secp::{ContextFlag, Secp256k1};
288/// use core::core::transaction::KernelFeatures;
289/// use core::core::{Output, OutputFeatures};
290/// use keychain::{Keychain, ExtKeychain, SwitchCommitmentType};
291/// use std::convert::TryInto;
292///
293/// // Create signature
294/// let secp = Secp256k1::with_caps(ContextFlag::Commit);
295/// let keychain = ExtKeychain::from_random_seed(false).unwrap();
296/// let fees = 10_000;
297/// let value = reward(fees);
298/// let key_id = ExtKeychain::derive_key_id(1, 1, 0, 0, 0);
299/// let switch = SwitchCommitmentType::Regular;
300/// let commit = keychain.commit(value, &key_id, switch).unwrap();
301/// let builder = proof::ProofBuilder::new(&keychain);
302/// let proof = proof::create(&keychain, &builder, value, &key_id, switch, commit, None).unwrap();
303/// let output = Output::new(OutputFeatures::Coinbase, commit, proof);
304/// let height = 20;
305/// let over_commit = secp.commit_value(reward(fees)).unwrap();
306/// let out_commit = output.commitment();
307/// let features = KernelFeatures::HeightLocked{fee: 1.into(), lock_height: height};
308/// let msg = features.kernel_sig_msg().unwrap();
309/// let excess = secp.commit_sum(vec![out_commit], vec![over_commit]).unwrap();
310/// let pubkey = excess.to_pubkey(&secp).unwrap();
311/// let sig = aggsig::sign_from_key_id(&secp, &keychain, &msg, value, &key_id, None, Some(&pubkey)).unwrap();
312///
313/// // Verify the signature from the excess commit
314/// let sig_verifies =
315///     aggsig::verify_single_from_commit(&keychain.secp(), &sig, &msg, &excess);
316/// assert!(!sig_verifies.is_err());
317/// ```
318
319pub fn verify_single_from_commit(
320	secp: &Secp256k1,
321	sig: &Signature,
322	msg: &Message,
323	commit: &Commitment,
324) -> Result<(), Error> {
325	let pubkey = commit.to_pubkey(secp)?;
326	if !verify_single(secp, sig, msg, None, &pubkey, Some(&pubkey), false) {
327		return Err(Error::Signature("Signature validation error".to_string()));
328	}
329	Ok(())
330}
331
332/// Verifies a completed (summed) signature, which must include the message
333/// and pubkey sum values that are used during signature creation time
334/// to create 'e'
335/// Returns `Ok(())` if the signature is valid, or a Signature
336/// [ErrorKind](../enum.ErrorKind.html) otherwise
337///
338/// # Arguments
339///
340/// * `secp` - A Secp256k1 Context initialized for Verification
341/// * `sig` - The Signature to verify
342/// * `pubkey` - Corresponding Public Key of the private key used to sign the message.
343/// * `pubkey_sum` - (Optional) The sum of the public keys of all signers participating
344/// in the full signature. If included, this value is encoded in e. Must be the same
345/// value as when the signature was created to verify correctly.
346/// * `msg` - The message to verify (fee|lockheight).
347///
348/// # Example
349///
350/// ```
351/// # extern crate grin_core as core;
352/// # extern crate rand;
353/// use rand::thread_rng;
354/// use core::libtx::aggsig;
355/// use util::secp::key::{PublicKey, SecretKey};
356/// use util::secp::{ContextFlag, Secp256k1, Message};
357///
358/// let secp = Secp256k1::with_caps(ContextFlag::Full);
359/// let secret_nonce = aggsig::create_secnonce(&secp).unwrap();
360/// let secret_key = SecretKey::new(&secp, &mut thread_rng());
361/// let pub_nonce_sum = PublicKey::from_secret_key(&secp, &secret_nonce).unwrap();
362/// // ... Add all other participating nonces
363/// let pub_key_sum = PublicKey::from_secret_key(&secp, &secret_key).unwrap();
364/// // ... Add all other participating keys
365/// let mut msg_bytes = [0; 32];
366/// // ... Encode message
367/// let message = Message::from_slice(&msg_bytes).unwrap();
368/// let sig_part = aggsig::calculate_partial_sig(
369///     &secp,
370///     &secret_key,
371///     &secret_nonce,
372///     &pub_nonce_sum,
373///     Some(&pub_key_sum),
374///     &message,
375/// ).unwrap();
376/// // ... Verify above, once all signatures have been added together
377/// let sig_verifies = aggsig::verify_completed_sig(
378///     &secp,
379///     &sig_part,
380///     &pub_key_sum,
381///     Some(&pub_key_sum),
382///     &message,
383///     );
384/// assert!(!sig_verifies.is_err());
385/// ```
386
387pub fn verify_completed_sig(
388	secp: &Secp256k1,
389	sig: &Signature,
390	pubkey: &PublicKey,
391	pubkey_sum: Option<&PublicKey>,
392	msg: &secp::Message,
393) -> Result<(), Error> {
394	if !verify_single(secp, sig, msg, None, pubkey, pubkey_sum, true) {
395		return Err(Error::Signature("Signature validation error".to_string()));
396	}
397	Ok(())
398}
399
400/// Adds signatures
401pub fn add_signatures(
402	secp: &Secp256k1,
403	part_sigs: Vec<&Signature>,
404	nonce_sum: &PublicKey,
405) -> Result<Signature, Error> {
406	// Add public nonces kR*G + kS*G
407	let sig = aggsig::add_signatures_single(&secp, part_sigs, &nonce_sum)?;
408	Ok(sig)
409}
410
411/// Subtract a partial signature from a completed signature
412/// see https://github.com/mimblewimble/rust-secp256k1-zkp/blob/e9e4f09bd0c85da914774a52219457ba10ac3e57/src/aggsig.rs#L267
413pub fn subtract_signature(
414	secp: &Secp256k1,
415	sig: &Signature,
416	partial_sig: &Signature,
417) -> Result<(Signature, Option<Signature>), Error> {
418	let sig = aggsig::subtract_partial_signature(secp, sig, partial_sig)?;
419	Ok(sig)
420}
421/// Just a simple sig, creates its own nonce if not provided
422pub fn sign_single(
423	secp: &Secp256k1,
424	msg: &Message,
425	skey: &SecretKey,
426	snonce: Option<&SecretKey>,
427	pubkey_sum: Option<&PublicKey>,
428) -> Result<Signature, Error> {
429	let sig = aggsig::sign_single(secp, &msg, skey, snonce, None, None, pubkey_sum, None)?;
430	Ok(sig)
431}
432
433/// Verifies an aggsig signature
434pub fn verify_single(
435	secp: &Secp256k1,
436	sig: &Signature,
437	msg: &Message,
438	pubnonce: Option<&PublicKey>,
439	pubkey: &PublicKey,
440	pubkey_sum: Option<&PublicKey>,
441	is_partial: bool,
442) -> bool {
443	aggsig::verify_single(
444		secp, sig, msg, pubnonce, pubkey, pubkey_sum, None, is_partial,
445	)
446}
447
448/// Verify a batch of signatures.
449pub fn verify_batch(
450	secp: &Secp256k1,
451	sigs: &Vec<Signature>,
452	msgs: &Vec<Message>,
453	pubkeys: &Vec<PublicKey>,
454) -> bool {
455	aggsig::verify_batch(secp, sigs, msgs, pubkeys)
456}
457
458/// Just a simple sig, creates its own nonce, etc
459pub fn sign_with_blinding(
460	secp: &Secp256k1,
461	msg: &Message,
462	blinding: &BlindingFactor,
463	pubkey_sum: Option<&PublicKey>,
464) -> Result<Signature, Error> {
465	let skey = &blinding.secret_key(&secp)?;
466	let sig = aggsig::sign_single(secp, &msg, skey, None, None, None, pubkey_sum, None)?;
467	Ok(sig)
468}