feat(identity): make secp256k1::SecretKey::sign infallible

Previously, this function would return an error in case the provided digest is not of 32 bytes long. As per our [spec](https://github.com/libp2p/specs/blob/master/peer-ids/peer-ids.md#secp256k1), we hash _all_ messages with SHA256 before signing, thus this error can never happen in practice.

This brings us one step closer to an infallible `Keypair::sign` which is now only fallible due to RSA signing. If we manage to fix that as well, constructors like `noise::Config::new` will become infallible.

Pull-Request: #3850.
This commit is contained in:
Thomas Eizinger
2023-05-12 04:43:14 +02:00
committed by GitHub
parent 1bf6264cbe
commit 25958a2f8c
3 changed files with 20 additions and 16 deletions

View File

@ -8,6 +8,10 @@
- Make `Keypair` and `PublicKey` opaque.
See [PR 3866].
- Remove `identity::secp256k1::SecretKey::sign_hash` and make `identity::secp256k1::SecretKey::sign` infallible.
See [PR 3850].
[PR 3850]: https://github.com/libp2p/rust-libp2p/pull/3850
[PR 3715]: https://github.com/libp2p/rust-libp2p/pull/3715
[PR 3863]: https://github.com/libp2p/rust-libp2p/pull/3863
[PR 3866]: https://github.com/libp2p/rust-libp2p/pull/3866

View File

@ -198,7 +198,7 @@ impl Keypair {
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
KeyPairInner::Rsa(ref pair) => pair.sign(msg),
#[cfg(feature = "secp256k1")]
KeyPairInner::Secp256k1(ref pair) => pair.secret().sign(msg),
KeyPairInner::Secp256k1(ref pair) => Ok(pair.secret().sign(msg)),
#[cfg(feature = "ecdsa")]
KeyPairInner::Ecdsa(ref pair) => Ok(pair.secret().sign(msg)),
}

View File

@ -20,7 +20,7 @@
//! Secp256k1 keys.
use super::error::{DecodingError, SigningError};
use super::error::DecodingError;
use asn1_der::typed::{DerDecodable, Sequence};
use core::cmp;
use core::fmt;
@ -142,26 +142,26 @@ impl SecretKey {
/// ECDSA signature, as defined in [RFC3278].
///
/// [RFC3278]: https://tools.ietf.org/html/rfc3278#section-8.2
pub fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, SigningError> {
self.sign_hash(Sha256::digest(msg).as_ref())
pub fn sign(&self, msg: &[u8]) -> Vec<u8> {
let generic_array = Sha256::digest(msg);
// FIXME: Once `generic-array` hits 1.0, we should be able to just use `Into` here.
let mut array = [0u8; 32];
array.copy_from_slice(generic_array.as_slice());
let message = Message::parse(&array);
libsecp256k1::sign(&message, &self.0)
.0
.serialize_der()
.as_ref()
.into()
}
/// Returns the raw bytes of the secret key.
pub fn to_bytes(&self) -> [u8; 32] {
self.0.serialize()
}
/// Sign a raw message of length 256 bits with this secret key, produces a DER-encoded
/// ECDSA signature.
pub fn sign_hash(&self, msg: &[u8]) -> Result<Vec<u8>, SigningError> {
let m = Message::parse_slice(msg)
.map_err(|_| SigningError::new("failed to parse secp256k1 digest"))?;
Ok(libsecp256k1::sign(&m, &self.0)
.0
.serialize_der()
.as_ref()
.into())
}
}
/// A Secp256k1 public key.