Skip to content

Commit c47ead9

Browse files
Move Signature and SerializedSignature to new ecdsa module
With the introduction of Schnorr signatures, exporting a `Signature` type without any further qualification is ambiguous. To minimize the ambiguity, the `ecdsa` module is public which should encourage users to refer to its types as `ecdsa::Signature` and `ecdsa::SerializedSignature`. To reduce ambiguity in the APIs on `Secp256k1`, we deprecate several fucntions and introduce new variants that explicitly mention the use of the ECDSA signature algorithm. Due to the move of `Signature` and `SerializedSignature` to a new module, this patch is a breaking change. The impact is minimal though and fixing the compile errors encourages a qualified naming of the type.
1 parent 49c7e21 commit c47ead9

File tree

6 files changed

+483
-410
lines changed

6 files changed

+483
-410
lines changed

examples/sign_verify.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@ extern crate bitcoin_hashes;
22
extern crate secp256k1;
33

44
use bitcoin_hashes::{sha256, Hash};
5-
use secp256k1::{Error, Message, PublicKey, Secp256k1, SecretKey, Signature, Signing, Verification};
5+
use secp256k1::{Error, Message, PublicKey, Secp256k1, SecretKey, ecdsa, Signing, Verification};
66

77
fn verify<C: Verification>(secp: &Secp256k1<C>, msg: &[u8], sig: [u8; 64], pubkey: [u8; 33]) -> Result<bool, Error> {
88
let msg = sha256::Hash::hash(msg);
99
let msg = Message::from_slice(&msg)?;
10-
let sig = Signature::from_compact(&sig)?;
10+
let sig = ecdsa::Signature::from_compact(&sig)?;
1111
let pubkey = PublicKey::from_slice(&pubkey)?;
1212

13-
Ok(secp.verify(&msg, &sig, &pubkey).is_ok())
13+
Ok(secp.verify_ecdsa(&msg, &sig, &pubkey).is_ok())
1414
}
1515

