spark_cryptography/
secp.rs

1use bitcoin::secp256k1::{All, Error as Secp256k1Error, PublicKey, Secp256k1, SecretKey};
2use rand::rngs::OsRng;
3
4use crate::error::SparkCryptographyError;
5
6/// Subtracts the rhs public key from the lhs public key
7///
8/// Input keys must be 33-byte compressed secp256k1 public keys
9///
10/// # Arguments
11///
12/// * `pk1` - The first public key
13/// * `pk2` - The second public key
14///
15/// # Returns
16/// The result of subtracting the second public key from the first
17///
18/// # Errors
19/// - [`SparkCryptographyError::SecpError`] if the keys are not valid.
20///
21/// # Examples
22/// ```
23/// use bitcoin::secp256k1::{PublicKey, Secp256k1};
24/// use spark_cryptography::secp::subtract_public_keys;
25/// use bitcoin::secp256k1::rand::rngs::OsRng;
26///
27/// let secp = Secp256k1::new();
28/// let (_, pk1) = secp.generate_keypair(&mut OsRng);
29/// let (_, pk2) = secp.generate_keypair(&mut OsRng);
30/// let result = subtract_public_keys(&pk1, &pk2).unwrap();
31/// ```
32#[cfg_attr(feature = "telemetry", tracing::instrument(skip_all))]
33pub fn subtract_public_keys(
34    pk1: &PublicKey,
35    pk2: &PublicKey,
36) -> Result<PublicKey, SparkCryptographyError> {
37    let secp = Secp256k1::new();
38
39    // Negate the second key and add
40    let negated = pk2.negate(&secp);
41    Ok(pk1.combine(&negated)?)
42}
43
44/// Subtracts the rhs secret key from the lhs secret key
45///
46/// Input keys must be 32 bytes
47///
48/// # Arguments
49///
50/// * `sk1` - The first secret key
51/// * `sk2` - The second secret key
52///
53/// # Returns
54/// The result of subtracting the second secret key from the first
55///
56/// # Errors
57/// - [`Secp256k1Error`] if the keys are not valid.
58///
59/// # Examples
60/// ```
61/// use bitcoin::secp256k1::{SecretKey, Secp256k1};
62/// use spark_cryptography::secp::subtract_secret_keys;
63/// use bitcoin::secp256k1::rand::rngs::OsRng;
64///
65/// let secp = Secp256k1::new();
66/// let (sk1, _) = secp.generate_keypair(&mut OsRng);
67/// let (sk2, _) = secp.generate_keypair(&mut OsRng);
68/// let result = subtract_secret_keys(&sk1, &sk2).unwrap();
69/// ```
70#[cfg_attr(feature = "telemetry", tracing::instrument(skip_all))]
71pub fn subtract_secret_keys(sk1: &SecretKey, sk2: &SecretKey) -> Result<SecretKey, Secp256k1Error> {
72    // Negate the second key and add
73    let negated = sk2.negate();
74    sk1.add_tweak(&negated.into())
75}
76
77/// Generates a new keypair
78///
79/// # Arguments
80///
81/// * `secp` - The secp256k1 context
82///
83/// # Returns
84/// A tuple of the secret key and public key
85///
86/// # Errors
87/// - [`Secp256k1Error`] if the keys are not valid.
88///
89/// # Examples
90/// ```
91/// use bitcoin::secp256k1::{Secp256k1, All};
92/// use spark_cryptography::secp::generate_keypair;
93///
94/// let secp = Secp256k1::new();
95/// let (sk, pk) = generate_keypair(&secp);
96/// ```
97#[cfg_attr(feature = "telemetry", tracing::instrument(skip_all))]
98pub fn generate_keypair(secp: &Secp256k1<All>) -> (SecretKey, PublicKey) {
99    secp.generate_keypair(&mut OsRng)
100}