├── .gitignore ├── fuzz ├── .gitignore ├── Cargo.toml └── fuzz_targets │ ├── fuzz_ecdh.rs │ ├── fuzz_sign.rs │ └── fuzz_aggsig.rs ├── Makefile ├── .gitmodules ├── FORK ├── README.md ├── Cargo.toml ├── azure-pipelines.yml ├── src ├── ecdh.rs ├── constants.rs ├── macros.rs ├── aggsig.rs ├── ffi.rs ├── key.rs └── lib.rs └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /fuzz/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | target 3 | corpus 4 | artifacts 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | test: 2 | cargo test 3 | 4 | build: 5 | cargo build 6 | 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "depend/secp256k1-zkp"] 2 | path = depend/secp256k1-zkp 3 | url = https://github.com/mimblewimble/secp256k1-zkp 4 | -------------------------------------------------------------------------------- /FORK: -------------------------------------------------------------------------------- 1 | Forked from https://github.com/apoelstra/rust-secp256k1 2 | 3 | The forked repository is tracked into a branch called 'vendor'. The master 4 | branch of this repository contains our modifications on top of that. To 5 | update from upstream: 6 | 7 | git remote add upstream https://github.com/apoelstra/rust-secp256k1 8 | git checkout vendor 9 | git pull upstream secp256k1-zkp 10 | git push origin vendor 11 | git checkout master 12 | git merge vendor 13 | git push 14 | 15 | -------------------------------------------------------------------------------- /fuzz/Cargo.toml: -------------------------------------------------------------------------------- 1 | 2 | [package] 3 | name = "grin_secp256k1zkp-fuzz" 4 | version = "0.0.0" 5 | authors = ["Automatically generated"] 6 | publish = false 7 | edition = "2018" 8 | 9 | [package.metadata] 10 | cargo-fuzz = true 11 | 12 | [dependencies] 13 | libfuzzer-sys = "0.3" 14 | 15 | [dependencies.grin_secp256k1zkp] 16 | path = ".." 17 | 18 | # Prevent this from interfering with workspaces 19 | [workspace] 20 | members = ["."] 21 | 22 | [[bin]] 23 | name = "fuzz_sign" 24 | path = "fuzz_targets/fuzz_sign.rs" 25 | 26 | [[bin]] 27 | name = "fuzz_ecdh" 28 | path = "fuzz_targets/fuzz_ecdh.rs" 29 | 30 | [[bin]] 31 | name = "fuzz_aggsig" 32 | path = "fuzz_targets/fuzz_aggsig.rs" 33 | -------------------------------------------------------------------------------- /fuzz/fuzz_targets/fuzz_ecdh.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | use libfuzzer_sys::fuzz_target; 3 | 4 | extern crate secp256k1zkp; 5 | 6 | use secp256k1zkp::{Secp256k1, PublicKey, SecretKey}; 7 | use secp256k1zkp::ecdh::SharedSecret; 8 | 9 | fuzz_target!(|data: &[u8]| { 10 | if data.len() < 32 { 11 | return (); 12 | } 13 | 14 | let s = Secp256k1::new(); 15 | 16 | if let Ok(sk) = SecretKey::from_slice(&s, &data[..32]) { 17 | match PublicKey::from_secret_key(&s, &sk) { 18 | Ok(pk) => { let _ = SharedSecret::new(&s, &pk, &sk); () }, 19 | Err(e) => panic!("cannot create public key from secret: {}", e), 20 | } 21 | } 22 | }); 23 | 24 | -------------------------------------------------------------------------------- /fuzz/fuzz_targets/fuzz_sign.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | use libfuzzer_sys::fuzz_target; 3 | 4 | extern crate secp256k1zkp; 5 | 6 | use secp256k1zkp::{Message, Secp256k1, PublicKey, SecretKey}; 7 | 8 | fuzz_target!(|data: &[u8]| { 9 | if data.len() < 64 { 10 | return (); 11 | } 12 | 13 | let s = Secp256k1::new(); 14 | 15 | let msg = Message::from_slice(&data[..32]).unwrap(); 16 | 17 | if let Ok(sk) = SecretKey::from_slice(&s, &data[32..64]) { 18 | match s.sign(&msg, &sk) { 19 | Ok(sig) => { 20 | match PublicKey::from_secret_key(&s, &sk) { 21 | Ok(pk) => s.verify(&msg, &sig, &pk).unwrap(), 22 | Err(e) => panic!("cannot create public key from secret: {}", e), 23 | } 24 | } 25 | Err(e) => panic!("error creating signature: {}", e), 26 | } 27 | } 28 | }); 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://dev.azure.com/mimblewimble/rust-secp256k1-zkp/_apis/build/status/mimblewimble.rust-secp256k1-zkp?branchName=master)](https://dev.azure.com/mimblewimble/rust-secp256k1-zkp/_build/latest?definitionId=4&branchName=master) 2 | 3 | ### rust-secp256k1 4 | 5 | `rust-secp256k1` is a wrapper around [libsecp256k1](https://github.com/bitcoin/secp256k1), 6 | a C library by Peter Wuille for producing ECDSA signatures using the SECG curve 7 | `secp256k1`. This library 8 | * exposes type-safe Rust bindings for all `libsecp256k1` functions 9 | * implements key generation 10 | * implements deterministic nonce generation via RFC6979 11 | * implements many unit tests, adding to those already present in `libsecp256k1` 12 | * makes no allocations (except in unit tests) for efficiency and use in freestanding implementations 13 | 14 | [Full documentation](https://www.wpsoftware.net/rustdoc/secp256k1/) 15 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | 3 | name = "grin_secp256k1zkp" 4 | version = "0.7.14" 5 | authors = [ "Grin Developers ", 6 | "Dawid Ciężarkiewicz ", 7 | "Andrew Poelstra " ] 8 | license = "CC0-1.0" 9 | homepage = "https://grin.mw" 10 | repository = "https://github.com/mimblewimble/rust-secp256k1-zkp/" 11 | description = "Grin's fork with Zero-Knowledge extensions of Rust bindings for Pieter Wuille's `libsecp256k1` library. Implements ECDSA for the SECG elliptic curve group secp256k1 and related utilities." 12 | keywords = [ "crypto", "secp256k1", "grin", "bitcoin", "zero-knowledge" ] 13 | readme = "README.md" 14 | edition = "2018" 15 | 16 | build = "build.rs" 17 | [build-dependencies] 18 | cc = "1.0" 19 | 20 | [lib] 21 | name = "secp256k1zkp" 22 | path = "src/lib.rs" 23 | 24 | [features] 25 | unstable = [] 26 | default = [] 27 | bullet-proof-sizing = [] 28 | dev = ["clippy"] 29 | 30 | [dependencies] 31 | arrayvec = "0.7" 32 | clippy = {version = "0.0", optional = true} 33 | rand = "0.5" 34 | libc = "0.2" 35 | serde = { version = "1.0", features = ["derive"] } 36 | serde_json = "1.0" 37 | zeroize = { version = "1.1", features = ["zeroize_derive"] } 38 | 39 | [dev-dependencies] 40 | chrono = "0.4.5" 41 | rand_core = "0.2" 42 | -------------------------------------------------------------------------------- /fuzz/fuzz_targets/fuzz_aggsig.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | use libfuzzer_sys::fuzz_target; 3 | 4 | extern crate secp256k1zkp; 5 | 6 | use secp256k1zkp::{ 7 | AggSigPartialSignature, 8 | ContextFlag, 9 | Message, 10 | Secp256k1, 11 | PublicKey, 12 | SecretKey 13 | }; 14 | 15 | use secp256k1zkp::aggsig::AggSigContext; 16 | use secp256k1zkp::rand::{Rng, thread_rng}; 17 | 18 | fuzz_target!(|data: &[u8]| { 19 | let numkeys = 3; 20 | if data.len() < (numkeys + 1) * 32 { 21 | return (); 22 | } 23 | 24 | let mut rng = thread_rng(); 25 | let secp = Secp256k1::with_caps(ContextFlag::Full); 26 | let mut pks: Vec = Vec::with_capacity(numkeys); 27 | let mut keypairs: Vec<(SecretKey, PublicKey)> = Vec::with_capacity(numkeys); 28 | 29 | for i in 0..numkeys { 30 | if let Ok(sk) = SecretKey::from_slice(&secp, &data[i*32..(i+1)*32]) { 31 | let pk = PublicKey::from_secret_key(&secp, &sk).unwrap(); 32 | pks.push(pk.clone()); 33 | keypairs.push((sk, pk)); 34 | } else { 35 | let (sk, pk) = secp.generate_keypair(&mut rng).unwrap(); 36 | pks.push(pk.clone()); 37 | keypairs.push((sk, pk)); 38 | } 39 | } 40 | 41 | let aggsig = AggSigContext::new(&secp, &pks); 42 | 43 | for i in 0..numkeys { 44 | if aggsig.generate_nonce(i) != true { 45 | panic!("failed to generate aggsig nonce: {}", i); 46 | } 47 | } 48 | 49 | let mut msg_in = [0u8; 32]; 50 | rng.fill(&mut msg_in); 51 | let msg = Message::from_slice(&msg_in).unwrap(); 52 | 53 | let mut partial_sigs: Vec = vec![]; 54 | 55 | for (i, (ss, _)) in keypairs.iter().enumerate() { 56 | match aggsig.partial_sign(msg.clone(), ss.clone(), i) { 57 | Ok(res) => partial_sigs.push(res), 58 | Err(e) => panic!("error creating partial signature: {:?}", e), 59 | } 60 | } 61 | 62 | match aggsig.combine_signatures(&partial_sigs) { 63 | Ok(full_sig) => { let _ = aggsig.verify(full_sig, msg.clone(), &pks); () }, 64 | Err(e) => panic!("error combining signatures: {:?}", e), 65 | } 66 | }); 67 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2019 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 | trigger: 16 | branches: 17 | include: 18 | - master 19 | - milestone/* 20 | tags: 21 | include: ['*'] 22 | 23 | pr: 24 | branches: 25 | include: ['*'] 26 | 27 | variables: 28 | RUST_BACKTRACE: '1' 29 | RUSTFLAGS: '-C debug-assertions' 30 | 31 | jobs: 32 | - job: linux 33 | pool: 34 | vmImage: ubuntu-latest 35 | strategy: 36 | matrix: 37 | stable: 38 | rustup_toolchain: stable 39 | beta: 40 | rustup_toolchain: beta 41 | nightly: 42 | rustup_toolchain: nightly 43 | steps: 44 | - script: | 45 | rustup toolchain install $RUSTUP_TOOLCHAIN 46 | rustup default $RUSTUP_TOOLCHAIN 47 | - script: | 48 | git submodule update --init 49 | cargo build 50 | cargo build --release 51 | cargo test 52 | cargo test --release 53 | cargo bench 54 | cargo doc 55 | displayName: Test 56 | - job: macos 57 | pool: 58 | vmImage: macos-latest 59 | strategy: 60 | matrix: 61 | stable: 62 | rustup_toolchain: stable 63 | beta: 64 | rustup_toolchain: beta 65 | nightly: 66 | rustup_toolchain: nightly 67 | steps: 68 | - script: | 69 | rustup toolchain install $RUSTUP_TOOLCHAIN 70 | rustup default $RUSTUP_TOOLCHAIN 71 | - script: | 72 | git submodule update --init 73 | cargo build 74 | cargo build --release 75 | cargo test 76 | cargo test --release 77 | cargo bench 78 | cargo doc 79 | displayName: Test 80 | - job: windows 81 | pool: 82 | vmImage: windows-latest 83 | strategy: 84 | matrix: 85 | stable: 86 | rustup_toolchain: stable 87 | beta: 88 | rustup_toolchain: beta 89 | nightly: 90 | rustup_toolchain: nightly 91 | steps: 92 | - script: | 93 | curl -sSf -o rustup-init.exe https://win.rustup.rs 94 | rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain %RUSTUP_TOOLCHAIN% 95 | displayName: Install Toolchain 96 | - script: | 97 | git submodule update --init 98 | cargo build 99 | cargo build --release 100 | cargo test 101 | cargo test --release 102 | cargo bench 103 | cargo doc 104 | displayName: Test 105 | -------------------------------------------------------------------------------- /src/ecdh.rs: -------------------------------------------------------------------------------- 1 | // Bitcoin secp256k1 bindings 2 | // Written in 2015 by 3 | // Andrew Poelstra 4 | // 5 | // To the extent possible under law, the author(s) have dedicated all 6 | // copyright and related and neighboring rights to this software to 7 | // the public domain worldwide. This software is distributed without 8 | // any warranty. 9 | // 10 | // You should have received a copy of the CC0 Public Domain Dedication 11 | // along with this software. 12 | // If not, see . 13 | // 14 | 15 | //! # ECDH 16 | //! Support for shared secret computations 17 | //! 18 | 19 | use std::ops; 20 | 21 | use super::Secp256k1; 22 | use crate::key::{SecretKey, PublicKey}; 23 | use crate::ffi; 24 | 25 | /// A tag used for recovering the public key from a compact signature 26 | #[derive(Clone, PartialEq, Eq, Debug)] 27 | pub struct SharedSecret(ffi::SharedSecret); 28 | 29 | impl SharedSecret { 30 | /// Creates a new shared secret from a pubkey and secret key 31 | #[inline] 32 | pub fn new(secp: &Secp256k1, point: &PublicKey, scalar: &SecretKey) -> SharedSecret { 33 | unsafe { 34 | let mut ss = ffi::SharedSecret::blank(); 35 | let res = ffi::secp256k1_ecdh(secp.ctx, &mut ss, point.as_ptr(), scalar.as_ptr()); 36 | debug_assert_eq!(res, 1); 37 | SharedSecret(ss) 38 | } 39 | } 40 | 41 | /// Obtains a raw pointer suitable for use with FFI functions 42 | #[inline] 43 | pub fn as_ptr(&self) -> *const ffi::SharedSecret { 44 | &self.0 as *const _ 45 | } 46 | } 47 | 48 | /// Creates a new shared secret from a FFI shared secret 49 | impl From for SharedSecret { 50 | #[inline] 51 | fn from(ss: ffi::SharedSecret) -> SharedSecret { 52 | SharedSecret(ss) 53 | } 54 | } 55 | 56 | 57 | impl ops::Index for SharedSecret { 58 | type Output = u8; 59 | 60 | #[inline] 61 | fn index(&self, index: usize) -> &u8 { 62 | &self.0[index] 63 | } 64 | } 65 | 66 | impl ops::Index> for SharedSecret { 67 | type Output = [u8]; 68 | 69 | #[inline] 70 | fn index(&self, index: ops::Range) -> &[u8] { 71 | &self.0[index] 72 | } 73 | } 74 | 75 | impl ops::Index> for SharedSecret { 76 | type Output = [u8]; 77 | 78 | #[inline] 79 | fn index(&self, index: ops::RangeFrom) -> &[u8] { 80 | &self.0[index.start..] 81 | } 82 | } 83 | 84 | impl ops::Index for SharedSecret { 85 | type Output = [u8]; 86 | 87 | #[inline] 88 | fn index(&self, _: ops::RangeFull) -> &[u8] { 89 | &self.0[..] 90 | } 91 | } 92 | 93 | #[cfg(test)] 94 | mod tests { 95 | use rand::thread_rng; 96 | use super::SharedSecret; 97 | use super::super::Secp256k1; 98 | 99 | #[test] 100 | fn ecdh() { 101 | let s = Secp256k1::with_caps(crate::ContextFlag::SignOnly); 102 | let (sk1, pk1) = s.generate_keypair(&mut thread_rng()).unwrap(); 103 | let (sk2, pk2) = s.generate_keypair(&mut thread_rng()).unwrap(); 104 | 105 | let sec1 = SharedSecret::new(&s, &pk1, &sk2); 106 | let sec2 = SharedSecret::new(&s, &pk2, &sk1); 107 | let sec_odd = SharedSecret::new(&s, &pk1, &sk1); 108 | assert_eq!(sec1, sec2); 109 | assert!(sec_odd != sec2); 110 | } 111 | } 112 | 113 | #[cfg(all(test, feature = "unstable"))] 114 | mod benches { 115 | use rand::thread_rng; 116 | use test::{Bencher, black_box}; 117 | 118 | use super::SharedSecret; 119 | use super::super::Secp256k1; 120 | 121 | #[bench] 122 | pub fn bench_ecdh(bh: &mut Bencher) { 123 | let s = Secp256k1::with_caps(::ContextFlag::SignOnly); 124 | let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); 125 | 126 | let s = Secp256k1::new(); 127 | bh.iter( || { 128 | let res = SharedSecret::new(&s, &pk, &sk); 129 | black_box(res); 130 | }); 131 | } 132 | } 133 | 134 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | 123 | -------------------------------------------------------------------------------- /src/constants.rs: -------------------------------------------------------------------------------- 1 | // Bitcoin secp256k1 bindings 2 | // Written in 2014 by 3 | // Dawid Ciężarkiewicz 4 | // Andrew Poelstra 5 | // 6 | // To the extent possible under law, the author(s) have dedicated all 7 | // copyright and related and neighboring rights to this software to 8 | // the public domain worldwide. This software is distributed without 9 | // any warranty. 10 | // 11 | // You should have received a copy of the CC0 Public Domain Dedication 12 | // along with this software. 13 | // If not, see . 14 | // 15 | 16 | //! # Constants 17 | //! Constants related to the API and the underlying curve 18 | 19 | /// The size (in bytes) of a message 20 | pub const MESSAGE_SIZE: usize = 32; 21 | 22 | /// The size (in bytes) of a secret key 23 | pub const SECRET_KEY_SIZE: usize = 32; 24 | 25 | /// The size (in bytes) of a public key array. This only needs to be 65 26 | /// but must be 72 for compatibility with the `ArrayVec` library. 27 | pub const PUBLIC_KEY_SIZE: usize = 72; 28 | 29 | /// The size (in bytes) of an uncompressed public key 30 | pub const UNCOMPRESSED_PUBLIC_KEY_SIZE: usize = 65; 31 | 32 | /// The size (in bytes) of a compressed public key 33 | pub const COMPRESSED_PUBLIC_KEY_SIZE: usize = 33; 34 | 35 | /// The size of an agg sig 36 | pub const AGG_SIGNATURE_SIZE: usize = 64; 37 | 38 | /// The maximum size of a signature 39 | pub const MAX_SIGNATURE_SIZE: usize = 72; 40 | 41 | /// The maximum size of a compact signature 42 | pub const COMPACT_SIGNATURE_SIZE: usize = 64; 43 | 44 | /// The size of a generator point 45 | pub const GENERATOR_SIZE: usize = 64; 46 | 47 | /// The size of a Pedersen commitment 48 | pub const PEDERSEN_COMMITMENT_SIZE: usize = 33; 49 | 50 | /// The size of a Pedersen commitment 51 | pub const PEDERSEN_COMMITMENT_SIZE_INTERNAL: usize = 64; 52 | 53 | /// The size of a single Bullet proof 54 | pub const SINGLE_BULLET_PROOF_SIZE: usize = 675; 55 | 56 | #[cfg(feature = "bullet-proof-sizing")] 57 | pub const MAX_PROOF_SIZE: usize = SINGLE_BULLET_PROOF_SIZE; 58 | /// The max size of a range proof 59 | #[cfg(not(feature = "bullet-proof-sizing"))] 60 | pub const MAX_PROOF_SIZE: usize = 5134; 61 | 62 | /// The maximum size of a message embedded in a range proof 63 | #[cfg(not(feature = "bullet-proof-sizing"))] 64 | pub const PROOF_MSG_SIZE: usize = 2048; 65 | #[cfg(feature = "bullet-proof-sizing")] 66 | pub const PROOF_MSG_SIZE: usize = 2048; 67 | 68 | /// The maximum size of an optional message embedded in a bullet proof 69 | pub const BULLET_PROOF_MSG_SIZE: usize = 20; 70 | 71 | /// The order of the secp256k1 curve 72 | pub const CURVE_ORDER: [u8; 32] = [ 73 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 74 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 75 | 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 76 | 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 77 | ]; 78 | 79 | /// Generator point G 80 | /// 81 | /// Used as generator point for the blinding factor in Pedersen Commitments. 82 | /// Definition: Standard generator point of secp256k1 83 | /// (as defined in http://www.secg.org/sec2-v2.pdf) 84 | /// 85 | /// Format: x- and y- coordinate, without compressed/uncompressed prefix byte 86 | pub const GENERATOR_G : [u8;64] = [ 87 | 0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac, 88 | 0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07, 89 | 0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9, 90 | 0x59, 0xf2, 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98, 91 | 0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 92 | 0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8, 93 | 0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19, 94 | 0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8 95 | ]; 96 | 97 | /// Generator point H 98 | /// 99 | /// Used as generator point for the value in Pedersen Commitments. 100 | /// Created as NUMS (nothing-up-my-sleeve) curve point from SHA256 hash of G. 101 | /// Details: Calculate sha256 of uncompressed serialization format of G, treat the 102 | /// result as x-coordinate, find the first point on curve with this x-coordinate 103 | /// (which happens to exist on the curve) 104 | /// 105 | /// Example in SageMath: 106 | /// -------------------- 107 | /// sage: import hashlib 108 | /// 109 | /// sage: # finite field of secp256k1: 110 | /// sage: F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F) 111 | /// sage: # Elliptic Curve defined by y^2 = x^3 + 0x + 7 over finite field F ( = secp256k1) 112 | /// sage: secp256k1 = EllipticCurve ([F (0), F (7)]) 113 | /// 114 | /// sage: # hash of generator point G in uncompressed form: 115 | /// sage: hash_of_g = hashlib.sha256('0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'.decode('hex')) 116 | /// sage: hash_of_g_as_int = Integer(int(hash_of_g.hexdigest(),16)) 117 | /// 118 | /// sage: # get the first point on the curve (if any exists) from given x-coordinate: 119 | /// sage: POINT_H = secp256k1.lift_x(hash_of_g_as_int) 120 | /// 121 | /// sage: # output x- and y-coordinates of the point in hexadecimal: 122 | /// sage: '%x %x'%POINT_H.xy() 123 | /// 124 | /// sage Result: '50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0 31d3c6863973926e049e637cb1b5f40a36dac28af1766968c30c2313f3a38904' 125 | /// 126 | /// Format: x- and y- coordinate, without compressed/uncompressed prefix byte 127 | pub const GENERATOR_H : [u8;64] = [ 128 | 0x50, 0x92, 0x9b, 0x74, 0xc1, 0xa0, 0x49, 0x54, 129 | 0xb7, 0x8b, 0x4b, 0x60, 0x35, 0xe9, 0x7a, 0x5e, 130 | 0x07, 0x8a, 0x5a, 0x0f, 0x28, 0xec, 0x96, 0xd5, 131 | 0x47, 0xbf, 0xee, 0x9a, 0xce, 0x80, 0x3a, 0xc0, 132 | 0x31, 0xd3, 0xc6, 0x86, 0x39, 0x73, 0x92, 0x6e, 133 | 0x04, 0x9e, 0x63, 0x7c, 0xb1, 0xb5, 0xf4, 0x0a, 134 | 0x36, 0xda, 0xc2, 0x8a, 0xf1, 0x76, 0x69, 0x68, 135 | 0xc3, 0x0c, 0x23, 0x13, 0xf3, 0xa3, 0x89, 0x04 136 | ]; 137 | 138 | /// Generator point J 139 | /// 140 | /// Used as generator point in Switch Commitments. 141 | /// Created as NUMS (nothing-up-my-sleeve) curve point from double-SHA256 hash of G. 142 | /// Details: Calculate sha256 of sha256 of uncompressed serialization format of G, treat 143 | /// the result as x-coordinate, find the first point on curve with this x-coordinate 144 | /// (which happens to exist on the curve) 145 | /// 146 | /// Example in SageMath: 147 | /// -------------------- 148 | /// sage: import hashlib 149 | /// 150 | /// sage: # finite field of secp256k1: 151 | /// sage: F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F) 152 | /// sage: # Elliptic Curve defined by y^2 = x^3 + 0x + 7 over finite field F ( = secp256k1) 153 | /// sage: secp256k1 = EllipticCurve ([F (0), F (7)]) 154 | /// 155 | /// sage: # hash of generator point G in uncompressed form: 156 | /// sage: hash_of_g = hashlib.sha256('0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'.decode('hex')) 157 | /// 158 | /// sage: # double hash of generator point G: 159 | /// sage: double_hash_of_g = hashlib.sha256(hash_of_g.hexdigest().decode('hex')) 160 | /// sage: # treat as Integer 161 | /// sage: double_hash_as_int = Integer(int(double_hash_of_g.hexdigest(),16)) 162 | /// 163 | /// sage: # get the first point on the curve (if any exists) from given x-coordinate: 164 | /// sage: POINT_J = secp256k1.lift_x(double_hash_as_int) 165 | /// 166 | /// sage: # output x- and y-coordinates of the point in hexadecimal: 167 | /// sage: '%x %x'%POINT_J.xy() 168 | /// 169 | /// sage Result: 'b860f56795fc03f3c21685383d1b5a2f2954f49b7e398b8d2a0193933621155f a43f09d32caa8f53423f427403a56a3165a5a69a74cf56fc5901a2dca6c5c43a' 170 | /// 171 | /// Format: 172 | /// raw x- and y- coordinate, without compressed/uncompressed prefix byte 173 | /// in REVERSED byte order (indicated by the suffix "_RAW")! 174 | /// 175 | /// This is different from G and H as in the underlying secp256k1 library, J is 176 | /// declared as "secp256k1_pubkey" while G and H are declared as "secp256k1_generator" 177 | /// which seem to be represented and parsed differently (see "secp256k1_ec_pubkey_parse" vs 178 | /// "secp256k1_generator_parse" in https://github.com/mimblewimble/secp256k1-zkp/). 179 | pub const GENERATOR_PUB_J_RAW : [u8;64] = [ 180 | 0x5f, 0x15, 0x21, 0x36, 0x93, 0x93, 0x01, 0x2a, 181 | 0x8d, 0x8b, 0x39, 0x7e, 0x9b, 0xf4, 0x54, 0x29, 182 | 0x2f, 0x5a, 0x1b, 0x3d, 0x38, 0x85, 0x16, 0xc2, 183 | 0xf3, 0x03, 0xfc, 0x95, 0x67, 0xf5, 0x60, 0xb8, 184 | 0x3a, 0xc4, 0xc5, 0xa6, 0xdc, 0xa2, 0x01, 0x59, 185 | 0xfc, 0x56, 0xcf, 0x74, 0x9a, 0xa6, 0xa5, 0x65, 186 | 0x31, 0x6a, 0xa5, 0x03, 0x74, 0x42, 0x3f, 0x42, 187 | 0x53, 0x8f, 0xaa, 0x2c, 0xd3, 0x09, 0x3f, 0xa4 188 | ]; 189 | -------------------------------------------------------------------------------- /src/macros.rs: -------------------------------------------------------------------------------- 1 | // Bitcoin secp256k1 bindings 2 | // Written in 2014 by 3 | // Dawid Ciężarkiewicz 4 | // Andrew Poelstra 5 | // 6 | // To the extent possible under law, the author(s) have dedicated all 7 | // copyright and related and neighboring rights to this software to 8 | // the public domain worldwide. This software is distributed without 9 | // any warranty. 10 | // 11 | // You should have received a copy of the CC0 Public Domain Dedication 12 | // along with this software. 13 | // If not, see . 14 | // 15 | 16 | // This is a macro that routinely comes in handy 17 | macro_rules! impl_array_newtype { 18 | ($thing:ident, $ty:ty, $len:expr) => { 19 | impl $thing { 20 | #[inline] 21 | /// Converts the object to a raw pointer for FFI interfacing 22 | pub fn as_ptr(&self) -> *const $ty { 23 | let &$thing(ref dat) = self; 24 | dat.as_ptr() 25 | } 26 | 27 | #[inline] 28 | /// Converts the object to a mutable raw pointer for FFI interfacing 29 | pub fn as_mut_ptr(&mut self) -> *mut $ty { 30 | let &mut $thing(ref mut dat) = self; 31 | dat.as_mut_ptr() 32 | } 33 | 34 | #[inline] 35 | /// Returns the length of the object as an array 36 | pub fn len(&self) -> usize { $len } 37 | 38 | #[inline] 39 | /// Returns whether the object as an array is empty 40 | pub fn is_empty(&self) -> bool { false } 41 | } 42 | 43 | impl AsRef<[u8]> for $thing { 44 | fn as_ref(&self) -> &[u8] { 45 | self.0.as_ref() 46 | } 47 | } 48 | 49 | impl PartialEq for $thing { 50 | #[inline] 51 | fn eq(&self, other: &$thing) -> bool { 52 | &self[..] == &other[..] 53 | } 54 | } 55 | 56 | impl Eq for $thing {} 57 | 58 | impl PartialOrd for $thing { 59 | #[inline] 60 | fn partial_cmp(&self, other: &$thing) -> Option<::core::cmp::Ordering> { 61 | self[..].partial_cmp(&other[..]) 62 | } 63 | } 64 | 65 | impl Ord for $thing { 66 | #[inline] 67 | fn cmp(&self, other: &$thing) -> ::core::cmp::Ordering { 68 | self[..].cmp(&other[..]) 69 | } 70 | } 71 | 72 | impl Clone for $thing { 73 | #[inline] 74 | fn clone(&self) -> $thing { 75 | unsafe { 76 | use std::ptr::copy_nonoverlapping; 77 | use std::mem; 78 | let mut ret: $thing = mem::MaybeUninit::uninit().assume_init(); 79 | copy_nonoverlapping(self.as_ptr(), 80 | ret.as_mut_ptr(), 81 | mem::size_of::<$thing>()); 82 | ret 83 | } 84 | } 85 | } 86 | 87 | impl ::std::ops::Index for $thing { 88 | type Output = $ty; 89 | 90 | #[inline] 91 | fn index(&self, index: usize) -> &$ty { 92 | let &$thing(ref dat) = self; 93 | &dat[index] 94 | } 95 | } 96 | 97 | impl ::std::ops::Index<::std::ops::Range> for $thing { 98 | type Output = [$ty]; 99 | 100 | #[inline] 101 | fn index(&self, index: ::std::ops::Range) -> &[$ty] { 102 | let &$thing(ref dat) = self; 103 | &dat[index] 104 | } 105 | } 106 | 107 | impl ::std::ops::Index<::std::ops::RangeTo> for $thing { 108 | type Output = [$ty]; 109 | 110 | #[inline] 111 | fn index(&self, index: ::std::ops::RangeTo) -> &[$ty] { 112 | let &$thing(ref dat) = self; 113 | &dat[index] 114 | } 115 | } 116 | 117 | impl ::std::ops::Index<::std::ops::RangeFrom> for $thing { 118 | type Output = [$ty]; 119 | 120 | #[inline] 121 | fn index(&self, index: ::std::ops::RangeFrom) -> &[$ty] { 122 | let &$thing(ref dat) = self; 123 | &dat[index] 124 | } 125 | } 126 | 127 | impl ::std::ops::Index<::std::ops::RangeFull> for $thing { 128 | type Output = [$ty]; 129 | 130 | #[inline] 131 | fn index(&self, _: ::std::ops::RangeFull) -> &[$ty] { 132 | let &$thing(ref dat) = self; 133 | &dat[..] 134 | } 135 | } 136 | 137 | impl ::std::hash::Hash for $thing { 138 | fn hash(&self, state: &mut H) { 139 | state.write(&self.0) 140 | // for n in 0..self.len() { 141 | // state.write_u8(self.0[n]); 142 | // } 143 | } 144 | } 145 | 146 | impl<'de> ::serde::Deserialize<'de> for $thing { 147 | fn deserialize(d: D) -> Result<$thing, D::Error> 148 | where D: ::serde::Deserializer<'de> 149 | { 150 | // We have to define the Visitor struct inside the function 151 | // to make it local ... all we really need is that it's 152 | // local to the macro, but this works too :) 153 | struct Visitor { 154 | marker: ::std::marker::PhantomData<$thing>, 155 | } 156 | impl<'de> ::serde::de::Visitor<'de> for Visitor { 157 | type Value = $thing; 158 | 159 | #[inline] 160 | fn visit_seq(self, mut a: A) -> Result<$thing, A::Error> 161 | where A: ::serde::de::SeqAccess<'de> 162 | { 163 | unsafe { 164 | use std::mem; 165 | let mut ret: [$ty; $len] = mem::MaybeUninit::uninit().assume_init(); 166 | for i in 0..$len { 167 | ret[i] = match a.next_element()? { 168 | Some(c) => c, 169 | None => return Err(::serde::de::Error::invalid_length(i, &self)) 170 | }; 171 | } 172 | let one_after_last : Option = a.next_element()?; 173 | if one_after_last.is_some() { 174 | return Err(::serde::de::Error::invalid_length($len + 1, &self)); 175 | } 176 | Ok($thing(ret)) 177 | } 178 | } 179 | 180 | fn expecting(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 181 | write!(f, "a sequence of {} elements", $len) 182 | } 183 | } 184 | 185 | // Begin actual function 186 | d.deserialize_seq(Visitor { marker: ::std::marker::PhantomData }) 187 | } 188 | } 189 | 190 | impl ::serde::Serialize for $thing { 191 | fn serialize(&self, s: S) -> Result 192 | where S: ::serde::Serializer 193 | { 194 | (&self.0[..]).serialize(s) 195 | } 196 | } 197 | } 198 | } 199 | 200 | macro_rules! impl_pretty_debug { 201 | ($thing:ident) => { 202 | impl ::std::fmt::Debug for $thing { 203 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 204 | write!(f, "{}(", stringify!($thing))?; 205 | for i in self[..].iter().cloned() { 206 | write!(f, "{:02x}", i)?; 207 | } 208 | write!(f, ")") 209 | } 210 | } 211 | } 212 | } 213 | 214 | macro_rules! impl_raw_debug { 215 | ($thing:ident) => { 216 | impl ::std::fmt::Debug for $thing { 217 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 218 | for i in self[..].iter().cloned() { 219 | write!(f, "{:02x}", i)?; 220 | } 221 | Ok(()) 222 | } 223 | } 224 | } 225 | } 226 | 227 | macro_rules! map_vec { 228 | ($thing:expr, $mapfn:expr ) => { 229 | $thing.iter() 230 | .map($mapfn) 231 | .collect::>() 232 | } 233 | } 234 | 235 | #[cfg(test)] 236 | // A macro useful for serde (de)serialization tests 237 | macro_rules! round_trip_serde ( 238 | ($var:ident) => ({ 239 | let start = $var; 240 | let mut encoded = Vec::new(); 241 | { 242 | let mut serializer = crate::json::ser::Serializer::new(&mut encoded); 243 | ::serde::Serialize::serialize(&start, &mut serializer).unwrap(); 244 | } 245 | let mut deserializer = crate::json::de::Deserializer::from_slice(&encoded); 246 | let decoded = ::serde::Deserialize::deserialize(&mut deserializer); 247 | assert_eq!(Some(start), decoded.ok()); 248 | }) 249 | ); 250 | -------------------------------------------------------------------------------- /src/aggsig.rs: -------------------------------------------------------------------------------- 1 | // Rust secp256k1 bindings for aggsig functions 2 | // 2018 The Grin developers 3 | // 4 | // To the extent possible under law, the author(s) have dedicated all 5 | // copyright and related and neighboring rights to this software to 6 | // the public domain worldwide. This software is distributed without 7 | // any warranty. 8 | // 9 | // You should have received a copy of the CC0 Public Domain Dedication 10 | // along with this software. 11 | // If not, see . 12 | // 13 | 14 | //! # Aggregated Signature (a.k.a. Schnorr) Functionality 15 | 16 | use libc::size_t; 17 | use crate::ffi; 18 | use crate::key::{PublicKey, SecretKey}; 19 | use rand::{thread_rng, Rng}; 20 | use std::ptr; 21 | use crate::Secp256k1; 22 | use crate::{AggSigPartialSignature, Error, Message, Signature}; 23 | 24 | const SCRATCH_SPACE_SIZE: size_t = 1024 * 1024; 25 | 26 | /// The 256 bits 0 27 | pub const ZERO_256: [u8; 32] = [ 28 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29 | ]; 30 | 31 | /// Single-Signer (plain old Schnorr, sans-multisig) export nonce 32 | /// Returns: Ok(SecretKey) on success 33 | /// In: 34 | /// msg: the message to sign 35 | /// seckey: the secret key 36 | pub fn export_secnonce_single(secp: &Secp256k1) -> Result { 37 | let mut return_key = SecretKey::new(&secp, &mut thread_rng()); 38 | let mut seed = [0u8; 32]; 39 | thread_rng().fill(&mut seed); 40 | let retval = unsafe { 41 | ffi::secp256k1_aggsig_export_secnonce_single( 42 | secp.ctx, 43 | return_key.as_mut_ptr(), 44 | seed.as_ptr(), 45 | ) 46 | }; 47 | if retval == 0 { 48 | return Err(Error::InvalidSignature); 49 | } 50 | Ok(return_key) 51 | } 52 | 53 | // This is a macro that check zero public key 54 | macro_rules! is_zero_pubkey { 55 | (reterr => $e:expr) => { 56 | match $e { 57 | Some(n) => { 58 | if (n.0).0.starts_with(&ZERO_256) { 59 | return Err(Error::InvalidPublicKey); 60 | } 61 | n.as_ptr() 62 | } 63 | None => ptr::null(), 64 | } 65 | }; 66 | (retfalse => $e:expr) => { 67 | match $e { 68 | Some(n) => { 69 | if (n.0).0.starts_with(&ZERO_256) { 70 | return false; 71 | } 72 | n.as_ptr() 73 | } 74 | None => ptr::null(), 75 | } 76 | }; 77 | } 78 | 79 | /// Single-Signer (plain old Schnorr, sans-multisig) signature creation 80 | /// Returns: Ok(Signature) on success 81 | /// In: 82 | /// msg: the message to sign 83 | /// seckey: the secret key 84 | /// extra: if Some(), add this key to s 85 | /// secnonce: if Some(SecretKey), the secret nonce to use. If None, generate a nonce 86 | /// pubnonce: if Some(PublicKey), overrides the public nonce to encode as part of e 87 | /// final_nonce_sum: if Some(PublicKey), overrides the public nonce to encode as part of e 88 | pub fn sign_single( 89 | secp: &Secp256k1, 90 | msg: &Message, 91 | seckey: &SecretKey, 92 | secnonce: Option<&SecretKey>, 93 | extra: Option<&SecretKey>, 94 | pubnonce: Option<&PublicKey>, 95 | pubkey_for_e: Option<&PublicKey>, 96 | final_nonce_sum: Option<&PublicKey>, 97 | ) -> Result { 98 | let mut retsig = Signature::from(ffi::Signature::new()); 99 | let mut seed = [0u8; 32]; 100 | thread_rng().fill(&mut seed); 101 | 102 | let secnonce = match secnonce { 103 | Some(n) => n.as_ptr(), 104 | None => ptr::null(), 105 | }; 106 | 107 | let pubnonce = is_zero_pubkey!(reterr => pubnonce); 108 | 109 | let extra = match extra { 110 | Some(e) => e.as_ptr(), 111 | None => ptr::null(), 112 | }; 113 | 114 | let final_nonce_sum = is_zero_pubkey!(reterr => final_nonce_sum); 115 | 116 | let pe = is_zero_pubkey!(reterr => pubkey_for_e); 117 | 118 | let retval = unsafe { 119 | ffi::secp256k1_aggsig_sign_single( 120 | secp.ctx, 121 | retsig.as_mut_ptr(), 122 | msg.as_ptr(), 123 | seckey.as_ptr(), 124 | secnonce, 125 | extra, 126 | pubnonce, 127 | final_nonce_sum, 128 | pe, 129 | seed.as_ptr(), 130 | ) 131 | }; 132 | if retval == 0 { 133 | return Err(Error::InvalidSignature); 134 | } 135 | Ok(retsig) 136 | } 137 | 138 | /// Single-Signer (plain old Schnorr, sans-multisig) signature verification 139 | /// Returns: Ok(Signature) on success 140 | /// In: 141 | /// sig: The signature 142 | /// msg: the message to verify 143 | /// pubnonce: if Some(PublicKey) overrides the public nonce used to calculate e 144 | /// pubkey: the public key 145 | /// pubkey_total: The total of all public keys (for the message in e) 146 | /// is_partial: whether this is a partial sig, or a fully-combined sig 147 | pub fn verify_single( 148 | secp: &Secp256k1, 149 | sig: &Signature, 150 | msg: &Message, 151 | pubnonce: Option<&PublicKey>, 152 | pubkey: &PublicKey, 153 | pubkey_total_for_e: Option<&PublicKey>, 154 | extra_pubkey: Option<&PublicKey>, 155 | is_partial: bool, 156 | ) -> bool { 157 | let pubnonce = is_zero_pubkey!(retfalse => pubnonce); 158 | 159 | let pe = is_zero_pubkey!(retfalse => pubkey_total_for_e); 160 | 161 | let extra = is_zero_pubkey!(retfalse => extra_pubkey); 162 | 163 | let is_partial = match is_partial { 164 | true => 1, 165 | false => 0, 166 | }; 167 | 168 | if (sig.0).0.starts_with(&ZERO_256) || (pubkey.0).0.starts_with(&ZERO_256) { 169 | return false; 170 | } 171 | 172 | let retval = unsafe { 173 | ffi::secp256k1_aggsig_verify_single( 174 | secp.ctx, 175 | sig.as_ptr(), 176 | msg.as_ptr(), 177 | pubnonce, 178 | pubkey.as_ptr(), 179 | pe, 180 | extra, 181 | is_partial, 182 | ) 183 | }; 184 | match retval { 185 | 0 => false, 186 | 1 => true, 187 | _ => false, 188 | } 189 | } 190 | 191 | 192 | /// Batch Schnorr signature verification 193 | /// Returns: true on success 194 | /// In: 195 | /// sigs: The signatures 196 | /// msg: The messages to verify 197 | /// pubkey: The public keys 198 | pub fn verify_batch( 199 | secp: &Secp256k1, 200 | sigs: &Vec, 201 | msgs: &Vec, 202 | pub_keys: &Vec, 203 | ) -> bool { 204 | if sigs.len() != msgs.len() || sigs.len() != pub_keys.len() { 205 | return false; 206 | } 207 | 208 | for i in 0..pub_keys.len() { 209 | if (pub_keys[i].0).0.starts_with(&ZERO_256) { 210 | return false; 211 | } 212 | } 213 | 214 | let sigs_vec = map_vec!(sigs, |s| s.0.as_ptr()); 215 | let msgs_vec = map_vec!(msgs, |m| m.as_ptr()); 216 | let pub_keys_vec = map_vec!(pub_keys, |pk| pk.as_ptr()); 217 | 218 | unsafe { 219 | let scratch = ffi::secp256k1_scratch_space_create(secp.ctx, SCRATCH_SPACE_SIZE); 220 | let result = ffi::secp256k1_schnorrsig_verify_batch( 221 | secp.ctx, 222 | scratch, 223 | sigs_vec.as_ptr(), 224 | msgs_vec.as_ptr(), 225 | pub_keys_vec.as_ptr(), 226 | sigs.len(), 227 | ); 228 | ffi::secp256k1_scratch_space_destroy(scratch); 229 | result == 1 230 | } 231 | } 232 | 233 | /// Single-Signer addition of Signatures 234 | /// Returns: Ok(Signature) on success 235 | /// In: 236 | /// sig1: sig1 to add 237 | /// sig2: sig2 to add 238 | /// pubnonce_total: sum of public nonces 239 | pub fn add_signatures_single( 240 | secp: &Secp256k1, 241 | sigs: Vec<&Signature>, 242 | pubnonce_total: &PublicKey, 243 | ) -> Result { 244 | let mut retsig = Signature::from(ffi::Signature::new()); 245 | let sig_vec = map_vec!(sigs, |s| s.0.as_ptr()); 246 | let retval = unsafe { 247 | ffi::secp256k1_aggsig_add_signatures_single( 248 | secp.ctx, 249 | retsig.as_mut_ptr(), 250 | sig_vec.as_ptr(), 251 | sig_vec.len(), 252 | pubnonce_total.as_ptr(), 253 | ) 254 | }; 255 | if retval == 0 { 256 | return Err(Error::InvalidSignature); 257 | } 258 | Ok(retsig) 259 | } 260 | 261 | /// Subtraction of partial signature from a signature 262 | /// Returns: Ok((Signature, None)) on success if the resulting signature has only one possibility 263 | /// Ok((Signature, Signature)) on success if the resulting signature could be one of either possiblity 264 | /// In: 265 | /// sig: completed signature from which to subtact a partial 266 | /// partial_sig: the partial signature to subtract 267 | pub fn subtract_partial_signature( 268 | secp: &Secp256k1, 269 | sig: &Signature, 270 | partial_sig: &Signature, 271 | ) -> Result<(Signature, Option), Error> { 272 | let mut ret_partsig = Signature::from(ffi::Signature::new()); 273 | let mut ret_partsig_alt = Signature::from(ffi::Signature::new()); 274 | let retval = unsafe { 275 | ffi::secp256k1_aggsig_subtract_partial_signature( 276 | secp.ctx, 277 | ret_partsig.as_mut_ptr(), 278 | ret_partsig_alt.as_mut_ptr(), 279 | sig.as_ptr(), 280 | partial_sig.as_ptr(), 281 | ) 282 | }; 283 | 284 | match retval { 285 | -1 => Err(Error::SigSubtractionFailure), 286 | 1 => Ok((ret_partsig, None)), 287 | 2 => Ok((ret_partsig, Some(ret_partsig_alt))), 288 | _ => Err(Error::InvalidSignature) 289 | } 290 | } 291 | 292 | 293 | /// Manages an instance of an aggsig multisig context, and provides all methods 294 | /// to act on that context 295 | #[derive(Clone, Debug)] 296 | pub struct AggSigContext { 297 | ctx: *mut ffi::Context, 298 | aggsig_ctx: *mut ffi::AggSigContext, 299 | } 300 | 301 | impl AggSigContext { 302 | /// Creates new aggsig context with a new random seed 303 | pub fn new(secp: &Secp256k1, pubkeys: &Vec) -> AggSigContext { 304 | let mut seed = [0u8; 32]; 305 | thread_rng().fill(&mut seed); 306 | let pubkeys: Vec<*const ffi::PublicKey> = pubkeys.into_iter().map(|p| p.as_ptr()).collect(); 307 | let pubkeys = &pubkeys[..]; 308 | unsafe { 309 | AggSigContext { 310 | ctx: secp.ctx, 311 | aggsig_ctx: ffi::secp256k1_aggsig_context_create( 312 | secp.ctx, 313 | pubkeys[0], 314 | pubkeys.len(), 315 | seed.as_ptr(), 316 | ), 317 | } 318 | } 319 | } 320 | 321 | /// Generate a nonce pair for a single signature part in an aggregated signature 322 | /// Returns: true on success 323 | /// false if a nonce has already been generated for this index 324 | /// In: index: which signature to generate a nonce for 325 | pub fn generate_nonce(&self, index: usize) -> bool { 326 | let retval = 327 | unsafe { ffi::secp256k1_aggsig_generate_nonce(self.ctx, self.aggsig_ctx, index) }; 328 | match retval { 329 | 0 => false, 330 | 1 => true, 331 | _ => false, 332 | } 333 | } 334 | 335 | /// Generate a single signature part in an aggregated signature 336 | /// Returns: Ok(AggSigPartialSignature) on success 337 | /// In: 338 | /// msg: the message to sign 339 | /// seckey: the secret key 340 | /// index: which index to generate a partial sig for 341 | pub fn partial_sign( 342 | &self, 343 | msg: Message, 344 | seckey: SecretKey, 345 | index: usize, 346 | ) -> Result { 347 | let mut retsig = AggSigPartialSignature::from(ffi::AggSigPartialSignature::new()); 348 | let retval = unsafe { 349 | ffi::secp256k1_aggsig_partial_sign( 350 | self.ctx, 351 | self.aggsig_ctx, 352 | retsig.as_mut_ptr(), 353 | msg.as_ptr(), 354 | seckey.as_ptr(), 355 | index, 356 | ) 357 | }; 358 | if retval == 0 { 359 | return Err(Error::PartialSigFailure); 360 | } 361 | Ok(retsig) 362 | } 363 | 364 | /// Aggregate multiple signature parts into a single aggregated signature 365 | /// Returns: Ok(Signature) on success 366 | /// In: 367 | /// partial_sigs: vector of partial signatures 368 | pub fn combine_signatures( 369 | &self, 370 | partial_sigs: &Vec, 371 | ) -> Result { 372 | let mut retsig = Signature::from(ffi::Signature::new()); 373 | let partial_sigs: Vec<*const ffi::AggSigPartialSignature> = 374 | partial_sigs.into_iter().map(|p| p.as_ptr()).collect(); 375 | let partial_sigs = &partial_sigs[..]; 376 | let retval = unsafe { 377 | ffi::secp256k1_aggsig_combine_signatures( 378 | self.ctx, 379 | self.aggsig_ctx, 380 | retsig.as_mut_ptr(), 381 | partial_sigs[0], 382 | partial_sigs.len(), 383 | ) 384 | }; 385 | if retval == 0 { 386 | return Err(Error::PartialSigFailure); 387 | } 388 | Ok(retsig) 389 | } 390 | 391 | /// Verifies aggregate sig 392 | /// Returns: true if valid, okay if not 393 | /// In: 394 | /// msg: message to verify 395 | /// sig: combined signature 396 | /// pks: public keys 397 | pub fn verify(&self, sig: Signature, msg: Message, pks: &Vec) -> bool { 398 | let pks: Vec<*const ffi::PublicKey> = pks.into_iter().map(|p| p.as_ptr()).collect(); 399 | let pks = &pks[..]; 400 | let retval = unsafe { 401 | ffi::secp256k1_aggsig_build_scratch_and_verify( 402 | self.ctx, 403 | sig.as_ptr(), 404 | msg.as_ptr(), 405 | pks[0], 406 | pks.len(), 407 | ) 408 | }; 409 | match retval { 410 | 0 => false, 411 | 1 => true, 412 | _ => false, 413 | } 414 | } 415 | } 416 | 417 | impl Drop for AggSigContext { 418 | fn drop(&mut self) { 419 | unsafe { 420 | ffi::secp256k1_aggsig_context_destroy(self.aggsig_ctx); 421 | } 422 | } 423 | } 424 | 425 | #[cfg(test)] 426 | mod tests { 427 | use super::{ 428 | add_signatures_single, export_secnonce_single, sign_single, verify_single, verify_batch, 429 | AggSigContext, Secp256k1, 430 | }; 431 | use crate::aggsig::subtract_partial_signature; 432 | use crate::ffi; 433 | use crate::key::{PublicKey, SecretKey}; 434 | use rand::{thread_rng, Rng}; 435 | use crate::ContextFlag; 436 | use crate::{AggSigPartialSignature, Message, Signature}; 437 | 438 | #[test] 439 | fn test_aggsig_multisig() { 440 | let numkeys = 5; 441 | let secp = Secp256k1::with_caps(ContextFlag::Full); 442 | let mut keypairs: Vec<(SecretKey, PublicKey)> = vec![]; 443 | for _ in 0..numkeys { 444 | keypairs.push(secp.generate_keypair(&mut thread_rng()).unwrap()); 445 | } 446 | let pks: Vec = keypairs.clone().into_iter().map(|(_, p)| p).collect(); 447 | println!( 448 | "Creating aggsig context with {} pubkeys: {:?}", 449 | pks.len(), 450 | pks 451 | ); 452 | let aggsig = AggSigContext::new(&secp, &pks); 453 | println!("Generating nonces for each index"); 454 | for i in 0..numkeys { 455 | let retval = aggsig.generate_nonce(i); 456 | println!("{} returned {}", i, retval); 457 | assert!(retval == true); 458 | } 459 | 460 | let mut msg = [0u8; 32]; 461 | thread_rng().fill(&mut msg); 462 | let msg = Message::from_slice(&msg).unwrap(); 463 | let mut partial_sigs: Vec = vec![]; 464 | for i in 0..numkeys { 465 | println!( 466 | "Partial sign message: {:?} at index {}, SK:{:?}", 467 | msg, i, keypairs[i].0 468 | ); 469 | 470 | let result = aggsig.partial_sign(msg, keypairs[i].0.clone(), i); 471 | match result { 472 | Ok(ps) => { 473 | println!("Partial sig: {:?}", ps); 474 | partial_sigs.push(ps); 475 | } 476 | Err(e) => panic!("Partial sig failed: {}", e), 477 | } 478 | } 479 | 480 | let result = aggsig.combine_signatures(&partial_sigs); 481 | 482 | let combined_sig = match result { 483 | Ok(cs) => { 484 | println!("Combined sig: {:?}", cs); 485 | cs 486 | } 487 | Err(e) => panic!("Combining partial sig failed: {}", e), 488 | }; 489 | 490 | println!( 491 | "Verifying Combined sig: {:?}, msg: {:?}, pks:{:?}", 492 | combined_sig, msg, pks 493 | ); 494 | let result = aggsig.verify(combined_sig, msg, &pks); 495 | println!("Signature verification: {}", result); 496 | } 497 | 498 | #[test] 499 | fn test_aggsig_single() { 500 | let secp = Secp256k1::with_caps(ContextFlag::Full); 501 | let (sk, pk) = secp.generate_keypair(&mut thread_rng()).unwrap(); 502 | 503 | println!( 504 | "Performing aggsig single context with seckey, pubkey: {:?},{:?}", 505 | sk, pk 506 | ); 507 | 508 | let mut msg = [0u8; 32]; 509 | thread_rng().fill(&mut msg); 510 | let msg = Message::from_slice(&msg).unwrap(); 511 | let sig = sign_single(&secp, &msg, &sk, None, None, None, None, None).unwrap(); 512 | 513 | println!( 514 | "Verifying aggsig single: {:?}, msg: {:?}, pk:{:?}", 515 | sig, msg, pk 516 | ); 517 | let result = verify_single(&secp, &sig, &msg, None, &pk, None, None, false); 518 | println!("Signature verification single (correct): {}", result); 519 | assert!(result == true); 520 | 521 | let mut msg = [0u8; 32]; 522 | thread_rng().fill(&mut msg); 523 | let msg = Message::from_slice(&msg).unwrap(); 524 | println!( 525 | "Verifying aggsig single: {:?}, msg: {:?}, pk:{:?}", 526 | sig, msg, pk 527 | ); 528 | let result = verify_single(&secp, &sig, &msg, None, &pk, None, None, false); 529 | println!("Signature verification single (wrong message): {}", result); 530 | assert!(result == false); 531 | 532 | // test optional extra key 533 | let mut msg = [0u8; 32]; 534 | thread_rng().fill(&mut msg); 535 | let msg = Message::from_slice(&msg).unwrap(); 536 | let (sk_extra, pk_extra) = secp.generate_keypair(&mut thread_rng()).unwrap(); 537 | let sig = sign_single(&secp, &msg, &sk, None, Some(&sk_extra), None, None, None).unwrap(); 538 | let result = verify_single(&secp, &sig, &msg, None, &pk, None, Some(&pk_extra), false); 539 | assert!(result == true); 540 | } 541 | 542 | #[test] 543 | fn test_aggsig_batch() { 544 | let secp = Secp256k1::with_caps(ContextFlag::Full); 545 | 546 | let mut sigs: Vec = vec![]; 547 | let mut msgs: Vec = vec![]; 548 | let mut pub_keys: Vec = vec![]; 549 | 550 | for _ in 0..100 { 551 | let (sk, pk) = secp.generate_keypair(&mut thread_rng()).unwrap(); 552 | let mut msg = [0u8; 32]; 553 | thread_rng().fill(&mut msg); 554 | 555 | let msg = Message::from_slice(&msg).unwrap(); 556 | let sig = sign_single(&secp, &msg, &sk, None, None, None, Some(&pk), None).unwrap(); 557 | 558 | let result_single = verify_single(&secp, &sig, &msg, None, &pk, Some(&pk), None, false); 559 | assert!(result_single == true); 560 | 561 | pub_keys.push(pk); 562 | msgs.push(msg); 563 | sigs.push(sig); 564 | } 565 | 566 | println!("Verifying aggsig batch of 100"); 567 | let result = verify_batch(&secp, &sigs, &msgs, &pub_keys); 568 | assert!(result == true); 569 | } 570 | 571 | #[test] 572 | fn test_aggsig_fuzz() { 573 | let secp = Secp256k1::with_caps(ContextFlag::Full); 574 | let (sk, pk) = secp.generate_keypair(&mut thread_rng()).unwrap(); 575 | 576 | println!( 577 | "Performing aggsig single context with seckey, pubkey: {:?},{:?}", 578 | sk, pk 579 | ); 580 | 581 | let mut msg = [0u8; 32]; 582 | thread_rng().fill(&mut msg); 583 | let msg = Message::from_slice(&msg).unwrap(); 584 | let sig = sign_single(&secp, &msg, &sk, None, None, None, None, None).unwrap(); 585 | 586 | // force sig[32..] as 0 to simulate Fuzz test 587 | let corrupted = &mut [0u8; 64]; 588 | let mut i = 0; 589 | for elem in corrupted[..32].iter_mut() { 590 | *elem = sig.0[i]; 591 | i += 1; 592 | } 593 | let corrupted_sig: Signature = Signature { 594 | 0: ffi::Signature(*corrupted), 595 | }; 596 | println!( 597 | "Verifying aggsig single: {:?}, msg: {:?}, pk:{:?}", 598 | corrupted_sig, msg, pk 599 | ); 600 | let result = verify_single(&secp, &corrupted_sig, &msg, None, &pk, None, None, false); 601 | println!("Signature verification single (correct): {}", result); 602 | assert!(result == false); 603 | 604 | // force sig[0..32] as 0 to simulate Fuzz test 605 | let corrupted = &mut [0u8; 64]; 606 | let mut i = 32; 607 | for elem in corrupted[32..].iter_mut() { 608 | *elem = sig.0[i]; 609 | i += 1; 610 | } 611 | let corrupted_sig: Signature = Signature { 612 | 0: ffi::Signature(*corrupted), 613 | }; 614 | println!( 615 | "Verifying aggsig single: {:?}, msg: {:?}, pk:{:?}", 616 | corrupted_sig, msg, pk 617 | ); 618 | let result = verify_single(&secp, &corrupted_sig, &msg, None, &pk, None, None, false); 619 | println!("Signature verification single (correct): {}", result); 620 | assert!(result == false); 621 | 622 | // force pk as 0 to simulate Fuzz test 623 | let zero_pk = PublicKey::new(); 624 | println!( 625 | "Verifying aggsig single: {:?}, msg: {:?}, pk:{:?}", 626 | sig, msg, zero_pk 627 | ); 628 | let result = verify_single(&secp, &sig, &msg, None, &zero_pk, None, None, false); 629 | println!("Signature verification single (correct): {}", result); 630 | assert!(result == false); 631 | 632 | let mut sigs: Vec = vec![]; 633 | sigs.push(sig); 634 | let mut msgs: Vec = vec![]; 635 | msgs.push(msg); 636 | let mut pub_keys: Vec = vec![]; 637 | pub_keys.push(zero_pk); 638 | println!( 639 | "Verifying aggsig batch: {:?}, msg: {:?}, pk:{:?}", 640 | sig, msg, zero_pk 641 | ); 642 | let result = verify_batch(&secp, &sigs, &msgs, &pub_keys); 643 | println!("Signature verification batch: {}", result); 644 | assert!(result == false); 645 | 646 | 647 | // force pk[0..32] as 0 to simulate Fuzz test 648 | let corrupted = &mut [0u8; 64]; 649 | let mut i = 32; 650 | for elem in corrupted[32..].iter_mut() { 651 | *elem = pk.0[i]; 652 | i += 1; 653 | } 654 | let corrupted_pk: PublicKey = PublicKey { 655 | 0: ffi::PublicKey(*corrupted), 656 | }; 657 | println!( 658 | "Verifying aggsig single: {:?}, msg: {:?}, pk:{:?}", 659 | sig, msg, corrupted_pk 660 | ); 661 | let result = verify_single(&secp, &sig, &msg, None, &corrupted_pk, None, None, false); 662 | println!("Signature verification single (correct): {}", result); 663 | assert!(result == false); 664 | 665 | // more tests on other parameters 666 | let zero_pk = PublicKey::new(); 667 | let result = verify_single( 668 | &secp, 669 | &sig, 670 | &msg, 671 | Some(&zero_pk), 672 | &zero_pk, 673 | Some(&zero_pk), 674 | Some(&zero_pk), 675 | false, 676 | ); 677 | assert!(result == false); 678 | 679 | let mut msg = [0u8; 32]; 680 | thread_rng().fill(&mut msg); 681 | let msg = Message::from_slice(&msg).unwrap(); 682 | if sign_single( 683 | &secp, 684 | &msg, 685 | &sk, 686 | None, 687 | None, 688 | Some(&zero_pk), 689 | Some(&zero_pk), 690 | Some(&zero_pk), 691 | ).is_ok() 692 | { 693 | panic!("sign_single should fail on zero public key, but not!"); 694 | } 695 | } 696 | 697 | #[test] 698 | fn test_aggsig_exchange() { 699 | for _ in 0..20 { 700 | let secp = Secp256k1::with_caps(ContextFlag::Full); 701 | // Generate keys for sender, receiver 702 | let (sk1, pk1) = secp.generate_keypair(&mut thread_rng()).unwrap(); 703 | let (sk2, pk2) = secp.generate_keypair(&mut thread_rng()).unwrap(); 704 | 705 | // Generate nonces for sender, receiver 706 | let secnonce_1 = export_secnonce_single(&secp).unwrap(); 707 | let secnonce_2 = export_secnonce_single(&secp).unwrap(); 708 | 709 | // Calculate public nonces 710 | let _ = PublicKey::from_secret_key(&secp, &secnonce_1).unwrap(); 711 | let pubnonce_2 = PublicKey::from_secret_key(&secp, &secnonce_2).unwrap(); 712 | 713 | // And get the total 714 | let mut nonce_sum = pubnonce_2.clone(); 715 | let _ = nonce_sum.add_exp_assign(&secp, &secnonce_1); 716 | 717 | // Random message 718 | let mut msg = [0u8; 32]; 719 | thread_rng().fill(&mut msg); 720 | let msg = Message::from_slice(&msg).unwrap(); 721 | 722 | // Add public keys (for storing in e) 723 | let mut pk_sum = pk2.clone(); 724 | let _ = pk_sum.add_exp_assign(&secp, &sk1); 725 | 726 | // Receiver signs 727 | let sig1 = sign_single( 728 | &secp, 729 | &msg, 730 | &sk1, 731 | Some(&secnonce_1), 732 | None, 733 | Some(&nonce_sum), 734 | Some(&pk_sum), 735 | Some(&nonce_sum), 736 | ).unwrap(); 737 | 738 | // Sender verifies receivers sig 739 | let result = verify_single( 740 | &secp, 741 | &sig1, 742 | &msg, 743 | Some(&nonce_sum), 744 | &pk1, 745 | Some(&pk_sum), 746 | None, 747 | true, 748 | ); 749 | assert!(result == true); 750 | 751 | // Sender signs 752 | let sig2 = sign_single( 753 | &secp, 754 | &msg, 755 | &sk2, 756 | Some(&secnonce_2), 757 | None, 758 | Some(&nonce_sum), 759 | Some(&pk_sum), 760 | Some(&nonce_sum), 761 | ).unwrap(); 762 | 763 | // Receiver verifies sender's sig 764 | let result = verify_single( 765 | &secp, 766 | &sig2, 767 | &msg, 768 | Some(&nonce_sum), 769 | &pk2, 770 | Some(&pk_sum), 771 | None, 772 | true, 773 | ); 774 | assert!(result == true); 775 | 776 | let sig_vec = vec![&sig1, &sig2]; 777 | // Receiver calculates final sig 778 | let final_sig = add_signatures_single(&secp, sig_vec, &nonce_sum).unwrap(); 779 | 780 | // Verification of final sig: 781 | let result = verify_single( 782 | &secp, 783 | &final_sig, 784 | &msg, 785 | None, 786 | &pk_sum, 787 | Some(&pk_sum), 788 | None, 789 | false, 790 | ); 791 | assert!(result == true); 792 | 793 | // Subtract sig1 from final sig 794 | let (res_sig, res_sig_opt) = subtract_partial_signature(&secp, &final_sig, &sig1).unwrap(); 795 | assert!(res_sig == sig2 || res_sig_opt == Some(sig2)); 796 | 797 | // Subtract sig2 from final sig for good measure 798 | let (res_sig, res_sig_opt) = subtract_partial_signature(&secp, &final_sig, &sig2).unwrap(); 799 | assert!(res_sig == sig1 || res_sig_opt == Some(sig1)); 800 | } 801 | } 802 | } 803 | -------------------------------------------------------------------------------- /src/ffi.rs: -------------------------------------------------------------------------------- 1 | // Bitcoin secp256k1 bindings 2 | // Written in 2014 by 3 | // Dawid Ciężarkiewicz 4 | // Andrew Poelstra 5 | // 6 | // To the extent possible under law, the author(s) have dedicated all 7 | // copyright and related and neighboring rights to this software to 8 | // the public domain worldwide. This software is distributed without 9 | // any warranty. 10 | // 11 | // You should have received a copy of the CC0 Public Domain Dedication 12 | // along with this software. 13 | // If not, see . 14 | // 15 | 16 | //! # FFI bindings 17 | //! Direct bindings to the underlying C library functions. These should 18 | //! not be needed for most users. 19 | use std::mem; 20 | 21 | use libc::{c_int, c_uchar, c_uint, c_void, size_t}; 22 | 23 | /// Flag for context to enable no precomputation 24 | pub const SECP256K1_START_NONE: c_uint = (1 << 0) | 0; 25 | /// Flag for context to enable verification precomputation 26 | pub const SECP256K1_START_VERIFY: c_uint = (1 << 0) | (1 << 8); 27 | /// Flag for context to enable signing precomputation 28 | pub const SECP256K1_START_SIGN: c_uint = (1 << 0) | (1 << 9); 29 | /// Flag for keys to indicate uncompressed serialization format 30 | pub const SECP256K1_SER_UNCOMPRESSED: c_uint = (1 << 1) | 0; 31 | /// Flag for keys to indicate compressed serialization format 32 | pub const SECP256K1_SER_COMPRESSED: c_uint = (1 << 1) | (1 << 8); 33 | 34 | /// A nonce generation function. Ordinary users of the library 35 | /// never need to see this type; only if you need to control 36 | /// nonce generation do you need to use it. I have deliberately 37 | /// made this hard to do: you have to write your own wrapper 38 | /// around the FFI functions to use it. And it's an unsafe type. 39 | /// Nonces are generated deterministically by RFC6979 by 40 | /// default; there should be no need to ever change this. 41 | pub type NonceFn = unsafe extern "C" fn(nonce32: *mut c_uchar, 42 | msg32: *const c_uchar, 43 | key32: *const c_uchar, 44 | algo16: *const c_uchar, 45 | attempt: c_uint, 46 | data: *const c_void); 47 | 48 | 49 | /// A Secp256k1 context, containing various precomputed values and such 50 | /// needed to do elliptic curve computations. If you create one of these 51 | /// with `secp256k1_context_create` you MUST destroy it with 52 | /// `secp256k1_context_destroy`, or else you will have a memory leak. 53 | #[derive(Clone, Debug)] 54 | #[repr(C)] pub struct Context(c_int); 55 | 56 | /// Secp256k1 aggsig context. As above, needs to be destroyed with 57 | /// `secp256k1_aggsig_context_destroy` 58 | #[derive(Clone, Debug)] 59 | #[repr(C)] pub struct AggSigContext(c_int); 60 | 61 | /// Secp256k1 scratch space 62 | #[derive(Clone, Debug)] 63 | #[repr(C)] pub struct ScratchSpace(c_int); 64 | 65 | /// Secp256k1 bulletproof generators 66 | #[derive(Clone, Debug)] 67 | #[repr(C)] pub struct BulletproofGenerators(c_int); 68 | 69 | /// Generator 70 | #[repr(C)] 71 | pub struct Generator(pub [c_uchar; 64]); 72 | impl Copy for Generator {} 73 | impl_array_newtype!(Generator, c_uchar, 64); 74 | impl_raw_debug!(Generator); 75 | 76 | /// Library-internal representation of a Secp256k1 public key 77 | #[repr(C)] 78 | pub struct PublicKey(pub [c_uchar; 64]); 79 | impl Copy for PublicKey {} 80 | impl_array_newtype!(PublicKey, c_uchar, 64); 81 | impl_raw_debug!(PublicKey); 82 | 83 | impl PublicKey { 84 | /// Create a new (zeroed) public key usable for the FFI interface 85 | pub fn new() -> PublicKey { PublicKey([0; 64]) } 86 | /// Create a new (uninitialized) public key usable for the FFI interface 87 | pub unsafe fn blank() -> PublicKey { mem::MaybeUninit::uninit().assume_init() } 88 | } 89 | 90 | /// Library-internal representation of a Secp256k1 signature 91 | #[repr(C)] 92 | pub struct Signature(pub [c_uchar; 64]); 93 | impl Copy for Signature {} 94 | impl_array_newtype!(Signature, c_uchar, 64); 95 | impl_raw_debug!(Signature); 96 | 97 | /// Library-internal representation of a Secp256k1 signature + recovery ID 98 | #[repr(C)] 99 | pub struct RecoverableSignature([c_uchar; 65]); 100 | impl Copy for RecoverableSignature {} 101 | impl_array_newtype!(RecoverableSignature, c_uchar, 65); 102 | impl_raw_debug!(RecoverableSignature); 103 | 104 | /// Library-internal representation of a Secp256k1 aggsig partial signature 105 | #[repr(C)] 106 | pub struct AggSigPartialSignature([c_uchar; 32]); 107 | impl Copy for AggSigPartialSignature {} 108 | impl_array_newtype!(AggSigPartialSignature, c_uchar, 32); 109 | impl_raw_debug!(AggSigPartialSignature); 110 | 111 | impl Signature { 112 | /// Create a new (zeroed) signature usable for the FFI interface 113 | pub fn new() -> Signature { Signature([0; 64]) } 114 | /// Create a signature from raw data 115 | pub fn from_data(data: [u8; 64]) -> Signature { Signature(data) } 116 | /// Create a new (uninitialized) signature usable for the FFI interface 117 | pub unsafe fn blank() -> Signature { mem::MaybeUninit::uninit().assume_init() } 118 | } 119 | 120 | impl RecoverableSignature { 121 | /// Create a new (zeroed) signature usable for the FFI interface 122 | pub fn new() -> RecoverableSignature { RecoverableSignature([0; 65]) } 123 | /// Create a new (uninitialized) signature usable for the FFI interface 124 | pub unsafe fn blank() -> RecoverableSignature { mem::MaybeUninit::uninit().assume_init() } 125 | } 126 | 127 | impl AggSigPartialSignature { 128 | /// Create a new (zeroed) aggsig partial signature usable for the FFI interface 129 | pub fn new() -> AggSigPartialSignature { AggSigPartialSignature([0; 32]) } 130 | /// Create a new (uninitialized) signature usable for the FFI interface 131 | pub unsafe fn blank() -> AggSigPartialSignature { mem::MaybeUninit::uninit().assume_init() } 132 | } 133 | 134 | /// Library-internal representation of an ECDH shared secret 135 | #[repr(C)] 136 | pub struct SharedSecret([c_uchar; 32]); 137 | impl_array_newtype!(SharedSecret, c_uchar, 32); 138 | impl_raw_debug!(SharedSecret); 139 | 140 | impl SharedSecret { 141 | /// Create a new (zeroed) signature usable for the FFI interface 142 | pub fn new() -> SharedSecret { SharedSecret([0; 32]) } 143 | /// Create a new (uninitialized) signature usable for the FFI interface 144 | pub unsafe fn blank() -> SharedSecret { mem::MaybeUninit::uninit().assume_init() } 145 | } 146 | 147 | 148 | extern "C" { 149 | pub static secp256k1_nonce_function_rfc6979: NonceFn; 150 | 151 | pub static secp256k1_nonce_function_default: NonceFn; 152 | 153 | // Contexts 154 | pub fn secp256k1_context_create(flags: c_uint) -> *mut Context; 155 | 156 | pub fn secp256k1_context_clone(cx: *mut Context) -> *mut Context; 157 | 158 | pub fn secp256k1_context_destroy(cx: *mut Context); 159 | 160 | pub fn secp256k1_context_randomize(cx: *mut Context, 161 | seed32: *const c_uchar) 162 | -> c_int; 163 | // Scratch space 164 | pub fn secp256k1_scratch_space_create(cx: *mut Context, 165 | max_size: size_t) 166 | -> *mut ScratchSpace; 167 | 168 | pub fn secp256k1_scratch_space_destroy(sp: *mut ScratchSpace); 169 | 170 | // Generator 171 | pub fn secp256k1_generator_generate(cx: *const Context, 172 | gen: *mut Generator, 173 | seed32: *const c_uchar) 174 | -> c_int; 175 | 176 | // TODO secp256k1_context_set_illegal_callback 177 | // TODO secp256k1_context_set_error_callback 178 | // (Actually, I don't really want these exposed; if either of these 179 | // are ever triggered it indicates a bug in rust-secp256k1, since 180 | // one goal is to use Rust's type system to eliminate all possible 181 | // bad inputs.) 182 | 183 | // Pubkeys 184 | pub fn secp256k1_ec_pubkey_parse(cx: *const Context, pk: *mut PublicKey, 185 | input: *const c_uchar, in_len: size_t) 186 | -> c_int; 187 | 188 | pub fn secp256k1_ec_pubkey_serialize(cx: *const Context, output: *const c_uchar, 189 | out_len: *mut size_t, pk: *const PublicKey, 190 | compressed: c_uint) 191 | -> c_int; 192 | 193 | // Signatures 194 | pub fn secp256k1_ecdsa_signature_parse_der(cx: *const Context, sig: *mut Signature, 195 | input: *const c_uchar, in_len: size_t) 196 | -> c_int; 197 | 198 | pub fn secp256k1_ecdsa_signature_parse_compact(cx: *const Context, sig: *mut Signature, 199 | input64: *const c_uchar) 200 | -> c_int; 201 | 202 | pub fn ecdsa_signature_parse_der_lax(cx: *const Context, sig: *mut Signature, 203 | input: *const c_uchar, in_len: size_t) 204 | -> c_int; 205 | 206 | pub fn secp256k1_ecdsa_signature_serialize_der(cx: *const Context, output: *const c_uchar, 207 | out_len: *mut size_t, sig: *const Signature) 208 | -> c_int; 209 | 210 | pub fn secp256k1_ecdsa_signature_serialize_compact(cx: *const Context, output64: *const c_uchar, 211 | sig: *const Signature) 212 | -> c_int; 213 | 214 | pub fn secp256k1_ecdsa_recoverable_signature_parse_compact(cx: *const Context, sig: *mut RecoverableSignature, 215 | input64: *const c_uchar, recid: c_int) 216 | -> c_int; 217 | 218 | pub fn secp256k1_ecdsa_recoverable_signature_serialize_compact(cx: *const Context, output64: *const c_uchar, 219 | recid: *mut c_int, sig: *const RecoverableSignature) 220 | -> c_int; 221 | 222 | pub fn secp256k1_ecdsa_recoverable_signature_convert(cx: *const Context, sig: *mut Signature, 223 | input: *const RecoverableSignature) 224 | -> c_int; 225 | 226 | pub fn secp256k1_ecdsa_signature_normalize(cx: *const Context, out_sig: *mut Signature, 227 | in_sig: *const Signature) 228 | -> c_int; 229 | 230 | // ECDSA 231 | pub fn secp256k1_ecdsa_verify(cx: *const Context, 232 | sig: *const Signature, 233 | msg32: *const c_uchar, 234 | pk: *const PublicKey) 235 | -> c_int; 236 | 237 | pub fn secp256k1_ecdsa_sign(cx: *const Context, 238 | sig: *mut Signature, 239 | msg32: *const c_uchar, 240 | sk: *const c_uchar, 241 | noncefn: NonceFn, 242 | noncedata: *const c_void) 243 | -> c_int; 244 | 245 | pub fn secp256k1_ecdsa_sign_recoverable(cx: *const Context, 246 | sig: *mut RecoverableSignature, 247 | msg32: *const c_uchar, 248 | sk: *const c_uchar, 249 | noncefn: NonceFn, 250 | noncedata: *const c_void) 251 | -> c_int; 252 | 253 | pub fn secp256k1_ecdsa_recover(cx: *const Context, 254 | pk: *mut PublicKey, 255 | sig: *const RecoverableSignature, 256 | msg32: *const c_uchar) 257 | -> c_int; 258 | // AGGSIG (Schnorr) Multisig 259 | pub fn secp256k1_aggsig_context_create(cx: *const Context, 260 | pks: *const PublicKey, 261 | n_pks: size_t, 262 | seed32: *const c_uchar) 263 | -> *mut AggSigContext; 264 | 265 | pub fn secp256k1_aggsig_context_destroy(aggctx: *mut AggSigContext); 266 | 267 | pub fn secp256k1_aggsig_generate_nonce(cx: *const Context, 268 | aggctx: *mut AggSigContext, 269 | index: size_t) 270 | -> c_int; 271 | 272 | pub fn secp256k1_aggsig_partial_sign(cx: *const Context, 273 | aggctx: *mut AggSigContext, 274 | sig: *mut AggSigPartialSignature, 275 | msghash32: *const c_uchar, 276 | seckey32: *const c_uchar, 277 | index: size_t) 278 | -> c_int; 279 | 280 | pub fn secp256k1_aggsig_combine_signatures(cx: *const Context, 281 | aggctx: *mut AggSigContext, 282 | sig64: *mut Signature, 283 | partial: *const AggSigPartialSignature, 284 | index: size_t) 285 | -> c_int; 286 | 287 | pub fn secp256k1_aggsig_build_scratch_and_verify(cx: *const Context, 288 | sig64: *const Signature, 289 | msg32: *const c_uchar, 290 | pks: *const PublicKey, 291 | n_pubkeys: size_t) 292 | -> c_int; 293 | 294 | // AGGSIG (single sig or single-signer Schnorr) 295 | pub fn secp256k1_aggsig_export_secnonce_single(cx: *const Context, 296 | secnonce32: *mut c_uchar, 297 | seed32: *const c_uchar) 298 | -> c_int; 299 | 300 | pub fn secp256k1_aggsig_sign_single(cx: *const Context, 301 | sig: *mut Signature, 302 | msg32: *const c_uchar, 303 | seckey32: *const c_uchar, 304 | secnonce32: *const c_uchar, 305 | extra32: *const c_uchar, 306 | pubnonce_for_e: *const PublicKey, 307 | pubnonce_total: *const PublicKey, 308 | pubkey_for_e: *const PublicKey, 309 | seed32: *const c_uchar) 310 | -> c_int; 311 | 312 | pub fn secp256k1_aggsig_verify_single(cx: *const Context, 313 | sig: *const Signature, 314 | msg32: *const c_uchar, 315 | pubnonce: *const PublicKey, 316 | pk: *const PublicKey, 317 | pk_total: *const PublicKey, 318 | extra_pubkey: *const PublicKey, 319 | is_partial: c_uint) 320 | -> c_int; 321 | 322 | pub fn secp256k1_schnorrsig_verify_batch(cx: *const Context, 323 | scratch: *mut ScratchSpace, 324 | sig: *const *const c_uchar, 325 | msg32: *const *const c_uchar, 326 | pk: *const *const PublicKey, 327 | n_sigs: size_t) 328 | -> c_int; 329 | 330 | pub fn secp256k1_aggsig_add_signatures_single(cx: *const Context, 331 | ret_sig: *mut Signature, 332 | sigs: *const *const c_uchar, 333 | num_sigs: size_t, 334 | pubnonce_total: *const PublicKey) 335 | -> c_int; 336 | 337 | pub fn secp256k1_aggsig_subtract_partial_signature(cx: *const Context, 338 | ret_partsig: *mut Signature, 339 | ret_partsig_alt: *mut Signature, 340 | sig: *const Signature, 341 | part_sig: *const Signature) 342 | -> c_int; 343 | 344 | // EC 345 | pub fn secp256k1_ec_seckey_verify(cx: *const Context, 346 | sk: *const c_uchar) -> c_int; 347 | 348 | pub fn secp256k1_ec_pubkey_create(cx: *const Context, pk: *mut PublicKey, 349 | sk: *const c_uchar) -> c_int; 350 | 351 | //TODO secp256k1_ec_privkey_export 352 | //TODO secp256k1_ec_privkey_import 353 | 354 | pub fn secp256k1_ec_privkey_tweak_add(cx: *const Context, 355 | sk: *mut c_uchar, 356 | tweak: *const c_uchar) 357 | -> c_int; 358 | 359 | pub fn secp256k1_ec_pubkey_tweak_add(cx: *const Context, 360 | pk: *mut PublicKey, 361 | tweak: *const c_uchar) 362 | -> c_int; 363 | 364 | pub fn secp256k1_ec_privkey_tweak_mul(cx: *const Context, 365 | sk: *mut c_uchar, 366 | tweak: *const c_uchar) 367 | -> c_int; 368 | 369 | pub fn secp256k1_ec_pubkey_tweak_mul(cx: *const Context, 370 | pk: *mut PublicKey, 371 | tweak: *const c_uchar) 372 | -> c_int; 373 | 374 | pub fn secp256k1_ec_pubkey_combine(cx: *const Context, 375 | out: *mut PublicKey, 376 | ins: *const *const PublicKey, 377 | n: c_int) 378 | -> c_int; 379 | 380 | pub fn secp256k1_ec_privkey_tweak_inv(cx: *const Context, 381 | sk: *mut c_uchar) 382 | -> c_int; 383 | 384 | pub fn secp256k1_ec_privkey_tweak_neg(cx: *const Context, 385 | sk: *mut c_uchar) 386 | -> c_int; 387 | 388 | pub fn secp256k1_ecdh(cx: *const Context, 389 | out: *mut SharedSecret, 390 | point: *const PublicKey, 391 | scalar: *const c_uchar) 392 | -> c_int; 393 | 394 | // Parse a 33-byte commitment into 64 byte internal commitment object 395 | pub fn secp256k1_pedersen_commitment_parse(cx: *const Context, 396 | commit: *mut c_uchar, 397 | input: *const c_uchar) 398 | -> c_int; 399 | 400 | // Serialize a 64-byte commit object into a 33 byte serialized byte sequence 401 | pub fn secp256k1_pedersen_commitment_serialize(cx: *const Context, 402 | output: *mut c_uchar, 403 | commit: *const c_uchar) 404 | -> c_int; 405 | 406 | 407 | // Generates a pedersen commitment: *commit = blind * G + value * G2. 408 | // The commitment is 33 bytes, the blinding factor is 32 bytes. 409 | pub fn secp256k1_pedersen_commit( 410 | ctx: *const Context, 411 | commit: *mut c_uchar, 412 | blind: *const c_uchar, 413 | value: u64, 414 | value_gen: *const c_uchar, 415 | blind_gen: *const c_uchar 416 | ) -> c_int; 417 | 418 | // Generates a pedersen commitment: *commit = blind * G + value * G2. 419 | // The commitment is 33 bytes, the blinding factor and the value are 32 bytes. 420 | pub fn secp256k1_pedersen_blind_commit( 421 | ctx: *const Context, 422 | commit: *mut c_uchar, 423 | blind: *const c_uchar, 424 | value: *const c_uchar, 425 | value_gen: *const c_uchar, 426 | blind_gen: *const c_uchar 427 | ) -> c_int; 428 | 429 | // Get the public key of a pedersen commitment 430 | pub fn secp256k1_pedersen_commitment_to_pubkey( 431 | cx: *const Context, pk: *mut PublicKey, 432 | commit: *const c_uchar) -> c_int; 433 | 434 | // Get a pedersen commitment from a pubkey 435 | pub fn secp256k1_pubkey_to_pedersen_commitment( 436 | cx: *const Context, commit: *mut c_uchar, 437 | pk: *const PublicKey) -> c_int; 438 | 439 | // Takes a list of n pointers to 32 byte blinding values, the first negs 440 | // of which are treated with positive sign and the rest negative, then 441 | // calculates an additional blinding value that adds to zero. 442 | pub fn secp256k1_pedersen_blind_sum( 443 | ctx: *const Context, 444 | blind_out: *const c_uchar, 445 | blinds: *const *const c_uchar, 446 | n: size_t, 447 | npositive: size_t 448 | ) -> c_int; 449 | 450 | // Takes two list of 64-byte commitments and sums the first set, subtracts 451 | // the second and returns the resulting commitment. 452 | pub fn secp256k1_pedersen_commit_sum( 453 | ctx: *const Context, 454 | commit_out: *const c_uchar, 455 | commits: *const *const c_uchar, 456 | pcnt: size_t, 457 | ncommits: *const *const c_uchar, 458 | ncnt: size_t 459 | ) -> c_int; 460 | 461 | // Calculate blinding factor for switch commitment x + H(xG+vH | xJ) 462 | pub fn secp256k1_blind_switch( 463 | ctx: *const Context, 464 | blind_switch: *mut c_uchar, 465 | blind: *const c_uchar, 466 | value: u64, 467 | value_gen: *const c_uchar, 468 | blind_gen: *const c_uchar, 469 | switch_pubkey: *const c_uchar 470 | ) -> c_int; 471 | 472 | // Takes two list of 64-byte commitments and sums the first set and 473 | // subtracts the second and verifies that they sum to 0. 474 | pub fn secp256k1_pedersen_verify_tally(ctx: *const Context, 475 | commits: *const *const c_uchar, 476 | pcnt: size_t, 477 | ncommits: *const *const c_uchar, 478 | ncnt: size_t 479 | ) -> c_int; 480 | 481 | pub fn secp256k1_rangeproof_info( 482 | ctx: *const Context, 483 | exp: *mut c_int, 484 | mantissa: *mut c_int, 485 | min_value: *mut u64, 486 | max_value: *mut u64, 487 | proof: *const c_uchar, 488 | plen: size_t 489 | ) -> c_int; 490 | 491 | pub fn secp256k1_rangeproof_rewind( 492 | ctx: *const Context, 493 | blind_out: *mut c_uchar, 494 | value_out: *mut u64, 495 | message_out: *mut c_uchar, 496 | outlen: *mut size_t, 497 | nonce: *const c_uchar, 498 | min_value: *mut u64, 499 | max_value: *mut u64, 500 | commit: *const c_uchar, 501 | proof: *const c_uchar, 502 | plen: size_t, 503 | extra_commit: *const c_uchar, 504 | extra_commit_len: size_t, 505 | gen: *const c_uchar 506 | ) -> c_int; 507 | 508 | pub fn secp256k1_rangeproof_verify( 509 | ctx: *const Context, 510 | min_value: &mut u64, 511 | max_value: &mut u64, 512 | commit: *const c_uchar, 513 | proof: *const c_uchar, 514 | plen: size_t, 515 | extra_commit: *const c_uchar, 516 | extra_commit_len: size_t, 517 | gen: *const c_uchar 518 | ) -> c_int; 519 | 520 | pub fn secp256k1_rangeproof_sign( 521 | ctx: *const Context, 522 | proof: *mut c_uchar, 523 | plen: *mut size_t, 524 | min_value: u64, 525 | commit: *const c_uchar, 526 | blind: *const c_uchar, 527 | nonce: *const c_uchar, 528 | exp: c_int, 529 | min_bits: c_int, 530 | value: u64, 531 | message: *const c_uchar, 532 | msg_len: size_t, 533 | extra_commit: *const c_uchar, 534 | extra_commit_len: size_t, 535 | gen: *const c_uchar 536 | ) -> c_int; 537 | 538 | pub fn secp256k1_bulletproof_generators_create( 539 | ctx: *const Context, 540 | blinding_gen: *const c_uchar, 541 | n: size_t, 542 | ) -> *mut BulletproofGenerators; 543 | 544 | pub fn secp256k1_bulletproof_generators_destroy( 545 | ctx: *const Context, 546 | gen: *mut BulletproofGenerators, 547 | ); 548 | 549 | pub fn secp256k1_bulletproof_rangeproof_prove( 550 | ctx: *const Context, 551 | scratch: *mut ScratchSpace, 552 | gens: *const BulletproofGenerators, 553 | proof: *mut c_uchar, 554 | plen: *mut size_t, 555 | tau_x: *mut c_uchar, 556 | t_one: *mut PublicKey, 557 | t_two: *mut PublicKey, 558 | value: *const u64, 559 | min_value: *const u64, 560 | blind: *const *const c_uchar, 561 | commits: *const *const c_uchar, 562 | n_commits: size_t, 563 | value_gen: *const c_uchar, 564 | nbits: size_t, 565 | nonce: *const c_uchar, 566 | private_nonce: *const c_uchar, 567 | extra_commit: *const c_uchar, 568 | extra_commit_len: size_t, 569 | message: *const c_uchar, 570 | ) -> c_int; 571 | 572 | pub fn secp256k1_bulletproof_rangeproof_verify( 573 | ctx: *const Context, 574 | scratch: *mut ScratchSpace, 575 | gens: *const BulletproofGenerators, 576 | proof: *const c_uchar, 577 | plen: size_t, 578 | min_value: *const u64, 579 | commit: *const c_uchar, 580 | n_commits: size_t, 581 | nbits: size_t, 582 | value_gen: *const c_uchar, 583 | extra_commit: *const c_uchar, 584 | extra_commit_len: size_t 585 | ) -> c_int; 586 | 587 | pub fn secp256k1_bulletproof_rangeproof_verify_multi( 588 | ctx: *const Context, 589 | scratch: *mut ScratchSpace, 590 | gens: *const BulletproofGenerators, 591 | proofs: *const *const c_uchar, 592 | n_proofs: size_t, 593 | plen: size_t, 594 | min_value: *const *const u64, 595 | commits: *const *const c_uchar, 596 | n_commits: size_t, 597 | nbits: size_t, 598 | value_gen: *const c_uchar, 599 | extra_commit: *const *const c_uchar, 600 | extra_commit_len: *const size_t 601 | ) -> c_int; 602 | 603 | pub fn secp256k1_bulletproof_rangeproof_rewind( 604 | ctx: *const Context, 605 | value: *mut u64, 606 | blind: *mut c_uchar, 607 | proof: *const c_uchar, 608 | plen: size_t, 609 | min_value: u64, 610 | commit: *const c_uchar, 611 | value_gen: *const c_uchar, 612 | nonce: *const c_uchar, 613 | extra_commit: *const c_uchar, 614 | extra_commit_len: size_t, 615 | message: *mut c_uchar, 616 | ) -> c_int; 617 | } 618 | -------------------------------------------------------------------------------- /src/key.rs: -------------------------------------------------------------------------------- 1 | // Bitcoin secp256k1 bindings 2 | // Written in 2014 by 3 | // Dawid Ciężarkiewicz 4 | // Andrew Poelstra 5 | // 6 | // To the extent possible under law, the author(s) have dedicated all 7 | // copyright and related and neighboring rights to this software to 8 | // the public domain worldwide. This software is distributed without 9 | // any warranty. 10 | // 11 | // You should have received a copy of the CC0 Public Domain Dedication 12 | // along with this software. 13 | // If not, see . 14 | // 15 | 16 | //! # Public and secret keys 17 | 18 | use std::marker; 19 | use arrayvec::ArrayVec; 20 | use rand::Rng; 21 | use serde::{Serialize, Deserialize, Serializer, Deserializer}; 22 | 23 | use super::{Secp256k1, ContextFlag}; 24 | use super::Error::{self, IncapableContext, InvalidPublicKey, InvalidSecretKey}; 25 | use crate::constants; 26 | use crate::ffi; 27 | 28 | use zeroize::Zeroize; 29 | 30 | /// Secret 256-bit key used as `x` in an ECDSA signature 31 | #[derive(Zeroize)] 32 | #[zeroize(drop)] 33 | pub struct SecretKey(pub [u8; constants::SECRET_KEY_SIZE]); 34 | impl_array_newtype!(SecretKey, u8, constants::SECRET_KEY_SIZE); 35 | impl_pretty_debug!(SecretKey); 36 | 37 | /// The number 1 encoded as a secret key 38 | /// Deprecated; `static` is not what I want; use `ONE_KEY` instead 39 | pub static ONE: SecretKey = SecretKey([0, 0, 0, 0, 0, 0, 0, 0, 40 | 0, 0, 0, 0, 0, 0, 0, 0, 41 | 0, 0, 0, 0, 0, 0, 0, 0, 42 | 0, 0, 0, 0, 0, 0, 0, 1]); 43 | 44 | /// The number 0 encoded as a secret key 45 | pub const ZERO_KEY: SecretKey = SecretKey([0, 0, 0, 0, 0, 0, 0, 0, 46 | 0, 0, 0, 0, 0, 0, 0, 0, 47 | 0, 0, 0, 0, 0, 0, 0, 0, 48 | 0, 0, 0, 0, 0, 0, 0, 0]); 49 | 50 | /// The number 1 encoded as a secret key 51 | pub const ONE_KEY: SecretKey = SecretKey([0, 0, 0, 0, 0, 0, 0, 0, 52 | 0, 0, 0, 0, 0, 0, 0, 0, 53 | 0, 0, 0, 0, 0, 0, 0, 0, 54 | 0, 0, 0, 0, 0, 0, 0, 1]); 55 | 56 | /// A Secp256k1 public key, used for verification of signatures 57 | #[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Hash)] 58 | pub struct PublicKey(pub ffi::PublicKey); 59 | 60 | 61 | fn random_32_bytes(rng: &mut R) -> [u8; 32] { 62 | let mut ret = [0u8; 32]; 63 | rng.fill(&mut ret); 64 | ret 65 | } 66 | 67 | impl SecretKey { 68 | /// Creates a new random secret key 69 | #[inline] 70 | pub fn new(secp: &Secp256k1, rng: &mut R) -> SecretKey { 71 | let mut data = random_32_bytes(rng); 72 | unsafe { 73 | while ffi::secp256k1_ec_seckey_verify(secp.ctx, data.as_ptr()) == 0 { 74 | data = random_32_bytes(rng); 75 | } 76 | } 77 | SecretKey(data) 78 | } 79 | 80 | /// Converts a `SECRET_KEY_SIZE`-byte slice to a secret key 81 | #[inline] 82 | pub fn from_slice(secp: &Secp256k1, data: &[u8]) 83 | -> Result { 84 | match data.len() { 85 | constants::SECRET_KEY_SIZE => { 86 | let mut ret = [0; constants::SECRET_KEY_SIZE]; 87 | unsafe { 88 | if ffi::secp256k1_ec_seckey_verify(secp.ctx, data.as_ptr()) == 0 { 89 | return Err(InvalidSecretKey); 90 | } 91 | } 92 | ret[..].copy_from_slice(data); 93 | Ok(SecretKey(ret)) 94 | } 95 | _ => Err(InvalidSecretKey) 96 | } 97 | } 98 | 99 | #[inline] 100 | /// Adds one secret key to another, modulo the curve order 101 | pub fn add_assign(&mut self, secp: &Secp256k1, other: &SecretKey) 102 | -> Result<(), Error> { 103 | unsafe { 104 | if ffi::secp256k1_ec_privkey_tweak_add(secp.ctx, self.as_mut_ptr(), other.as_ptr()) != 1 { 105 | Err(InvalidSecretKey) 106 | } else { 107 | Ok(()) 108 | } 109 | } 110 | } 111 | 112 | #[inline] 113 | /// Multiplies one secret key by another, modulo the curve order 114 | pub fn mul_assign(&mut self, secp: &Secp256k1, other: &SecretKey) 115 | -> Result<(), Error> { 116 | unsafe { 117 | if ffi::secp256k1_ec_privkey_tweak_mul(secp.ctx, self.as_mut_ptr(), other.as_ptr()) != 1 { 118 | Err(InvalidSecretKey) 119 | } else { 120 | Ok(()) 121 | } 122 | } 123 | } 124 | 125 | #[inline] 126 | /// Inverses the secret key 127 | pub fn inv_assign(&mut self, secp: &Secp256k1) 128 | -> Result<(), Error> { 129 | unsafe { 130 | if ffi::secp256k1_ec_privkey_tweak_inv(secp.ctx, self.as_mut_ptr()) != 1 { 131 | Err(InvalidSecretKey) 132 | } else { 133 | Ok(()) 134 | } 135 | } 136 | } 137 | 138 | #[inline] 139 | /// Negates the secret key 140 | pub fn neg_assign(&mut self, secp: &Secp256k1) 141 | -> Result<(), Error> { 142 | unsafe { 143 | if ffi::secp256k1_ec_privkey_tweak_neg(secp.ctx, self.as_mut_ptr()) != 1 { 144 | Err(InvalidSecretKey) 145 | } else { 146 | Ok(()) 147 | } 148 | } 149 | } 150 | } 151 | 152 | impl PublicKey { 153 | /// Creates a new zeroed out public key 154 | #[inline] 155 | pub fn new() -> PublicKey { 156 | PublicKey(ffi::PublicKey::new()) 157 | } 158 | 159 | /// Creates a new public key as the sum of the provided keys 160 | pub fn from_combination(secp: &Secp256k1, in_keys: Vec<&PublicKey>) 161 | -> Result { 162 | let mut retkey = PublicKey::new(); 163 | if secp.caps == ContextFlag::SignOnly || secp.caps == ContextFlag::None { 164 | return Err(IncapableContext); 165 | } 166 | let in_vec:Vec<*const ffi::PublicKey> = in_keys.iter() 167 | .map(|pk| pk.as_ptr()) 168 | .collect(); 169 | unsafe { 170 | if ffi::secp256k1_ec_pubkey_combine(secp.ctx, &mut retkey.0 as *mut _, 171 | in_vec.as_ptr(), in_vec.len() as i32) == 1 { 172 | Ok(retkey) 173 | } else { 174 | Err(InvalidPublicKey) 175 | } 176 | } 177 | } 178 | 179 | /// Determines whether a pubkey is valid 180 | #[inline] 181 | pub fn is_valid(&self) -> bool { 182 | // The only invalid pubkey the API should be able to create is 183 | // the zero one. 184 | self.0[..].iter().any(|&x| x != 0) 185 | } 186 | 187 | /// Obtains a raw pointer suitable for use with FFI functions 188 | #[inline] 189 | pub fn as_ptr(&self) -> *const ffi::PublicKey { 190 | &self.0 as *const _ 191 | } 192 | 193 | /// Obtains a mutable raw pointer suitable for use with FFI functions 194 | #[inline] 195 | pub fn as_mut_ptr(&mut self) -> *mut ffi::PublicKey { 196 | &mut self.0 as *mut _ 197 | } 198 | 199 | /// Creates a new public key from a Secp256k1 public key 200 | #[inline] 201 | pub fn from_secp256k1_pubkey(pk: ffi::PublicKey) -> PublicKey { PublicKey(pk) } 202 | 203 | /// Creates a new public key from a secret key. 204 | #[inline] 205 | pub fn from_secret_key(secp: &Secp256k1, 206 | sk: &SecretKey) 207 | -> Result { 208 | if secp.caps == ContextFlag::VerifyOnly || secp.caps == ContextFlag::None { 209 | return Err(IncapableContext); 210 | } 211 | let mut pk = unsafe { ffi::PublicKey::blank() }; 212 | unsafe { 213 | // We can assume the return value because it's not possible to construct 214 | // an invalid `SecretKey` without transmute trickery or something 215 | let res = ffi::secp256k1_ec_pubkey_create(secp.ctx, &mut pk, sk.as_ptr()); 216 | debug_assert_eq!(res, 1); 217 | } 218 | Ok(PublicKey(pk)) 219 | } 220 | 221 | /// Creates a public key directly from a slice 222 | #[inline] 223 | pub fn from_slice(secp: &Secp256k1, data: &[u8]) 224 | -> Result { 225 | let mut pk = unsafe { ffi::PublicKey::blank() }; 226 | unsafe { 227 | if ffi::secp256k1_ec_pubkey_parse(secp.ctx, &mut pk, data.as_ptr(), 228 | data.len() as ::libc::size_t) == 1 { 229 | Ok(PublicKey(pk)) 230 | } else { 231 | Err(InvalidPublicKey) 232 | } 233 | } 234 | } 235 | 236 | #[inline] 237 | /// Serialize the key as a byte-encoded pair of values. In compressed form 238 | /// the y-coordinate is represented by only a single bit, as x determines 239 | /// it up to one bit. 240 | pub fn serialize_vec(&self, secp: &Secp256k1, compressed: bool) -> ArrayVec { 241 | let mut ret = ArrayVec::new(); 242 | 243 | unsafe { 244 | let mut ret_len = constants::PUBLIC_KEY_SIZE as ::libc::size_t; 245 | let compressed = if compressed { ffi::SECP256K1_SER_COMPRESSED } else { ffi::SECP256K1_SER_UNCOMPRESSED }; 246 | let err = ffi::secp256k1_ec_pubkey_serialize(secp.ctx, ret.as_ptr(), 247 | &mut ret_len, self.as_ptr(), 248 | compressed); 249 | debug_assert_eq!(err, 1); 250 | ret.set_len(ret_len as usize); 251 | } 252 | ret 253 | } 254 | 255 | #[inline] 256 | /// Adds the pk corresponding to `other` to the pk `self` in place 257 | pub fn add_exp_assign(&mut self, secp: &Secp256k1, other: &SecretKey) 258 | -> Result<(), Error> { 259 | if secp.caps == ContextFlag::SignOnly || secp.caps == ContextFlag::None { 260 | return Err(IncapableContext); 261 | } 262 | unsafe { 263 | if ffi::secp256k1_ec_pubkey_tweak_add(secp.ctx, &mut self.0 as *mut _, 264 | other.as_ptr()) == 1 { 265 | Ok(()) 266 | } else { 267 | Err(InvalidSecretKey) 268 | } 269 | } 270 | } 271 | 272 | #[inline] 273 | /// Muliplies the pk `self` in place by the scalar `other` 274 | pub fn mul_assign(&mut self, secp: &Secp256k1, other: &SecretKey) 275 | -> Result<(), Error> { 276 | if secp.caps == ContextFlag::SignOnly || secp.caps == ContextFlag::None { 277 | return Err(IncapableContext); 278 | } 279 | unsafe { 280 | if ffi::secp256k1_ec_pubkey_tweak_mul(secp.ctx, &mut self.0 as *mut _, 281 | other.as_ptr()) == 1 { 282 | Ok(()) 283 | } else { 284 | Err(InvalidSecretKey) 285 | } 286 | } 287 | } 288 | } 289 | 290 | 291 | /// Creates a new public key from a FFI public key 292 | impl From for PublicKey { 293 | #[inline] 294 | fn from(pk: ffi::PublicKey) -> PublicKey { 295 | PublicKey(pk) 296 | } 297 | } 298 | 299 | impl<'de> Deserialize<'de> for PublicKey { 300 | fn deserialize(d: D) -> Result 301 | where D: Deserializer<'de> 302 | { 303 | use serde::de; 304 | struct Visitor { 305 | marker: marker::PhantomData, 306 | } 307 | impl<'de> de::Visitor<'de> for Visitor { 308 | type Value = PublicKey; 309 | 310 | #[inline] 311 | fn visit_seq(self, mut a: A) -> Result 312 | where A: de::SeqAccess<'de> 313 | { 314 | debug_assert!(constants::UNCOMPRESSED_PUBLIC_KEY_SIZE >= constants::COMPRESSED_PUBLIC_KEY_SIZE); 315 | 316 | let s = Secp256k1::with_caps(crate::ContextFlag::None); 317 | unsafe { 318 | use std::mem; 319 | let mut ret: [u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE] = mem::MaybeUninit::uninit().assume_init(); 320 | 321 | let mut read_len = 0; 322 | while read_len < constants::UNCOMPRESSED_PUBLIC_KEY_SIZE { 323 | let read_ch = match a.next_element()? { 324 | Some(c) => c, 325 | None => break 326 | }; 327 | ret[read_len] = read_ch; 328 | read_len += 1; 329 | } 330 | let one_after_last : Option = a.next_element()?; 331 | if one_after_last.is_some() { 332 | return Err(de::Error::invalid_length(read_len + 1, &self)); 333 | } 334 | 335 | match read_len { 336 | constants::UNCOMPRESSED_PUBLIC_KEY_SIZE | constants::COMPRESSED_PUBLIC_KEY_SIZE 337 | => PublicKey::from_slice(&s, &ret[..read_len]).map_err( 338 | |e| match e { 339 | InvalidPublicKey => de::Error::invalid_value(de::Unexpected::Seq, &self), 340 | _ => de::Error::custom(&e.to_string()), 341 | } 342 | ), 343 | _ => Err(de::Error::invalid_length(read_len, &self)), 344 | } 345 | } 346 | } 347 | 348 | fn expecting(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 349 | write!(f, "a sequence of {} or {} bytes representing a valid compressed or uncompressed public key", 350 | constants::COMPRESSED_PUBLIC_KEY_SIZE, constants::UNCOMPRESSED_PUBLIC_KEY_SIZE) 351 | } 352 | } 353 | 354 | // Begin actual function 355 | d.deserialize_seq(Visitor { marker: ::std::marker::PhantomData }) 356 | } 357 | } 358 | 359 | impl Serialize for PublicKey { 360 | fn serialize(&self, s: S) -> Result 361 | where S: Serializer 362 | { 363 | let secp = Secp256k1::with_caps(crate::ContextFlag::None); 364 | (&self.serialize_vec(&secp, true)[..]).serialize(s) 365 | } 366 | } 367 | 368 | #[cfg(test)] 369 | mod test { 370 | extern crate rand_core; 371 | use super::super::{Secp256k1, ContextFlag}; 372 | use super::super::Error::{InvalidPublicKey, InvalidSecretKey, IncapableContext}; 373 | use super::{PublicKey, SecretKey}; 374 | use super::super::constants; 375 | 376 | use rand::{Error, RngCore, thread_rng}; 377 | use self::rand_core::impls; 378 | 379 | use std::slice::from_raw_parts; 380 | use crate::key::ONE_KEY; 381 | 382 | // This tests cleaning of SecretKey (e.g. secret key) on Drop. 383 | // To make this test fail, just remove `Zeroize` derive from `SecretKey` definition. 384 | #[test] 385 | fn skey_clear_on_drop() { 386 | let s = Secp256k1::new(); 387 | 388 | // Create buffer for blinding factor filled with non-zero bytes. 389 | let sk_bytes = ONE_KEY; 390 | let ptr = { 391 | // Fill blinding factor with some "sensitive" data. 392 | let sk = SecretKey::from_slice(&s, &sk_bytes[..]).unwrap(); 393 | sk.0.as_ptr() 394 | 395 | // -- after this line SecretKey should be zeroed. 396 | }; 397 | 398 | // Unsafely get data from where SecretKey was in memory. Should be all zeros. 399 | let sk_bytes = unsafe { from_raw_parts(ptr, constants::SECRET_KEY_SIZE) }; 400 | 401 | // There should be all zeroes. 402 | let mut all_zeros = true; 403 | for b in sk_bytes { 404 | if *b != 0x00 { 405 | all_zeros = false; 406 | } 407 | } 408 | 409 | assert!(all_zeros) 410 | } 411 | 412 | #[test] 413 | fn skey_from_slice() { 414 | let s = Secp256k1::new(); 415 | let sk = SecretKey::from_slice(&s, &[1; 31]); 416 | assert_eq!(sk, Err(InvalidSecretKey)); 417 | 418 | let sk = SecretKey::from_slice(&s, &[1; 32]); 419 | assert!(sk.is_ok()); 420 | } 421 | 422 | #[test] 423 | fn pubkey_from_slice() { 424 | let s = Secp256k1::new(); 425 | assert_eq!(PublicKey::from_slice(&s, &[]), Err(InvalidPublicKey)); 426 | assert_eq!(PublicKey::from_slice(&s, &[1, 2, 3]), Err(InvalidPublicKey)); 427 | 428 | let uncompressed = PublicKey::from_slice(&s, &[4, 54, 57, 149, 239, 162, 148, 175, 246, 254, 239, 75, 154, 152, 10, 82, 234, 224, 85, 220, 40, 100, 57, 121, 30, 162, 94, 156, 135, 67, 74, 49, 179, 57, 236, 53, 162, 124, 149, 144, 168, 77, 74, 30, 72, 211, 229, 110, 111, 55, 96, 193, 86, 227, 183, 152, 195, 155, 51, 247, 123, 113, 60, 228, 188]); 429 | assert!(uncompressed.is_ok()); 430 | 431 | let compressed = PublicKey::from_slice(&s, &[3, 23, 183, 225, 206, 31, 159, 148, 195, 42, 67, 115, 146, 41, 248, 140, 11, 3, 51, 41, 111, 180, 110, 143, 114, 134, 88, 73, 198, 174, 52, 184, 78]); 432 | assert!(compressed.is_ok()); 433 | } 434 | 435 | #[test] 436 | fn keypair_slice_round_trip() { 437 | let s = Secp256k1::new(); 438 | 439 | let (sk1, pk1) = s.generate_keypair(&mut thread_rng()).unwrap(); 440 | assert_eq!(SecretKey::from_slice(&s, &sk1[..]), Ok(sk1)); 441 | assert_eq!(PublicKey::from_slice(&s, &pk1.serialize_vec(&s, true)[..]), Ok(pk1)); 442 | assert_eq!(PublicKey::from_slice(&s, &pk1.serialize_vec(&s, false)[..]), Ok(pk1)); 443 | } 444 | 445 | #[test] 446 | fn invalid_secret_key() { 447 | let s = Secp256k1::new(); 448 | // Zero 449 | assert_eq!(SecretKey::from_slice(&s, &[0; 32]), Err(InvalidSecretKey)); 450 | // -1 451 | assert_eq!(SecretKey::from_slice(&s, &[0xff; 32]), Err(InvalidSecretKey)); 452 | // Top of range 453 | assert!(SecretKey::from_slice(&s, 454 | &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 455 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 456 | 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 457 | 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x40]).is_ok()); 458 | // One past top of range 459 | assert!(SecretKey::from_slice(&s, 460 | &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 461 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 462 | 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 463 | 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41]).is_err()); 464 | } 465 | 466 | #[test] 467 | fn test_pubkey_from_slice_bad_context() { 468 | let s = Secp256k1::without_caps(); 469 | let sk = SecretKey::new(&s, &mut thread_rng()); 470 | assert_eq!(PublicKey::from_secret_key(&s, &sk), Err(IncapableContext)); 471 | 472 | let s = Secp256k1::with_caps(ContextFlag::VerifyOnly); 473 | assert_eq!(PublicKey::from_secret_key(&s, &sk), Err(IncapableContext)); 474 | 475 | let s = Secp256k1::with_caps(ContextFlag::SignOnly); 476 | assert!(PublicKey::from_secret_key(&s, &sk).is_ok()); 477 | 478 | let s = Secp256k1::with_caps(ContextFlag::Full); 479 | assert!(PublicKey::from_secret_key(&s, &sk).is_ok()); 480 | } 481 | 482 | #[test] 483 | fn test_add_exp_bad_context() { 484 | let s = Secp256k1::with_caps(ContextFlag::Full); 485 | let (sk, mut pk) = s.generate_keypair(&mut thread_rng()).unwrap(); 486 | 487 | assert!(pk.add_exp_assign(&s, &sk).is_ok()); 488 | 489 | let s = Secp256k1::with_caps(ContextFlag::VerifyOnly); 490 | assert!(pk.add_exp_assign(&s, &sk).is_ok()); 491 | 492 | let s = Secp256k1::with_caps(ContextFlag::SignOnly); 493 | assert_eq!(pk.add_exp_assign(&s, &sk), Err(IncapableContext)); 494 | 495 | let s = Secp256k1::with_caps(ContextFlag::None); 496 | assert_eq!(pk.add_exp_assign(&s, &sk), Err(IncapableContext)); 497 | } 498 | 499 | #[test] 500 | fn test_bad_serde_deserialize() { 501 | use serde::Deserialize; 502 | use crate::json; 503 | 504 | // Invalid length 505 | let zero31 = "[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]"; 506 | let mut json = json::de::Deserializer::from_str(zero31); 507 | assert!(::deserialize(&mut json).is_err()); 508 | let mut json = json::de::Deserializer::from_str(zero31); 509 | assert!(::deserialize(&mut json).is_err()); 510 | 511 | let zero32 = "[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]"; 512 | let mut json = json::de::Deserializer::from_str(zero32); 513 | assert!(::deserialize(&mut json).is_err()); 514 | let mut json = json::de::Deserializer::from_str(zero32); 515 | assert!(::deserialize(&mut json).is_ok()); 516 | 517 | let zero33 = "[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]"; 518 | let mut json = json::de::Deserializer::from_str(zero33); 519 | assert!(::deserialize(&mut json).is_err()); 520 | let mut json = json::de::Deserializer::from_str(zero33); 521 | assert!(::deserialize(&mut json).is_err()); 522 | 523 | let trailing66 = "[4,149,16,196,140,38,92,239,179,65,59,224,230,183,91,238,240,46,186,252, 524 | 175,102,52,249,98,178,123,72,50,171,196,254,236,1,189,143,242,227,16,87, 525 | 247,183,162,68,237,140,92,205,151,129,166,58,111,96,123,64,180,147,51,12, 526 | 209,89,236,213,206,17]"; 527 | let mut json = json::de::Deserializer::from_str(trailing66); 528 | assert!(::deserialize(&mut json).is_err()); 529 | 530 | // The first 65 bytes of trailing66 are valid 531 | let valid65 = "[4,149,16,196,140,38,92,239,179,65,59,224,230,183,91,238,240,46,186,252, 532 | 175,102,52,249,98,178,123,72,50,171,196,254,236,1,189,143,242,227,16,87, 533 | 247,183,162,68,237,140,92,205,151,129,166,58,111,96,123,64,180,147,51,12, 534 | 209,89,236,213,206]"; 535 | let mut json = json::de::Deserializer::from_str(valid65); 536 | assert!(::deserialize(&mut json).is_ok()); 537 | 538 | // All zeroes pk is invalid 539 | let zero65 = "[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]"; 540 | let mut json = json::de::Deserializer::from_str(zero65); 541 | assert!(::deserialize(&mut json).is_err()); 542 | let mut json = json::de::Deserializer::from_str(zero65); 543 | assert!(::deserialize(&mut json).is_err()); 544 | 545 | // Syntax error 546 | let string = "\"my key\""; 547 | let mut json = json::de::Deserializer::from_str(string); 548 | assert!(::deserialize(&mut json).is_err()); 549 | let mut json = json::de::Deserializer::from_str(string); 550 | assert!(::deserialize(&mut json).is_err()); 551 | } 552 | 553 | 554 | #[test] 555 | fn test_serialize_serde() { 556 | let s = Secp256k1::new(); 557 | for _ in 0..500 { 558 | let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); 559 | round_trip_serde!(sk); 560 | round_trip_serde!(pk); 561 | } 562 | } 563 | 564 | #[test] 565 | fn test_out_of_range() { 566 | 567 | struct BadRng(u8); 568 | impl RngCore for BadRng { 569 | fn next_u32(&mut self) -> u32 { unimplemented!() } 570 | fn next_u64(&mut self) -> u64 { unimplemented!() } 571 | // This will set a secret key to a little over the 572 | // group order, then decrement with repeated calls 573 | // until it returns a valid key 574 | fn fill_bytes(&mut self, data: &mut [u8]) { 575 | let group_order: [u8; 32] = [ 576 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 577 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 578 | 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 579 | 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41]; 580 | assert_eq!(data.len(), 32); 581 | data.copy_from_slice(&group_order[..]); 582 | data[31] = self.0; 583 | self.0 -= 1; 584 | } 585 | fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { 586 | Ok(self.fill_bytes(dest)) 587 | } 588 | } 589 | 590 | let s = Secp256k1::new(); 591 | s.generate_keypair(&mut BadRng(0xff)).unwrap(); 592 | } 593 | 594 | #[test] 595 | fn test_pubkey_from_bad_slice() { 596 | let s = Secp256k1::new(); 597 | // Bad sizes 598 | assert_eq!(PublicKey::from_slice(&s, &[0; constants::COMPRESSED_PUBLIC_KEY_SIZE - 1]), 599 | Err(InvalidPublicKey)); 600 | assert_eq!(PublicKey::from_slice(&s, &[0; constants::COMPRESSED_PUBLIC_KEY_SIZE + 1]), 601 | Err(InvalidPublicKey)); 602 | assert_eq!(PublicKey::from_slice(&s, &[0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE - 1]), 603 | Err(InvalidPublicKey)); 604 | assert_eq!(PublicKey::from_slice(&s, &[0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE + 1]), 605 | Err(InvalidPublicKey)); 606 | 607 | // Bad parse 608 | assert_eq!(PublicKey::from_slice(&s, &[0xff; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]), 609 | Err(InvalidPublicKey)); 610 | assert_eq!(PublicKey::from_slice(&s, &[0x55; constants::COMPRESSED_PUBLIC_KEY_SIZE]), 611 | Err(InvalidPublicKey)); 612 | } 613 | 614 | #[test] 615 | fn test_debug_output() { 616 | struct DumbRng(u32); 617 | impl RngCore for DumbRng { 618 | fn next_u32(&mut self) -> u32 { 619 | self.0 = self.0.wrapping_add(1); 620 | self.0 621 | } 622 | fn next_u64(&mut self) -> u64 { 623 | self.next_u32() as u64 624 | } 625 | fn fill_bytes(&mut self, dest: &mut [u8]) { 626 | impls::fill_bytes_via_next(self, dest) 627 | } 628 | fn try_fill_bytes(&mut self, _dest: &mut [u8]) -> Result<(), Error> { unimplemented!() } 629 | } 630 | 631 | let s = Secp256k1::new(); 632 | let (sk, _) = s.generate_keypair(&mut DumbRng(0)).unwrap(); 633 | 634 | assert_eq!(&format!("{:?}", sk), 635 | "SecretKey(0100000000000000020000000000000003000000000000000400000000000000)"); 636 | } 637 | 638 | #[test] 639 | fn test_pubkey_serialize() { 640 | struct DumbRng(u32); 641 | impl RngCore for DumbRng { 642 | fn next_u32(&mut self) -> u32 { 643 | self.0 = self.0.wrapping_add(1); 644 | self.0 645 | } 646 | fn next_u64(&mut self) -> u64 { 647 | self.next_u32() as u64 648 | } 649 | fn fill_bytes(&mut self, dest: &mut [u8]) { 650 | impls::fill_bytes_via_next(self, dest) 651 | } 652 | fn try_fill_bytes(&mut self, _dest: &mut [u8]) -> Result<(), Error> { unimplemented!() } 653 | } 654 | 655 | let s = Secp256k1::new(); 656 | let (_, pk1) = s.generate_keypair(&mut DumbRng(0)).unwrap(); 657 | assert_eq!(&pk1.serialize_vec(&s, false)[..], 658 | &[4, 124, 121, 49, 14, 253, 63, 197, 50, 39, 194, 107, 17, 193, 219, 108, 154, 126, 9, 181, 248, 2, 12, 149, 233, 198, 71, 149, 134, 250, 184, 154, 229, 185, 28, 165, 110, 27, 3, 162, 126, 238, 167, 157, 242, 221, 76, 251, 237, 34, 231, 72, 39, 245, 3, 191, 64, 111, 170, 117, 103, 82, 28, 102, 163][..]); 659 | assert_eq!(&pk1.serialize_vec(&s, true)[..], 660 | &[3, 124, 121, 49, 14, 253, 63, 197, 50, 39, 194, 107, 17, 193, 219, 108, 154, 126, 9, 181, 248, 2, 12, 149, 233, 198, 71, 149, 134, 250, 184, 154, 229][..]); 661 | } 662 | 663 | #[test] 664 | fn test_addition() { 665 | let s = Secp256k1::new(); 666 | 667 | let (mut sk1, mut pk1) = s.generate_keypair(&mut thread_rng()).unwrap(); 668 | let (mut sk2, mut pk2) = s.generate_keypair(&mut thread_rng()).unwrap(); 669 | 670 | assert_eq!(PublicKey::from_secret_key(&s, &sk1).unwrap(), pk1); 671 | assert!(sk1.add_assign(&s, &sk2).is_ok()); 672 | assert!(pk1.add_exp_assign(&s, &sk2).is_ok()); 673 | assert_eq!(PublicKey::from_secret_key(&s, &sk1).unwrap(), pk1); 674 | 675 | assert_eq!(PublicKey::from_secret_key(&s, &sk2).unwrap(), pk2); 676 | assert!(sk2.add_assign(&s, &sk1).is_ok()); 677 | assert!(pk2.add_exp_assign(&s, &sk1).is_ok()); 678 | assert_eq!(PublicKey::from_secret_key(&s, &sk2).unwrap(), pk2); 679 | } 680 | 681 | #[test] 682 | fn test_multiplication() { 683 | let s = Secp256k1::new(); 684 | 685 | let (mut sk1, mut pk1) = s.generate_keypair(&mut thread_rng()).unwrap(); 686 | let (mut sk2, mut pk2) = s.generate_keypair(&mut thread_rng()).unwrap(); 687 | 688 | assert_eq!(PublicKey::from_secret_key(&s, &sk1).unwrap(), pk1); 689 | assert!(sk1.mul_assign(&s, &sk2).is_ok()); 690 | assert!(pk1.mul_assign(&s, &sk2).is_ok()); 691 | assert_eq!(PublicKey::from_secret_key(&s, &sk1).unwrap(), pk1); 692 | 693 | assert_eq!(PublicKey::from_secret_key(&s, &sk2).unwrap(), pk2); 694 | assert!(sk2.mul_assign(&s, &sk1).is_ok()); 695 | assert!(pk2.mul_assign(&s, &sk1).is_ok()); 696 | assert_eq!(PublicKey::from_secret_key(&s, &sk2).unwrap(), pk2); 697 | } 698 | 699 | #[test] 700 | fn test_pk_combination() { 701 | let s = Secp256k1::new(); 702 | 703 | let (sk1, mut pk1) = s.generate_keypair(&mut thread_rng()).unwrap(); 704 | let (sk2, mut pk2) = s.generate_keypair(&mut thread_rng()).unwrap(); 705 | 706 | let combined_pk = PublicKey::from_combination(&s, vec![&pk1,&pk2]).unwrap(); 707 | 708 | let _ = pk2.add_exp_assign(&s, &sk1); 709 | let _ = pk1.add_exp_assign(&s, &sk2); 710 | assert_eq!(combined_pk, pk2); 711 | assert_eq!(combined_pk, pk1); 712 | } 713 | 714 | #[test] 715 | fn test_inverse() { 716 | let s = Secp256k1::new(); 717 | 718 | let one = SecretKey::from_slice(&s, &[ 719 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 720 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 721 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 722 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]).unwrap(); 723 | 724 | let mut one_inv: SecretKey = one.clone(); 725 | one_inv.inv_assign(&s).unwrap(); 726 | assert_eq!(one_inv, one); 727 | 728 | let (sk1, _) = s.generate_keypair(&mut thread_rng()).unwrap(); 729 | let mut sk2: SecretKey = sk1.clone(); 730 | sk2.inv_assign(&s).unwrap(); 731 | sk2.inv_assign(&s).unwrap(); 732 | assert_eq!(sk2, sk1); 733 | 734 | let (sk1, _) = s.generate_keypair(&mut thread_rng()).unwrap(); 735 | let mut sk2: SecretKey = sk1.clone(); 736 | sk2.inv_assign(&s).unwrap(); 737 | sk2.mul_assign(&s, &sk1).unwrap(); 738 | assert_eq!(sk2, one); 739 | } 740 | 741 | #[test] 742 | fn test_negate() { 743 | let s = Secp256k1::new(); 744 | 745 | let (sk1, _) = s.generate_keypair(&mut thread_rng()).unwrap(); 746 | let mut sk2: SecretKey = sk1.clone(); 747 | sk2.neg_assign(&s).unwrap(); 748 | assert!(sk2.add_assign(&s, &sk1).is_err()); 749 | 750 | let (sk1, _) = s.generate_keypair(&mut thread_rng()).unwrap(); 751 | let mut sk2: SecretKey = sk1.clone(); 752 | sk2.neg_assign(&s).unwrap(); 753 | sk2.neg_assign(&s).unwrap(); 754 | assert_eq!(sk2, sk1); 755 | 756 | let (mut sk1, _) = s.generate_keypair(&mut thread_rng()).unwrap(); 757 | let mut sk2: SecretKey = sk1.clone(); 758 | sk1.neg_assign(&s).unwrap(); 759 | let sk1_clone = sk1.clone(); 760 | sk1.add_assign(&s, &sk1_clone).unwrap(); 761 | let sk2_clone = sk2.clone(); 762 | sk2.add_assign(&s, &sk2_clone).unwrap(); 763 | sk2.neg_assign(&s).unwrap(); 764 | assert_eq!(sk2, sk1); 765 | 766 | let one = SecretKey::from_slice(&s, &[ 767 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 768 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 769 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 770 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]).unwrap(); 771 | 772 | let (mut sk1, _) = s.generate_keypair(&mut thread_rng()).unwrap(); 773 | let mut sk2: SecretKey = one.clone(); 774 | sk2.neg_assign(&s).unwrap(); 775 | sk2.mul_assign(&s, &sk1).unwrap(); 776 | sk1.neg_assign(&s).unwrap(); 777 | assert_eq!(sk2, sk1); 778 | 779 | let (mut sk1, _) = s.generate_keypair(&mut thread_rng()).unwrap(); 780 | let mut sk2: SecretKey = sk1.clone(); 781 | sk1.neg_assign(&s).unwrap(); 782 | sk1.inv_assign(&s).unwrap(); 783 | sk2.inv_assign(&s).unwrap(); 784 | sk2.neg_assign(&s).unwrap(); 785 | assert_eq!(sk2, sk1); 786 | } 787 | 788 | #[test] 789 | fn pubkey_hash() { 790 | use std::collections::hash_map::DefaultHasher; 791 | use std::hash::{Hash, Hasher}; 792 | use std::collections::HashSet; 793 | 794 | fn hash(t: &T) -> u64 { 795 | let mut s = DefaultHasher::new(); 796 | t.hash(&mut s); 797 | s.finish() 798 | } 799 | 800 | let s = Secp256k1::new(); 801 | let mut set = HashSet::new(); 802 | const COUNT : usize = 1024; 803 | let count = (0..COUNT).map(|_| { 804 | let (_, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); 805 | let hash = hash(&pk); 806 | assert!(!set.contains(&hash)); 807 | set.insert(hash); 808 | }).count(); 809 | assert_eq!(count, COUNT); 810 | } 811 | } 812 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // Bitcoin secp256k1 bindings 2 | // Written in 2014 by 3 | // Dawid Ciężarkiewicz 4 | // Andrew Poelstra 5 | // 6 | // To the extent possible under law, the author(s) have dedicated all 7 | // copyright and related and neighboring rights to this software to 8 | // the public domain worldwide. This software is distributed without 9 | // any warranty. 10 | // 11 | // You should have received a copy of the CC0 Public Domain Dedication 12 | // along with this software. 13 | // If not, see . 14 | // 15 | 16 | //! # Secp256k1 17 | //! Rust bindings for Pieter Wuille's secp256k1 library, which is used for 18 | //! fast and accurate manipulation of ECDSA signatures on the secp256k1 19 | //! curve. Such signatures are used extensively by the Bitcoin network 20 | //! and its derivatives. 21 | //! 22 | 23 | #![crate_type = "lib"] 24 | #![crate_type = "rlib"] 25 | #![crate_type = "dylib"] 26 | #![crate_name = "secp256k1zkp"] 27 | 28 | // Coding conventions 29 | #![deny(non_upper_case_globals)] 30 | #![deny(non_camel_case_types)] 31 | #![deny(non_snake_case)] 32 | #![deny(unused_mut)] 33 | #![warn(missing_docs)] 34 | 35 | #![cfg_attr(feature = "dev", allow(unstable_features))] 36 | #![cfg_attr(feature = "dev", feature(plugin))] 37 | #![cfg_attr(feature = "dev", plugin(clippy))] 38 | 39 | #![cfg_attr(all(test, feature = "unstable"), feature(test))] 40 | #[cfg(all(test, feature = "unstable"))] extern crate test; 41 | 42 | extern crate arrayvec; 43 | extern crate serde; 44 | extern crate serde_json as json; 45 | 46 | extern crate libc; 47 | pub extern crate rand; 48 | 49 | extern crate zeroize; 50 | 51 | use libc::size_t; 52 | use std::{fmt, ops, ptr}; 53 | use rand::Rng; 54 | 55 | #[macro_use] 56 | mod macros; 57 | pub mod constants; 58 | pub mod ecdh; 59 | pub mod ffi; 60 | pub mod key; 61 | pub mod pedersen; 62 | pub mod aggsig; 63 | 64 | pub use key::SecretKey; 65 | pub use key::PublicKey; 66 | 67 | /// A tag used for recovering the public key from a compact signature 68 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] 69 | pub struct RecoveryId(i32); 70 | 71 | /// An ECDSA signature 72 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] 73 | pub struct Signature(ffi::Signature); 74 | 75 | impl std::convert::AsRef<[u8]> for Signature { 76 | fn as_ref(&self) -> &[u8] { 77 | &self.0.as_ref() 78 | } 79 | } 80 | 81 | /// An AggSig partial signature 82 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] 83 | pub struct AggSigPartialSignature(ffi::AggSigPartialSignature); 84 | 85 | impl std::convert::AsRef<[u8]> for AggSigPartialSignature { 86 | fn as_ref(&self) -> &[u8] { 87 | &self.0.as_ref() 88 | } 89 | } 90 | 91 | /// An ECDSA signature with a recovery ID for pubkey recovery 92 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] 93 | pub struct RecoverableSignature(ffi::RecoverableSignature); 94 | 95 | impl RecoveryId { 96 | #[inline] 97 | /// Allows library users to create valid recovery IDs from i32. 98 | pub fn from_i32(id: i32) -> Result { 99 | match id { 100 | 0 | 1 | 2 | 3 => Ok(RecoveryId(id)), 101 | _ => Err(Error::InvalidRecoveryId) 102 | } 103 | } 104 | 105 | #[inline] 106 | /// Allows library users to convert recovery IDs to i32. 107 | pub fn to_i32(&self) -> i32 { 108 | self.0 109 | } 110 | } 111 | 112 | impl Signature { 113 | #[inline] 114 | /// Converts a DER-encoded byte slice to a signature 115 | pub fn from_der(secp: &Secp256k1, data: &[u8]) -> Result { 116 | let mut ret = unsafe { ffi::Signature::blank() }; 117 | 118 | unsafe { 119 | if ffi::secp256k1_ecdsa_signature_parse_der(secp.ctx, &mut ret, 120 | data.as_ptr(), data.len() as libc::size_t) == 1 { 121 | Ok(Signature(ret)) 122 | } else { 123 | Err(Error::InvalidSignature) 124 | } 125 | } 126 | } 127 | 128 | /// Converts a 64-byte compact-encoded byte slice to a signature 129 | pub fn from_compact(secp: &Secp256k1, data: &[u8]) -> Result { 130 | let mut ret = unsafe { ffi::Signature::blank() }; 131 | if data.len() != 64 { 132 | return Err(Error::InvalidSignature); 133 | } 134 | 135 | unsafe { 136 | if ffi::secp256k1_ecdsa_signature_parse_compact(secp.ctx, &mut ret, 137 | data.as_ptr()) == 1 { 138 | Ok(Signature(ret)) 139 | } else { 140 | Err(Error::InvalidSignature) 141 | } 142 | } 143 | } 144 | 145 | /// Stores raw bytes provided as a signature, with no conversion 146 | pub fn from_raw_data(data: &[u8;64]) -> Result { 147 | Ok(Signature(ffi::Signature::from_data(data.clone()))) 148 | } 149 | 150 | /// Converts a "lax DER"-encoded byte slice to a signature. This is basically 151 | /// only useful for validating signatures in the Bitcoin blockchain from before 152 | /// 2016. It should never be used in new applications. This library does not 153 | /// support serializing to this "format" 154 | pub fn from_der_lax(secp: &Secp256k1, data: &[u8]) -> Result { 155 | unsafe { 156 | let mut ret = ffi::Signature::blank(); 157 | if ffi::ecdsa_signature_parse_der_lax(secp.ctx, &mut ret, 158 | data.as_ptr(), data.len() as libc::size_t) == 1 { 159 | Ok(Signature(ret)) 160 | } else { 161 | Err(Error::InvalidSignature) 162 | } 163 | } 164 | } 165 | 166 | /// Normalizes a signature to a "low S" form. In ECDSA, signatures are 167 | /// of the form (r, s) where r and s are numbers lying in some finite 168 | /// field. The verification equation will pass for (r, s) iff it passes 169 | /// for (r, -s), so it is possible to ``modify'' signatures in transit 170 | /// by flipping the sign of s. This does not constitute a forgery since 171 | /// the signed message still cannot be changed, but for some applications, 172 | /// changing even the signature itself can be a problem. Such applications 173 | /// require a "strong signature". It is believed that ECDSA is a strong 174 | /// signature except for this ambiguity in the sign of s, so to accomodate 175 | /// these applications libsecp256k1 will only accept signatures for which 176 | /// s is in the lower half of the field range. This eliminates the 177 | /// ambiguity. 178 | /// 179 | /// However, for some systems, signatures with high s-values are considered 180 | /// valid. (For example, parsing the historic Bitcoin blockchain requires 181 | /// this.) For these applications we provide this normalization function, 182 | /// which ensures that the s value lies in the lower half of its range. 183 | pub fn normalize_s(&mut self, secp: &Secp256k1) { 184 | unsafe { 185 | // Ignore return value, which indicates whether the sig 186 | // was already normalized. We don't care. 187 | ffi::secp256k1_ecdsa_signature_normalize(secp.ctx, self.as_mut_ptr(), 188 | self.as_ptr()); 189 | } 190 | } 191 | 192 | /// Obtains a raw pointer suitable for use with FFI functions 193 | #[inline] 194 | pub fn as_ptr(&self) -> *const ffi::Signature { 195 | &self.0 as *const _ 196 | } 197 | 198 | /// Obtains a raw mutable pointer suitable for use with FFI functions 199 | #[inline] 200 | pub fn as_mut_ptr(&mut self) -> *mut ffi::Signature { 201 | &mut self.0 as *mut _ 202 | } 203 | 204 | #[inline] 205 | /// Serializes the signature in DER format 206 | pub fn serialize_der(&self, secp: &Secp256k1) -> Vec { 207 | let mut ret = Vec::with_capacity(72); 208 | let mut len: size_t = ret.capacity() as size_t; 209 | unsafe { 210 | let err = ffi::secp256k1_ecdsa_signature_serialize_der(secp.ctx, ret.as_mut_ptr(), 211 | &mut len, self.as_ptr()); 212 | debug_assert!(err == 1); 213 | ret.set_len(len as usize); 214 | } 215 | ret 216 | } 217 | 218 | #[inline] 219 | /// Serializes the signature in compact format 220 | pub fn serialize_compact(&self, secp: &Secp256k1) -> [u8; 64] { 221 | let mut ret = [0; 64]; 222 | unsafe { 223 | let err = ffi::secp256k1_ecdsa_signature_serialize_compact(secp.ctx, ret.as_mut_ptr(), 224 | self.as_ptr()); 225 | debug_assert!(err == 1); 226 | } 227 | ret 228 | } 229 | 230 | #[inline] 231 | /// Just return raw data, no conversion tricks 232 | pub fn to_raw_data(&self) -> [u8; 64] { 233 | (self.0).0.clone() 234 | } 235 | } 236 | 237 | impl serde::Serialize for Signature { 238 | fn serialize(&self, s: S) -> Result 239 | where S: serde::Serializer 240 | { 241 | let secp = Secp256k1::with_caps(crate::ContextFlag::None); 242 | (&self.serialize_compact(&secp)[..]).serialize(s) 243 | } 244 | } 245 | 246 | impl<'de> serde::Deserialize<'de> for Signature { 247 | fn deserialize(d: D) -> Result 248 | where D: serde::Deserializer<'de> 249 | { 250 | use serde::de; 251 | struct Visitor { 252 | marker: std::marker::PhantomData, 253 | } 254 | impl<'de> de::Visitor<'de> for Visitor { 255 | type Value = Signature; 256 | 257 | #[inline] 258 | fn visit_seq(self, mut a: A) -> Result 259 | where A: de::SeqAccess<'de> 260 | { 261 | let s = Secp256k1::with_caps(crate::ContextFlag::None); 262 | unsafe { 263 | use std::mem; 264 | let mut ret: [u8; constants::COMPACT_SIGNATURE_SIZE] = mem::MaybeUninit::uninit().assume_init(); 265 | 266 | for i in 0..constants::COMPACT_SIGNATURE_SIZE { 267 | ret[i] = match a.next_element()? { 268 | Some(c) => c, 269 | None => return Err(::serde::de::Error::invalid_length(i, &self)) 270 | }; 271 | } 272 | let one_after_last : Option = a.next_element()?; 273 | if one_after_last.is_some() { 274 | return Err(serde::de::Error::invalid_length(constants::COMPACT_SIGNATURE_SIZE + 1, &self)); 275 | } 276 | 277 | Signature::from_compact(&s, &ret).map_err( 278 | |e| match e { 279 | Error::InvalidSignature => de::Error::invalid_value(de::Unexpected::Seq, &self), 280 | _ => de::Error::custom(&e.to_string()), 281 | } 282 | ) 283 | } 284 | } 285 | 286 | fn expecting(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 287 | write!(f, "a sequence of {} bytes representing a syntactically well-formed compact signature", 288 | constants::COMPACT_SIGNATURE_SIZE) 289 | } 290 | } 291 | 292 | // Begin actual function 293 | d.deserialize_seq(Visitor { marker: std::marker::PhantomData }) 294 | } 295 | } 296 | 297 | /// Creates a new signature from a FFI signature 298 | impl From for Signature { 299 | #[inline] 300 | fn from(sig: ffi::Signature) -> Signature { 301 | Signature(sig) 302 | } 303 | } 304 | 305 | impl AggSigPartialSignature { 306 | /// Obtains a raw pointer suitable for use with FFI functions 307 | #[inline] 308 | pub fn as_ptr(&self) -> *const ffi::AggSigPartialSignature { 309 | &self.0 as *const _ 310 | } 311 | 312 | /// Obtains a raw mutable pointer suitable for use with FFI functions 313 | #[inline] 314 | pub fn as_mut_ptr(&mut self) -> *mut ffi::AggSigPartialSignature { 315 | &mut self.0 as *mut _ 316 | } 317 | } 318 | 319 | /// Creates a new signature from a FFI signature 320 | impl From for AggSigPartialSignature { 321 | #[inline] 322 | fn from(sig: ffi::AggSigPartialSignature) -> AggSigPartialSignature { 323 | AggSigPartialSignature(sig) 324 | } 325 | } 326 | 327 | 328 | impl RecoverableSignature { 329 | #[inline] 330 | /// Converts a compact-encoded byte slice to a signature. This 331 | /// representation is nonstandard and defined by the libsecp256k1 332 | /// library. 333 | pub fn from_compact(secp: &Secp256k1, data: &[u8], recid: RecoveryId) -> Result { 334 | let mut ret = unsafe { ffi::RecoverableSignature::blank() }; 335 | 336 | unsafe { 337 | if data.len() != 64 { 338 | Err(Error::InvalidSignature) 339 | } else if ffi::secp256k1_ecdsa_recoverable_signature_parse_compact(secp.ctx, &mut ret, 340 | data.as_ptr(), recid.0) == 1 { 341 | Ok(RecoverableSignature(ret)) 342 | } else { 343 | Err(Error::InvalidSignature) 344 | } 345 | } 346 | } 347 | 348 | /// Obtains a raw pointer suitable for use with FFI functions 349 | #[inline] 350 | pub fn as_ptr(&self) -> *const ffi::RecoverableSignature { 351 | &self.0 as *const _ 352 | } 353 | 354 | #[inline] 355 | /// Serializes the recoverable signature in compact format 356 | pub fn serialize_compact(&self, secp: &Secp256k1) -> (RecoveryId, [u8; 64]) { 357 | let mut ret = [0u8; 64]; 358 | let mut recid = 0i32; 359 | unsafe { 360 | let err = ffi::secp256k1_ecdsa_recoverable_signature_serialize_compact( 361 | secp.ctx, ret.as_mut_ptr(), &mut recid, self.as_ptr()); 362 | assert!(err == 1); 363 | } 364 | (RecoveryId(recid), ret) 365 | } 366 | 367 | /// Converts a recoverable signature to a non-recoverable one (this is needed 368 | /// for verification 369 | #[inline] 370 | pub fn to_standard(&self, secp: &Secp256k1) -> Signature { 371 | let mut ret = unsafe { ffi::Signature::blank() }; 372 | unsafe { 373 | let err = ffi::secp256k1_ecdsa_recoverable_signature_convert(secp.ctx, &mut ret, self.as_ptr()); 374 | assert!(err == 1); 375 | } 376 | Signature(ret) 377 | } 378 | } 379 | 380 | /// Creates a new recoverable signature from a FFI one 381 | impl From for RecoverableSignature { 382 | #[inline] 383 | fn from(sig: ffi::RecoverableSignature) -> RecoverableSignature { 384 | RecoverableSignature(sig) 385 | } 386 | } 387 | 388 | impl ops::Index for Signature { 389 | type Output = u8; 390 | 391 | #[inline] 392 | fn index(&self, index: usize) -> &u8 { 393 | &self.0[index] 394 | } 395 | } 396 | 397 | impl ops::Index> for Signature { 398 | type Output = [u8]; 399 | 400 | #[inline] 401 | fn index(&self, index: ops::Range) -> &[u8] { 402 | &self.0[index] 403 | } 404 | } 405 | 406 | impl ops::Index> for Signature { 407 | type Output = [u8]; 408 | 409 | #[inline] 410 | fn index(&self, index: ops::RangeFrom) -> &[u8] { 411 | &self.0[index.start..] 412 | } 413 | } 414 | 415 | impl ops::Index for Signature { 416 | type Output = [u8]; 417 | 418 | #[inline] 419 | fn index(&self, _: ops::RangeFull) -> &[u8] { 420 | &self.0[..] 421 | } 422 | } 423 | 424 | /// A (hashed) message input to an ECDSA signature 425 | pub struct Message([u8; constants::MESSAGE_SIZE]); 426 | impl Copy for Message {} 427 | impl_array_newtype!(Message, u8, constants::MESSAGE_SIZE); 428 | impl_pretty_debug!(Message); 429 | 430 | impl Message { 431 | /// Converts a `MESSAGE_SIZE`-byte slice to a message object 432 | #[inline] 433 | pub fn from_slice(data: &[u8]) -> Result { 434 | match data.len() { 435 | constants::MESSAGE_SIZE => { 436 | let mut ret = [0; constants::MESSAGE_SIZE]; 437 | ret[..].copy_from_slice(data); 438 | Ok(Message(ret)) 439 | } 440 | _ => Err(Error::InvalidMessage) 441 | } 442 | } 443 | } 444 | 445 | /// Creates a message from a `MESSAGE_SIZE` byte array 446 | impl From<[u8; constants::MESSAGE_SIZE]> for Message { 447 | fn from(buf: [u8; constants::MESSAGE_SIZE]) -> Message { 448 | Message(buf) 449 | } 450 | } 451 | 452 | /// An ECDSA error 453 | #[derive(Copy, PartialEq, Eq, Clone, Debug, serde::Serialize, serde::Deserialize)] 454 | pub enum Error { 455 | /// A `Secp256k1` was used for an operation, but it was not created to 456 | /// support this (so necessary precomputations have not been done) 457 | IncapableContext, 458 | /// Signature failed verification 459 | IncorrectSignature, 460 | /// Badly sized message ("messages" are actually fixed-sized digests; see the `MESSAGE_SIZE` 461 | /// constant) 462 | InvalidMessage, 463 | /// Bad public key 464 | InvalidPublicKey, 465 | /// Bad commit 466 | InvalidCommit, 467 | /// Bad signature 468 | InvalidSignature, 469 | /// Bad secret key 470 | InvalidSecretKey, 471 | /// Bad recovery id 472 | InvalidRecoveryId, 473 | /// Summing commitments led to incorrect result 474 | IncorrectCommitSum, 475 | /// Range proof is invalid 476 | InvalidRangeProof, 477 | /// Error creating partial signature 478 | PartialSigFailure, 479 | /// Failure subtracting two signatures 480 | SigSubtractionFailure, 481 | } 482 | 483 | impl Error { 484 | fn as_str(&self) -> &str { 485 | match *self { 486 | Error::IncapableContext => "secp: context does not have sufficient capabilities", 487 | Error::IncorrectSignature => "secp: signature failed verification", 488 | Error::InvalidMessage => "secp: message was not 32 bytes (do you need to hash?)", 489 | Error::InvalidPublicKey => "secp: malformed public key", 490 | Error::InvalidCommit => "secp: malformed commit", 491 | Error::InvalidSignature => "secp: malformed signature", 492 | Error::InvalidSecretKey => "secp: malformed or out-of-range secret key", 493 | Error::InvalidRecoveryId => "secp: bad recovery id", 494 | Error::IncorrectCommitSum => "secp: invalid pedersen commitment sum", 495 | Error::InvalidRangeProof => "secp: invalid range proof", 496 | Error::PartialSigFailure => "secp: partial sig (aggsig) failure", 497 | Error::SigSubtractionFailure => "secp: subtraction (aggsig) did not result in any valid signatures", 498 | } 499 | } 500 | } 501 | 502 | // Passthrough Debug to Display, since errors should be user-visible 503 | impl fmt::Display for Error { 504 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { 505 | f.write_str(self.as_str()) 506 | } 507 | } 508 | 509 | impl std::error::Error for Error { 510 | fn description(&self) -> &str { self.as_str() } 511 | } 512 | 513 | 514 | /// The secp256k1 engine, used to execute all signature operations 515 | pub struct Secp256k1 { 516 | ctx: *mut ffi::Context, 517 | caps: ContextFlag 518 | } 519 | 520 | unsafe impl Send for Secp256k1 {} 521 | unsafe impl Sync for Secp256k1 {} 522 | 523 | /// Flags used to determine the capabilities of a `Secp256k1` object; 524 | /// the more capabilities, the more expensive it is to create. 525 | #[derive(PartialEq, Eq, Copy, Clone, Debug)] 526 | pub enum ContextFlag { 527 | /// Can neither sign nor verify signatures (cheapest to create, useful 528 | /// for cases not involving signatures, such as creating keys from slices) 529 | None, 530 | /// Can sign but not verify signatures 531 | SignOnly, 532 | /// Can verify but not create signatures 533 | VerifyOnly, 534 | /// Can verify and create signatures 535 | Full, 536 | /// Can do all of the above plus pedersen commitments 537 | Commit, 538 | } 539 | 540 | // Passthrough Debug to Display, since caps should be user-visible 541 | impl fmt::Display for ContextFlag { 542 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { 543 | fmt::Debug::fmt(self, f) 544 | } 545 | } 546 | 547 | impl Clone for Secp256k1 { 548 | fn clone(&self) -> Secp256k1 { 549 | Secp256k1 { 550 | ctx: unsafe { ffi::secp256k1_context_clone(self.ctx) }, 551 | caps: self.caps 552 | } 553 | } 554 | } 555 | 556 | impl PartialEq for Secp256k1 { 557 | fn eq(&self, other: &Secp256k1) -> bool { self.caps == other.caps } 558 | } 559 | impl Eq for Secp256k1 { } 560 | 561 | impl fmt::Debug for Secp256k1 { 562 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { 563 | write!(f, "Secp256k1 {{ [private], caps: {:?} }}", self.caps) 564 | } 565 | } 566 | 567 | impl Drop for Secp256k1 { 568 | fn drop(&mut self) { 569 | unsafe { ffi::secp256k1_context_destroy(self.ctx); } 570 | } 571 | } 572 | 573 | impl Secp256k1 { 574 | /// Creates a new Secp256k1 context 575 | #[inline] 576 | pub fn new() -> Secp256k1 { 577 | Secp256k1::with_caps(ContextFlag::Full) 578 | } 579 | 580 | /// Creates a new Secp256k1 context with the specified capabilities 581 | pub fn with_caps(caps: ContextFlag) -> Secp256k1 { 582 | let flag = match caps { 583 | ContextFlag::None => ffi::SECP256K1_START_NONE, 584 | ContextFlag::SignOnly => ffi::SECP256K1_START_SIGN, 585 | ContextFlag::VerifyOnly => ffi::SECP256K1_START_VERIFY, 586 | ContextFlag::Full | ContextFlag::Commit => { 587 | ffi::SECP256K1_START_SIGN | ffi::SECP256K1_START_VERIFY 588 | } 589 | }; 590 | Secp256k1 { ctx: unsafe { ffi::secp256k1_context_create(flag) }, caps: caps } 591 | } 592 | 593 | /// Creates a new Secp256k1 context with no capabilities (just de/serialization) 594 | pub fn without_caps() -> Secp256k1 { 595 | Secp256k1::with_caps(ContextFlag::None) 596 | } 597 | 598 | /// (Re)randomizes the Secp256k1 context for cheap sidechannel resistence; 599 | /// see comment in libsecp256k1 commit d2275795f by Gregory Maxwell 600 | pub fn randomize(&mut self, rng: &mut R) { 601 | let mut seed = [0u8; 32]; 602 | rng.fill(&mut seed); 603 | unsafe { 604 | let err = ffi::secp256k1_context_randomize(self.ctx, seed.as_ptr()); 605 | // This function cannot fail; it has an error return for future-proofing. 606 | // We do not expose this error since it is impossible to hit, and we have 607 | // precedent for not exposing impossible errors (for example in 608 | // `PublicKey::from_secret_key` where it is impossble to create an invalid 609 | // secret key through the API.) 610 | // However, if this DOES fail, the result is potentially weaker side-channel 611 | // resistance, which is deadly and undetectable, so we take out the entire 612 | // thread to be on the safe side. 613 | assert!(err == 1); 614 | } 615 | } 616 | 617 | /// Generates a random keypair. Convenience function for `key::SecretKey::new` 618 | /// and `key::PublicKey::from_secret_key`; call those functions directly for 619 | /// batch key generation. Requires a signing-capable context. 620 | #[inline] 621 | pub fn generate_keypair(&self, rng: &mut R) 622 | -> Result<(key::SecretKey, key::PublicKey), Error> { 623 | let sk = key::SecretKey::new(self, rng); 624 | let pk = key::PublicKey::from_secret_key(self, &sk)?; 625 | Ok((sk, pk)) 626 | } 627 | 628 | /// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce 629 | /// Requires a signing-capable context. 630 | pub fn sign(&self, msg: &Message, sk: &key::SecretKey) 631 | -> Result { 632 | if self.caps == ContextFlag::VerifyOnly || self.caps == ContextFlag::None { 633 | return Err(Error::IncapableContext); 634 | } 635 | 636 | let mut ret = unsafe { ffi::Signature::blank() }; 637 | unsafe { 638 | // We can assume the return value because it's not possible to construct 639 | // an invalid signature from a valid `Message` and `SecretKey` 640 | assert_eq!(ffi::secp256k1_ecdsa_sign(self.ctx, &mut ret, msg.as_ptr(), 641 | sk.as_ptr(), ffi::secp256k1_nonce_function_rfc6979, 642 | ptr::null()), 1); 643 | } 644 | Ok(Signature::from(ret)) 645 | } 646 | 647 | /// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce 648 | /// Requires a signing-capable context. 649 | pub fn sign_recoverable(&self, msg: &Message, sk: &key::SecretKey) 650 | -> Result { 651 | if self.caps == ContextFlag::VerifyOnly || self.caps == ContextFlag::None { 652 | return Err(Error::IncapableContext); 653 | } 654 | 655 | let mut ret = unsafe { ffi::RecoverableSignature::blank() }; 656 | unsafe { 657 | // We can assume the return value because it's not possible to construct 658 | // an invalid signature from a valid `Message` and `SecretKey` 659 | assert_eq!(ffi::secp256k1_ecdsa_sign_recoverable(self.ctx, &mut ret, msg.as_ptr(), 660 | sk.as_ptr(), ffi::secp256k1_nonce_function_rfc6979, 661 | ptr::null()), 1); 662 | } 663 | Ok(RecoverableSignature::from(ret)) 664 | } 665 | 666 | /// Determines the public key for which `sig` is a valid signature for 667 | /// `msg`. Requires a verify-capable context. 668 | pub fn recover(&self, msg: &Message, sig: &RecoverableSignature) 669 | -> Result { 670 | if self.caps == ContextFlag::SignOnly || self.caps == ContextFlag::None { 671 | return Err(Error::IncapableContext); 672 | } 673 | 674 | let mut pk = unsafe { ffi::PublicKey::blank() }; 675 | 676 | unsafe { 677 | if ffi::secp256k1_ecdsa_recover(self.ctx, &mut pk, 678 | sig.as_ptr(), msg.as_ptr()) != 1 { 679 | return Err(Error::InvalidSignature); 680 | } 681 | }; 682 | Ok(key::PublicKey::from(pk)) 683 | } 684 | 685 | /// Checks that `sig` is a valid ECDSA signature for `msg` using the public 686 | /// key `pubkey`. Returns `Ok(true)` on success. Note that this function cannot 687 | /// be used for Bitcoin consensus checking since there may exist signatures 688 | /// which OpenSSL would verify but not libsecp256k1, or vice-versa. Requires a 689 | /// verify-capable context. 690 | #[inline] 691 | pub fn verify(&self, msg: &Message, sig: &Signature, pk: &key::PublicKey) -> Result<(), Error> { 692 | if self.caps == ContextFlag::SignOnly || self.caps == ContextFlag::None { 693 | return Err(Error::IncapableContext); 694 | } 695 | 696 | if !pk.is_valid() { 697 | Err(Error::InvalidPublicKey) 698 | } else if unsafe { ffi::secp256k1_ecdsa_verify(self.ctx, sig.as_ptr(), msg.as_ptr(), 699 | pk.as_ptr()) } == 0 { 700 | Err(Error::IncorrectSignature) 701 | } else { 702 | Ok(()) 703 | } 704 | } 705 | } 706 | 707 | #[cfg(test)] 708 | mod tests { 709 | use rand::{Rng, thread_rng}; 710 | use crate::key::{SecretKey, PublicKey}; 711 | use super::constants; 712 | use super::{Secp256k1, Signature, RecoverableSignature, Message, RecoveryId, ContextFlag}; 713 | use super::Error::{InvalidMessage, InvalidPublicKey, IncorrectSignature, InvalidSignature, 714 | IncapableContext}; 715 | 716 | macro_rules! hex { 717 | ($hex:expr) => {{ 718 | let bytes = $hex.as_bytes(); 719 | let mut vec = Vec::new(); 720 | for i in (0..bytes.len()).step_by(2) { 721 | let high = (bytes[i] as char).to_digit(16).unwrap(); 722 | let low = (bytes[i + 1] as char).to_digit(16).unwrap(); 723 | vec.push(((high << 4) + low) as u8); 724 | } 725 | vec 726 | }}; 727 | } 728 | 729 | #[test] 730 | fn capabilities() { 731 | let none = Secp256k1::with_caps(ContextFlag::None); 732 | let sign = Secp256k1::with_caps(ContextFlag::SignOnly); 733 | let vrfy = Secp256k1::with_caps(ContextFlag::VerifyOnly); 734 | let full = Secp256k1::with_caps(ContextFlag::Full); 735 | 736 | let mut msg = [0u8; 32]; 737 | thread_rng().fill(&mut msg); 738 | let msg = Message::from_slice(&msg).unwrap(); 739 | 740 | // Try key generation 741 | assert_eq!(none.generate_keypair(&mut thread_rng()), Err(IncapableContext)); 742 | assert_eq!(vrfy.generate_keypair(&mut thread_rng()), Err(IncapableContext)); 743 | assert!(sign.generate_keypair(&mut thread_rng()).is_ok()); 744 | assert!(full.generate_keypair(&mut thread_rng()).is_ok()); 745 | let (sk, pk) = full.generate_keypair(&mut thread_rng()).unwrap(); 746 | 747 | // Try signing 748 | assert_eq!(none.sign(&msg, &sk), Err(IncapableContext)); 749 | assert_eq!(vrfy.sign(&msg, &sk), Err(IncapableContext)); 750 | assert!(sign.sign(&msg, &sk).is_ok()); 751 | assert!(full.sign(&msg, &sk).is_ok()); 752 | assert_eq!(none.sign_recoverable(&msg, &sk), Err(IncapableContext)); 753 | assert_eq!(vrfy.sign_recoverable(&msg, &sk), Err(IncapableContext)); 754 | assert!(sign.sign_recoverable(&msg, &sk).is_ok()); 755 | assert!(full.sign_recoverable(&msg, &sk).is_ok()); 756 | assert_eq!(sign.sign(&msg, &sk), full.sign(&msg, &sk)); 757 | assert_eq!(sign.sign_recoverable(&msg, &sk), full.sign_recoverable(&msg, &sk)); 758 | let sig = full.sign(&msg, &sk).unwrap(); 759 | let sigr = full.sign_recoverable(&msg, &sk).unwrap(); 760 | 761 | // Try verifying 762 | assert_eq!(none.verify(&msg, &sig, &pk), Err(IncapableContext)); 763 | assert_eq!(sign.verify(&msg, &sig, &pk), Err(IncapableContext)); 764 | assert!(vrfy.verify(&msg, &sig, &pk).is_ok()); 765 | assert!(full.verify(&msg, &sig, &pk).is_ok()); 766 | 767 | // Try pk recovery 768 | assert_eq!(none.recover(&msg, &sigr), Err(IncapableContext)); 769 | assert_eq!(sign.recover(&msg, &sigr), Err(IncapableContext)); 770 | assert!(vrfy.recover(&msg, &sigr).is_ok()); 771 | assert!(full.recover(&msg, &sigr).is_ok()); 772 | 773 | assert_eq!(vrfy.recover(&msg, &sigr), 774 | full.recover(&msg, &sigr)); 775 | assert_eq!(full.recover(&msg, &sigr), Ok(pk)); 776 | 777 | // Check that we can produce keys from slices with no precomputation 778 | let (pk_slice, sk_slice) = (&pk.serialize_vec(&none, true), &sk[..]); 779 | let new_pk = PublicKey::from_slice(&none, pk_slice).unwrap(); 780 | let new_sk = SecretKey::from_slice(&none, sk_slice).unwrap(); 781 | assert_eq!(sk, new_sk); 782 | assert_eq!(pk, new_pk); 783 | } 784 | 785 | #[test] 786 | fn recid_sanity_check() { 787 | let one = RecoveryId(1); 788 | assert_eq!(one, one.clone()); 789 | } 790 | 791 | #[test] 792 | fn invalid_pubkey() { 793 | let s = Secp256k1::new(); 794 | let sig = RecoverableSignature::from_compact(&s, &[1; 64], RecoveryId(0)).unwrap(); 795 | let pk = PublicKey::new(); 796 | let mut msg = [0u8; 32]; 797 | thread_rng().fill(&mut msg); 798 | let msg = Message::from_slice(&msg).unwrap(); 799 | 800 | assert_eq!(s.verify(&msg, &sig.to_standard(&s), &pk), Err(InvalidPublicKey)); 801 | } 802 | 803 | #[test] 804 | fn sign() { 805 | let mut s = Secp256k1::new(); 806 | s.randomize(&mut thread_rng()); 807 | let one = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 808 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]; 809 | 810 | let sk = SecretKey::from_slice(&s, &one).unwrap(); 811 | let msg = Message::from_slice(&one).unwrap(); 812 | 813 | let sig = s.sign_recoverable(&msg, &sk).unwrap(); 814 | assert_eq!(Ok(sig), RecoverableSignature::from_compact(&s, &[ 815 | 0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f, 816 | 0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6, 817 | 0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65, 818 | 0xc3, 0x6d, 0xed, 0xf4, 0x09, 0x2e, 0x88, 0x98, 819 | 0x4c, 0x1a, 0x97, 0x16, 0x52, 0xe0, 0xad, 0xa8, 820 | 0x80, 0x12, 0x0e, 0xf8, 0x02, 0x5e, 0x70, 0x9f, 821 | 0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06, 822 | 0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89], 823 | RecoveryId(1))) 824 | } 825 | 826 | #[test] 827 | fn signature_serialize_roundtrip() { 828 | let mut s = Secp256k1::new(); 829 | s.randomize(&mut thread_rng()); 830 | 831 | let mut msg = [0; 32]; 832 | for _ in 0..100 { 833 | thread_rng().fill(&mut msg); 834 | let msg = Message::from_slice(&msg).unwrap(); 835 | 836 | let (sk, _) = s.generate_keypair(&mut thread_rng()).unwrap(); 837 | let sig1 = s.sign(&msg, &sk).unwrap(); 838 | let der = sig1.serialize_der(&s); 839 | let sig2 = Signature::from_der(&s, &der[..]).unwrap(); 840 | assert_eq!(sig1, sig2); 841 | 842 | let compact = sig1.serialize_compact(&s); 843 | let sig2 = Signature::from_compact(&s, &compact[..]).unwrap(); 844 | assert_eq!(sig1, sig2); 845 | 846 | round_trip_serde!(sig1); 847 | 848 | assert!(Signature::from_compact(&s, &der[..]).is_err()); 849 | assert!(Signature::from_compact(&s, &compact[0..4]).is_err()); 850 | assert!(Signature::from_der(&s, &compact[..]).is_err()); 851 | assert!(Signature::from_der(&s, &der[0..4]).is_err()); 852 | } 853 | } 854 | 855 | #[test] 856 | fn signature_lax_der() { 857 | macro_rules! check_lax_sig( 858 | ($hex:expr) => ({ 859 | let secp = Secp256k1::without_caps(); 860 | let sig = hex!($hex); 861 | assert!(Signature::from_der_lax(&secp, &sig[..]).is_ok()); 862 | }) 863 | ); 864 | 865 | check_lax_sig!("304402204c2dd8a9b6f8d425fcd8ee9a20ac73b619906a6367eac6cb93e70375225ec0160220356878eff111ff3663d7e6bf08947f94443845e0dcc54961664d922f7660b80c"); 866 | check_lax_sig!("304402202ea9d51c7173b1d96d331bd41b3d1b4e78e66148e64ed5992abd6ca66290321c0220628c47517e049b3e41509e9d71e480a0cdc766f8cdec265ef0017711c1b5336f"); 867 | check_lax_sig!("3045022100bf8e050c85ffa1c313108ad8c482c4849027937916374617af3f2e9a881861c9022023f65814222cab09d5ec41032ce9c72ca96a5676020736614de7b78a4e55325a"); 868 | check_lax_sig!("3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45"); 869 | check_lax_sig!("3046022100eaa5f90483eb20224616775891397d47efa64c68b969db1dacb1c30acdfc50aa022100cf9903bbefb1c8000cf482b0aeeb5af19287af20bd794de11d82716f9bae3db1"); 870 | check_lax_sig!("3045022047d512bc85842ac463ca3b669b62666ab8672ee60725b6c06759e476cebdc6c102210083805e93bd941770109bcc797784a71db9e48913f702c56e60b1c3e2ff379a60"); 871 | check_lax_sig!("3044022023ee4e95151b2fbbb08a72f35babe02830d14d54bd7ed1320e4751751d1baa4802206235245254f58fd1be6ff19ca291817da76da65c2f6d81d654b5185dd86b8acf"); 872 | } 873 | 874 | #[test] 875 | fn sign_and_verify() { 876 | let mut s = Secp256k1::new(); 877 | s.randomize(&mut thread_rng()); 878 | 879 | let mut msg = [0; 32]; 880 | for _ in 0..100 { 881 | thread_rng().fill(&mut msg); 882 | let msg = Message::from_slice(&msg).unwrap(); 883 | 884 | let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); 885 | let sig = s.sign(&msg, &sk).unwrap(); 886 | assert_eq!(s.verify(&msg, &sig, &pk), Ok(())); 887 | } 888 | } 889 | 890 | #[test] 891 | fn sign_and_verify_extreme() { 892 | let mut s = Secp256k1::new(); 893 | s.randomize(&mut thread_rng()); 894 | 895 | // Wild keys: 1, CURVE_ORDER - 1 896 | // Wild msgs: 0, 1, CURVE_ORDER - 1, CURVE_ORDER 897 | let mut wild_keys = [[0; 32]; 2]; 898 | let mut wild_msgs = [[0; 32]; 4]; 899 | 900 | wild_keys[0][0] = 1; 901 | wild_msgs[1][0] = 1; 902 | 903 | use crate::constants; 904 | wild_keys[1][..].copy_from_slice(&constants::CURVE_ORDER[..]); 905 | wild_msgs[1][..].copy_from_slice(&constants::CURVE_ORDER[..]); 906 | wild_msgs[2][..].copy_from_slice(&constants::CURVE_ORDER[..]); 907 | 908 | wild_keys[1][0] -= 1; 909 | wild_msgs[1][0] -= 1; 910 | 911 | for key in wild_keys.iter().map(|k| SecretKey::from_slice(&s, &k[..]).unwrap()) { 912 | for msg in wild_msgs.iter().map(|m| Message::from_slice(&m[..]).unwrap()) { 913 | let sig = s.sign(&msg, &key).unwrap(); 914 | let pk = PublicKey::from_secret_key(&s, &key).unwrap(); 915 | assert_eq!(s.verify(&msg, &sig, &pk), Ok(())); 916 | } 917 | } 918 | } 919 | 920 | #[test] 921 | fn sign_and_verify_fail() { 922 | let mut s = Secp256k1::new(); 923 | s.randomize(&mut thread_rng()); 924 | 925 | let mut msg = [0u8; 32]; 926 | thread_rng().fill(&mut msg); 927 | let msg = Message::from_slice(&msg).unwrap(); 928 | 929 | let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); 930 | 931 | let sigr = s.sign_recoverable(&msg, &sk).unwrap(); 932 | let sig = sigr.to_standard(&s); 933 | 934 | let mut msg = [0u8; 32]; 935 | thread_rng().fill(&mut msg); 936 | let msg = Message::from_slice(&msg).unwrap(); 937 | assert_eq!(s.verify(&msg, &sig, &pk), Err(IncorrectSignature)); 938 | 939 | let recovered_key = s.recover(&msg, &sigr).unwrap(); 940 | assert!(recovered_key != pk); 941 | } 942 | 943 | #[test] 944 | fn sign_with_recovery() { 945 | let mut s = Secp256k1::new(); 946 | s.randomize(&mut thread_rng()); 947 | 948 | let mut msg = [0u8; 32]; 949 | thread_rng().fill(&mut msg); 950 | let msg = Message::from_slice(&msg).unwrap(); 951 | 952 | let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); 953 | 954 | let sig = s.sign_recoverable(&msg, &sk).unwrap(); 955 | 956 | assert_eq!(s.recover(&msg, &sig), Ok(pk)); 957 | } 958 | 959 | #[test] 960 | fn bad_recovery() { 961 | let mut s = Secp256k1::new(); 962 | s.randomize(&mut thread_rng()); 963 | 964 | let msg = Message::from_slice(&[0x55; 32]).unwrap(); 965 | 966 | // Zero is not a valid sig 967 | let sig = RecoverableSignature::from_compact(&s, &[0; 64], RecoveryId(0)).unwrap(); 968 | assert_eq!(s.recover(&msg, &sig), Err(InvalidSignature)); 969 | // ...but 111..111 is 970 | let sig = RecoverableSignature::from_compact(&s, &[1; 64], RecoveryId(0)).unwrap(); 971 | assert!(s.recover(&msg, &sig).is_ok()); 972 | } 973 | 974 | #[test] 975 | fn test_bad_slice() { 976 | let s = Secp256k1::new(); 977 | assert_eq!(Signature::from_der(&s, &[0; constants::MAX_SIGNATURE_SIZE + 1]), 978 | Err(InvalidSignature)); 979 | assert_eq!(Signature::from_der(&s, &[0; constants::MAX_SIGNATURE_SIZE]), 980 | Err(InvalidSignature)); 981 | 982 | assert_eq!(Message::from_slice(&[0; constants::MESSAGE_SIZE - 1]), 983 | Err(InvalidMessage)); 984 | assert_eq!(Message::from_slice(&[0; constants::MESSAGE_SIZE + 1]), 985 | Err(InvalidMessage)); 986 | assert!(Message::from_slice(&[0; constants::MESSAGE_SIZE]).is_ok()); 987 | } 988 | 989 | #[test] 990 | fn test_debug_output() { 991 | let s = Secp256k1::new(); 992 | let sig = RecoverableSignature::from_compact(&s, &[ 993 | 0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f, 994 | 0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6, 995 | 0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65, 996 | 0xc3, 0x6d, 0xed, 0xf4, 0x09, 0x2e, 0x88, 0x98, 997 | 0x4c, 0x1a, 0x97, 0x16, 0x52, 0xe0, 0xad, 0xa8, 998 | 0x80, 0x12, 0x0e, 0xf8, 0x02, 0x5e, 0x70, 0x9f, 999 | 0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06, 1000 | 0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89], 1001 | RecoveryId(1)).unwrap(); 1002 | assert_eq!(&format!("{:?}", sig), "RecoverableSignature(98882e09f4ed6dc3659e43fc771e0cafa60b1f926f2b77041f744721adff7366898cb609d0ee128d06ae9aa3c48020ff9f705e02f80e1280a8ade05216971a4c01)"); 1003 | 1004 | let msg = Message([1, 2, 3, 4, 5, 6, 7, 8, 1005 | 9, 10, 11, 12, 13, 14, 15, 16, 1006 | 17, 18, 19, 20, 21, 22, 23, 24, 1007 | 25, 26, 27, 28, 29, 30, 31, 255]); 1008 | assert_eq!(&format!("{:?}", msg), "Message(0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1fff)"); 1009 | } 1010 | 1011 | #[test] 1012 | fn test_recov_sig_serialize_compact() { 1013 | let s = Secp256k1::new(); 1014 | 1015 | let recid_in = RecoveryId(1); 1016 | let bytes_in = &[ 1017 | 0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f, 1018 | 0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6, 1019 | 0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65, 1020 | 0xc3, 0x6d, 0xed, 0xf4, 0x09, 0x2e, 0x88, 0x98, 1021 | 0x4c, 0x1a, 0x97, 0x16, 0x52, 0xe0, 0xad, 0xa8, 1022 | 0x80, 0x12, 0x0e, 0xf8, 0x02, 0x5e, 0x70, 0x9f, 1023 | 0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06, 1024 | 0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89]; 1025 | let sig = RecoverableSignature::from_compact( 1026 | &s, bytes_in, recid_in).unwrap(); 1027 | let (recid_out, bytes_out) = sig.serialize_compact(&s); 1028 | assert_eq!(recid_in, recid_out); 1029 | assert_eq!(&bytes_in[..], &bytes_out[..]); 1030 | } 1031 | 1032 | #[test] 1033 | fn test_recov_id_conversion_between_i32() { 1034 | assert!(RecoveryId::from_i32(-1).is_err()); 1035 | assert!(RecoveryId::from_i32(0).is_ok()); 1036 | assert!(RecoveryId::from_i32(1).is_ok()); 1037 | assert!(RecoveryId::from_i32(2).is_ok()); 1038 | assert!(RecoveryId::from_i32(3).is_ok()); 1039 | assert!(RecoveryId::from_i32(4).is_err()); 1040 | let id0 = RecoveryId::from_i32(0).unwrap(); 1041 | assert_eq!(id0.to_i32(), 0); 1042 | let id1 = RecoveryId(1); 1043 | assert_eq!(id1.to_i32(), 1); 1044 | } 1045 | 1046 | #[test] 1047 | fn test_low_s() { 1048 | // nb this is a transaction on testnet 1049 | // txid 8ccc87b72d766ab3128f03176bb1c98293f2d1f85ebfaf07b82cc81ea6891fa9 1050 | // input number 3 1051 | let sig = hex!("3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45"); 1052 | let pk = hex!("031ee99d2b786ab3b0991325f2de8489246a6a3fdb700f6d0511b1d80cf5f4cd43"); 1053 | let msg = hex!("a4965ca63b7d8562736ceec36dfa5a11bf426eb65be8ea3f7a49ae363032da0d"); 1054 | 1055 | let secp = Secp256k1::new(); 1056 | let mut sig = Signature::from_der(&secp, &sig[..]).unwrap(); 1057 | let pk = PublicKey::from_slice(&secp, &pk[..]).unwrap(); 1058 | let msg = Message::from_slice(&msg[..]).unwrap(); 1059 | 1060 | // without normalization we expect this will fail 1061 | assert_eq!(secp.verify(&msg, &sig, &pk), Err(IncorrectSignature)); 1062 | // after normalization it should pass 1063 | sig.normalize_s(&secp); 1064 | assert_eq!(secp.verify(&msg, &sig, &pk), Ok(())); 1065 | } 1066 | } 1067 | 1068 | #[cfg(all(test, feature = "unstable"))] 1069 | mod benches { 1070 | use rand::{Rng, thread_rng}; 1071 | use test::{Bencher, black_box}; 1072 | 1073 | use super::{Secp256k1, Message}; 1074 | 1075 | #[bench] 1076 | pub fn generate(bh: &mut Bencher) { 1077 | struct CounterRng(u32); 1078 | impl Rng for CounterRng { 1079 | fn next_u32(&mut self) -> u32 { self.0 += 1; self.0 } 1080 | } 1081 | 1082 | let s = Secp256k1::new(); 1083 | let mut r = CounterRng(0); 1084 | bh.iter( || { 1085 | let (sk, pk) = s.generate_keypair(&mut r).unwrap(); 1086 | black_box(sk); 1087 | black_box(pk); 1088 | }); 1089 | } 1090 | 1091 | #[bench] 1092 | pub fn bench_sign(bh: &mut Bencher) { 1093 | let s = Secp256k1::new(); 1094 | let mut msg = [0u8; 32]; 1095 | thread_rng().fill(&mut msg); 1096 | let msg = Message::from_slice(&msg).unwrap(); 1097 | let (sk, _) = s.generate_keypair(&mut thread_rng()).unwrap(); 1098 | 1099 | bh.iter(|| { 1100 | let sig = s.sign(&msg, &sk).unwrap(); 1101 | black_box(sig); 1102 | }); 1103 | } 1104 | 1105 | #[bench] 1106 | pub fn bench_verify(bh: &mut Bencher) { 1107 | let s = Secp256k1::new(); 1108 | let mut msg = [0u8; 32]; 1109 | thread_rng().fill(&mut msg); 1110 | let msg = Message::from_slice(&msg).unwrap(); 1111 | let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); 1112 | let sig = s.sign(&msg, &sk).unwrap(); 1113 | 1114 | bh.iter(|| { 1115 | let res = s.verify(&msg, &sig, &pk).unwrap(); 1116 | black_box(res); 1117 | }); 1118 | } 1119 | 1120 | #[bench] 1121 | pub fn bench_recover(bh: &mut Bencher) { 1122 | let s = Secp256k1::new(); 1123 | let mut msg = [0u8; 32]; 1124 | thread_rng().fill(&mut msg); 1125 | let msg = Message::from_slice(&msg).unwrap(); 1126 | let (sk, _) = s.generate_keypair(&mut thread_rng()).unwrap(); 1127 | let sig = s.sign_recoverable(&msg, &sk).unwrap(); 1128 | 1129 | bh.iter(|| { 1130 | let res = s.recover(&msg, &sig).unwrap(); 1131 | black_box(res); 1132 | }); 1133 | } 1134 | } 1135 | --------------------------------------------------------------------------------