16-
fn sign<C: Signing>(secp: &Secp256k1<C>, msg: &[u8], seckey: [u8; 32]) -> Result<Signature, Error> {
16+
fn sign<C: Signing>(secp: &Secp256k1<C>, msg: &[u8], seckey: [u8; 32]) -> Result<ecdsa::Signature, Error> {
1717
let msg = sha256::Hash::hash(msg);
1818
let msg = Message::from_slice(&msg)?;
1919
let seckey = SecretKey::from_slice(&seckey)?;
20-
Ok(secp.sign(&msg, &seckey))
20+
Ok(secp.sign_ecdsa(&msg, &seckey))
2121
}
2222

2323
fn main() {

examples/sign_verify_recovery.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,22 @@ extern crate bitcoin_hashes;
33
extern crate secp256k1;
44

55
use bitcoin_hashes::{sha256, Hash};
6-
use secp256k1::recovery::{RecoverableSignature, RecoveryId};
7-
use secp256k1::{Error, Message, PublicKey, Secp256k1, SecretKey, Signing, Verification};
6+
use secp256k1::{Error, Message, PublicKey, Secp256k1, SecretKey, Signing, Verification, ecdsa};
87

98
fn recover<C: Verification>(secp: &Secp256k1<C>,msg: &[u8],sig: [u8; 64],recovery_id: u8) -> Result<PublicKey, Error> {
109
let msg = sha256::Hash::hash(msg);
1110
let msg = Message::from_slice(&msg)?;
12-
let id = RecoveryId::from_i32(recovery_id as i32)?;
13-
let sig = RecoverableSignature::from_compact(&sig, id)?;
11+
let id = ecdsa::RecoveryId::from_i32(recovery_id as i32)?;
12+
let sig = ecdsa::RecoverableSignature::from_compact(&sig, id)?;
1413

15-
secp.recover(&msg, &sig)
14+
secp.recover_ecdsa(&msg, &sig)
1615
}
1716

18-
fn sign_recovery<C: Signing>(secp: &Secp256k1<C>, msg: &[u8], seckey: [u8; 32]) -> Result<RecoverableSignature, Error> {
17+
fn sign_recovery<C: Signing>(secp: &Secp256k1<C>, msg: &[u8], seckey: [u8; 32]) -> Result<ecdsa::RecoverableSignature, Error> {
1918
let msg = sha256::Hash::hash(msg);
2019
let msg = Message::from_slice(&msg)?;
2120
let seckey = SecretKey::from_slice(&seckey)?;
22-
Ok(secp.sign_recoverable(&msg, &seckey))
21+
Ok(secp.sign_ecdsa_recoverable(&msg, &seckey))
2322
}
2423

2524
fn main() {

no_std_test/src/main.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,22 +106,22 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize {
106106
let public_key = PublicKey::from_secret_key(&secp, &secret_key);
107107
let message = Message::from_slice(&[0xab; 32]).expect("32 bytes");
108108

109-
let sig = secp.sign(&message, &secret_key);
110-
assert!(secp.verify(&message, &sig, &public_key).is_ok());
109+
let sig = secp.sign_ecdsa(&message, &secret_key);
110+
assert!(secp.verify_ecdsa(&message, &sig, &public_key).is_ok());
111111

112-
let rec_sig = secp.sign_recoverable(&message, &secret_key);
113-
assert!(secp.verify(&message, &rec_sig.to_standard(), &public_key).is_ok());
114-
assert_eq!(public_key, secp.recover(&message, &rec_sig).unwrap());
112+
let rec_sig = secp.sign_ecdsa_recoverable(&message, &secret_key);
113+
assert!(secp.verify_ecdsa(&message, &rec_sig.to_standard(), &public_key).is_ok());
114+
assert_eq!(public_key, secp.recover_ecdsa(&message, &rec_sig).unwrap());
115115
let (rec_id, data) = rec_sig.serialize_compact();
116-
let new_rec_sig = recovery::RecoverableSignature::from_compact(&data, rec_id).unwrap();
116+
let new_rec_sig = ecdsa::RecoverableSignature::from_compact(&data, rec_id).unwrap();
117117
assert_eq!(rec_sig, new_rec_sig);
118118

119119
let mut cbor_ser = [0u8; 100];
120120
let writer = SliceWrite::new(&mut cbor_ser[..]);
121121
let mut ser = Serializer::new(writer);
122122
sig.serialize(&mut ser).unwrap();
123123
let size = ser.into_inner().bytes_written();
124-
let new_sig: Signature = de::from_mut_slice(&mut cbor_ser[..size]).unwrap();
124+
let new_sig: ecdsa::Signature = de::from_mut_slice(&mut cbor_ser[..size]).unwrap();
125125
assert_eq!(sig, new_sig);
126126

127127
let _ = SharedSecret::new(&public_key, &secret_key);

src/ecdsa/mod.rs

Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
//! Structs and functionality related to the ECDSA signature algorithm.
2+
3+
use core::{fmt, str, ops};
4+
use Error;
5+
use ffi::CPtr;
6+
use ffi;
7+
use from_hex;
8+
9+
#[cfg(feature = "recovery")]
10+
mod recovery;
11+
12+
#[cfg(feature = "recovery")]
13+
pub use self::recovery::{RecoveryId, RecoverableSignature};
14+
15+
/// An ECDSA signature
16+
#[derive(Copy, Clone, PartialEq, Eq)]
17+
pub struct Signature(pub(crate) ffi::Signature);
18+
19+
/// A DER serialized Signature
20+
#[derive(Copy, Clone)]
21+
pub struct SerializedSignature {
22+
data: [u8; 72],
23+
len: usize,
24+
}
25+
26+
impl fmt::Debug for Signature {
27+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
28+
fmt::Display::fmt(self, f)
29+
}
30+
}
31+
32+
impl fmt::Display for Signature {
33+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
34+
let sig = self.serialize_der();
35+
for v in sig.iter() {
36+
write!(f, "{:02x}", v)?;
37+
}
38+
Ok(())
39+
}
40+
}
41+
42+
impl str::FromStr for Signature {
43+
type Err = Error;
44+
fn from_str(s: &str) -> Result<Signature, Error> {
45+
let mut res = [0u8; 72];
46+
match from_hex(s, &mut res) {
47+
Ok(x) => Signature::from_der(&res[0..x]),
48+
_ => Err(Error::InvalidSignature),
49+
}
50+
}
51+
}
52+
53+
impl Default for SerializedSignature {
54+
fn default() -> SerializedSignature {
55+
SerializedSignature {
56+
data: [0u8; 72],
57+
len: 0,
58+
}
59+
}
60+
}
61+
62+
impl PartialEq for SerializedSignature {
63+
fn eq(&self, other: &SerializedSignature) -> bool {
64+
self.data[..self.len] == other.data[..other.len]
65+
}
66+
}
67+
68+
impl AsRef<[u8]> for SerializedSignature {
69+
fn as_ref(&self) -> &[u8] {
70+
&self.data[..self.len]
71+
}
72+
}
73+
74+
impl ops::Deref for SerializedSignature {
75+
type Target = [u8];
76+
77+
fn deref(&self) -> &[u8] {
78+
&self.data[..self.len]
79+
}
80+
}
81+
82+
impl Eq for SerializedSignature {}
83+
84+
impl SerializedSignature {
85+
/// Get a pointer to the underlying data with the specified capacity.
86+
pub(crate) fn get_data_mut_ptr(&mut self) -> *mut u8 {
87+
self.data.as_mut_ptr()
88+
}
89+
90+
/// Get the capacity of the underlying data buffer.
91+
pub fn capacity(&self) -> usize {
92+
self.data.len()
93+
}
94+
95+
/// Get the len of the used data.
96+
pub fn len(&self) -> usize {
97+
self.len
98+
}
99+
100+
/// Set the length of the object.
101+
pub(crate) fn set_len(&mut self, len: usize) {
102+
self.len = len;
103+
}
104+
105+
/// Convert the serialized signature into the Signature struct.
106+
/// (This DER deserializes it)
107+
pub fn to_signature(&self) -> Result<Signature, Error> {
108+
Signature::from_der(&self)
109+
}
110+
111+
/// Create a SerializedSignature from a Signature.
112+
/// (this DER serializes it)
113+
pub fn from_signature(sig: &Signature) -> SerializedSignature {
114+
sig.serialize_der()
115+
}
116+
117+
/// Check if the space is zero.
118+
pub fn is_empty(&self) -> bool { self.len() == 0 }
119+
}
120+
121+
impl Signature {
122+
#[inline]
123+
/// Converts a DER-encoded byte slice to a signature
124+
pub fn from_der(data: &[u8]) -> Result<Signature, Error> {
125+
if data.is_empty() {return Err(Error::InvalidSignature);}
126+
127+
unsafe {
128+
let mut ret = ffi::Signature::new();
129+
if ffi::secp256k1_ecdsa_signature_parse_der(
130+
ffi::secp256k1_context_no_precomp,
131+
&mut ret,
132+
data.as_c_ptr(),
133+
data.len() as usize,
134+
) == 1
135+
{
136+
Ok(Signature(ret))
137+
} else {
138+
Err(Error::InvalidSignature)
139+
}
140+
}
141+
}
142+
143+
/// Converts a 64-byte compact-encoded byte slice to a signature
144+
pub fn from_compact(data: &[u8]) -> Result<Signature, Error> {
145+
if data.len() != 64 {
146+
return Err(Error::InvalidSignature)
147+
}
148+
149+
unsafe {
150+
let mut ret = ffi::Signature::new();
151+
if ffi::secp256k1_ecdsa_signature_parse_compact(
152+
ffi::secp256k1_context_no_precomp,
153+
&mut ret,
154+
data.as_c_ptr(),
155+
) == 1
156+
{
157+
Ok(Signature(ret))
158+
} else {
159+
Err(Error::InvalidSignature)
160+
}
161+
}
162+
}
163+
164+
/// Converts a "lax DER"-encoded byte slice to a signature. This is basically
165+
/// only useful for validating signatures in the Bitcoin blockchain from before
166+
/// 2016. It should never be used in new applications. This library does not
167+
/// support serializing to this "format"
168+
pub fn from_der_lax(data: &[u8]) -> Result<Signature, Error> {
169+
if data.is_empty() {return Err(Error::InvalidSignature);}
170+
171+
unsafe {
172+
let mut ret = ffi::Signature::new();
173+
if ffi::ecdsa_signature_parse_der_lax(
174+
ffi::secp256k1_context_no_precomp,
175+
&mut ret,
176+
data.as_c_ptr(),
177+
data.len() as usize,
178+
) == 1
179+
{
180+
Ok(Signature(ret))
181+
} else {
182+
Err(Error::InvalidSignature)
183+
}
184+
}
185+
}
186+
187+
/// Normalizes a signature to a "low S" form. In ECDSA, signatures are
188+
/// of the form (r, s) where r and s are numbers lying in some finite
189+
/// field. The verification equation will pass for (r, s) iff it passes
190+
/// for (r, -s), so it is possible to ``modify'' signatures in transit
191+
/// by flipping the sign of s. This does not constitute a forgery since
192+
/// the signed message still cannot be changed, but for some applications,
193+
/// changing even the signature itself can be a problem. Such applications
194+
/// require a "strong signature". It is believed that ECDSA is a strong
195+
/// signature except for this ambiguity in the sign of s, so to accommodate
196+
/// these applications libsecp256k1 will only accept signatures for which
197+
/// s is in the lower half of the field range. This eliminates the
198+
/// ambiguity.
199+
///
200+
/// However, for some systems, signatures with high s-values are considered
201+
/// valid. (For example, parsing the historic Bitcoin blockchain requires
202+
/// this.) For these applications we provide this normalization function,
203+
/// which ensures that the s value lies in the lower half of its range.
204+
pub fn normalize_s(&mut self) {
205+
unsafe {
206+
// Ignore return value, which indicates whether the sig
207+
// was already normalized. We don't care.
208+
ffi::secp256k1_ecdsa_signature_normalize(
209+
ffi::secp256k1_context_no_precomp,
210+
self.as_mut_c_ptr(),
211+
self.as_c_ptr(),
212+
);
213+
}
214+
}
215+
216+
/// Obtains a raw pointer suitable for use with FFI functions
217+
#[inline]
218+
pub fn as_ptr(&self) -> *const ffi::Signature {
219+
&self.0
220+
}
221+
222+
/// Obtains a raw mutable pointer suitable for use with FFI functions
223+
#[inline]
224+
pub fn as_mut_ptr(&mut self) -> *mut ffi::Signature {
225+
&mut self.0
226+
}
227+
228+
#[inline]
229+
/// Serializes the signature in DER format
230+
pub fn serialize_der(&self) -> SerializedSignature {
231+
let mut ret = SerializedSignature::default();
232+
let mut len: usize = ret.capacity();
233+
unsafe {
234+
let err = ffi::secp256k1_ecdsa_signature_serialize_der(
235+
ffi::secp256k1_context_no_precomp,
236+
ret.get_data_mut_ptr(),
237+
&mut len,
238+
self.as_c_ptr(),
239+
);
240+
debug_assert!(err == 1);
241+
ret.set_len(len);
242+
}
243+
ret
244+
}
245+
246+
#[inline]
247+
/// Serializes the signature in compact format
248+
pub fn serialize_compact(&self) -> [u8; 64] {
249+
let mut ret = [0u8; 64];
250+
unsafe {
251+
let err = ffi::secp256k1_ecdsa_signature_serialize_compact(
252+
ffi::secp256k1_context_no_precomp,
253+
ret.as_mut_c_ptr(),
254+
self.as_c_ptr(),
255+
);
256+
debug_assert!(err == 1);
257+
}
258+
ret
259+
}
260+
}
261+
262+
impl CPtr for Signature {
263+
type Target = ffi::Signature;
264+
265+
fn as_c_ptr(&self) -> *const Self::Target {
266+
self.as_ptr()
267+
}
268+
269+
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
270+
self.as_mut_ptr()
271+
}
272+
}
273+
274+
/// Creates a new signature from a FFI signature
275+
impl From<ffi::Signature> for Signature {
276+
#[inline]
277+
fn from(sig: ffi::Signature) -> Signature {
278+
Signature(sig)
279+
}
280+
}
281+
282+
#[cfg(feature = "serde")]
283+
impl ::serde::Serialize for Signature {
284+
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
285+
if s.is_human_readable() {
286+
s.collect_str(self)
287+
} else {
288+
s.serialize_bytes(&self.serialize_der())
289+
}
290+
}
291+
}
292+
293+
#[cfg(feature = "serde")]
294+
impl<'de> ::serde::Deserialize<'de> for Signature {
295+
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
296+
if d.is_human_readable() {
297+
d.deserialize_str(::serde_util::FromStrVisitor::new(
298+
"a hex string representing a DER encoded Signature"
299+
))
300+
} else {
301+
d.deserialize_bytes(::serde_util::BytesVisitor::new(
302+
"raw byte stream, that represents a DER encoded Signature",
303+
Signature::from_der
304+
))
305+
}
306+
}
307+
}

0 commit comments

Comments
 (0)