diff --git a/bitcoin/src/sign_message.rs b/bitcoin/src/sign_message.rs index e5fd655dd..d722d549a 100644 --- a/bitcoin/src/sign_message.rs +++ b/bitcoin/src/sign_message.rs @@ -108,16 +108,13 @@ mod message_signing { serialized } - /// Create from a byte slice. - pub fn from_slice(bytes: &[u8]) -> Result { - if bytes.len() != 65 { - return Err(MessageSignatureError::InvalidLength); - } + /// Creates a `MessageSignature` from a fixed-length array. + pub fn from_byte_array( + bytes: &[u8; 65], + ) -> Result { // We just check this here so we can safely subtract further. if bytes[0] < 27 { - return Err(MessageSignatureError::InvalidEncoding( - secp256k1::Error::InvalidRecoveryId, - )); + return Err(secp256k1::Error::InvalidRecoveryId); }; let recid = RecoveryId::from_i32(((bytes[0] - 27) & 0x03) as i32)?; Ok(MessageSignature { @@ -126,6 +123,14 @@ mod message_signing { }) } + /// Create a `MessageSignature` from a byte slice. + #[deprecated(since = "TBD", note = "Use `from_byte_array` instead.")] + pub fn from_slice(bytes: &[u8]) -> Result { + let byte_array: [u8; 65] = + bytes.try_into().map_err(|_| MessageSignatureError::InvalidLength)?; + Self::from_byte_array(&byte_array).map_err(MessageSignatureError::from) + } + /// Attempt to recover a public key from the signature and the signed message. /// /// To get the message hash from a message, use [super::signed_msg_hash]. @@ -170,9 +175,14 @@ mod message_signing { impl MessageSignature { /// Convert a signature from base64 encoding. pub fn from_base64(s: &str) -> Result { - let bytes = - BASE64_STANDARD.decode(s).map_err(|_| MessageSignatureError::InvalidBase64)?; - MessageSignature::from_slice(&bytes) + if s.len() != 88 { + return Err(MessageSignatureError::InvalidLength); + } + let mut byte_array = [0; 65]; + BASE64_STANDARD + .decode_slice_unchecked(s, &mut byte_array) + .map_err(|_| MessageSignatureError::InvalidBase64)?; + MessageSignature::from_byte_array(&byte_array).map_err(MessageSignatureError::from) } /// Convert to base64 encoding. @@ -258,6 +268,10 @@ mod tests { assert_eq!(signature2.is_signed_by_address(&secp, &p2pkh, msg_hash), Ok(true)); assert_eq!(pubkey.0, secp256k1::PublicKey::from_secret_key(&secp, &privkey)); + let signature_base64 = signature.to_base64(); + let signature_round_trip = + super::MessageSignature::from_base64(&signature_base64).expect("message signature"); + assert_eq!(signature, signature_round_trip); } #[test] diff --git a/hashes/src/sha256t.rs b/hashes/src/sha256t.rs index 655e58783..7f2fae50e 100644 --- a/hashes/src/sha256t.rs +++ b/hashes/src/sha256t.rs @@ -71,13 +71,14 @@ where pub fn from_engine(e: HashEngine) -> Hash { from_engine(e) } /// Copies a byte slice into a hash object. + #[deprecated(since = "TBD", note = "Use `from_byte_array` instead.")] pub fn from_slice(sl: &[u8]) -> Result, FromSliceError> { if sl.len() != 32 { Err(FromSliceError { expected: 32, got: sl.len() }) } else { let mut ret = [0; 32]; ret.copy_from_slice(sl); - Ok(Self::internal_new(ret)) + Ok(Self::from_byte_array(ret)) } }