openethereum/accounts/ethkey/src/signature.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

326 lines
9.1 KiB
Rust
Raw Normal View History

2020-09-22 14:53:52 +02:00
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
2020-09-22 14:53:52 +02:00
// OpenEthereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
2020-09-22 14:53:52 +02:00
// OpenEthereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
2020-09-22 14:53:52 +02:00
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
2016-08-26 10:40:00 +02:00
use ethereum_types::{H256, H520};
2016-06-20 10:02:02 +02:00
use public_to_address;
2016-08-26 10:40:00 +02:00
use rustc_hex::{FromHex, ToHex};
use secp256k1::{
key::{PublicKey, SecretKey},
Error as SecpError, Message as SecpMessage, RecoverableSignature, RecoveryId,
};
use std::{
cmp::PartialEq,
fmt,
hash::{Hash, Hasher},
2016-06-20 10:02:02 +02:00
ops::{Deref, DerefMut},
str::FromStr,
};
use Address;
use Error;
use Message;
use Public;
use Secret;
use SECP256K1;
/// Signature encoded as RSV components
#[repr(C)]
pub struct Signature([u8; 65]);
impl Signature {
/// Get a slice into the 'r' portion of the data.
pub fn r(&self) -> &[u8] {
&self.0[0..32]
}
2020-08-05 06:08:03 +02:00
/// Get a slice into the 's' portion of the data.
pub fn s(&self) -> &[u8] {
&self.0[32..64]
}
2020-08-05 06:08:03 +02:00
/// Get the recovery byte.
pub fn v(&self) -> u8 {
self.0[64]
}
2020-08-05 06:08:03 +02:00
2017-05-11 12:18:20 +02:00
/// Encode the signature into RSV array (V altered to be in "Electrum" notation).
pub fn into_electrum(mut self) -> [u8; 65] {
self.0[64] += 27;
self.0
}
2020-08-05 06:08:03 +02:00
2017-05-11 12:18:20 +02:00
/// Parse bytes as a signature encoded as RSV (V in "Electrum" notation).
/// May return empty (invalid) signature if given data has invalid length.
2017-05-11 12:18:20 +02:00
pub fn from_electrum(data: &[u8]) -> Self {
2017-05-24 11:53:02 +02:00
if data.len() != 65 || data[64] < 27 {
// fallback to empty (invalid) signature
return Signature::default();
}
2020-08-05 06:08:03 +02:00
let mut sig = [0u8; 65];
2017-05-11 12:18:20 +02:00
sig.copy_from_slice(data);
sig[64] -= 27;
Signature(sig)
}
2020-08-05 06:08:03 +02:00
/// Create a signature object from the sig.
pub fn from_rsv(r: &H256, s: &H256, v: u8) -> Self {
let mut sig = [0u8; 65];
sig[0..32].copy_from_slice(&r);
sig[32..64].copy_from_slice(&s);
sig[64] = v;
Signature(sig)
}
2020-08-05 06:08:03 +02:00
/// Check if this is a "low" signature.
pub fn is_low_s(&self) -> bool {
H256::from_slice(self.s())
<= "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0".into()
}
2020-08-05 06:08:03 +02:00
/// Check if each component of the signature is in range.
pub fn is_valid(&self) -> bool {
self.v() <= 1
&& H256::from_slice(self.r())
< "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141".into()
&& H256::from_slice(self.r()) >= 1.into()
&& H256::from_slice(self.s())
< "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141".into()
&& H256::from_slice(self.s()) >= 1.into()
}
}
// manual implementation large arrays don't have trait impls by default.
// remove when integer generics exist
impl PartialEq for Signature {
fn eq(&self, other: &Self) -> bool {
&self.0[..] == &other.0[..]
}
}
2016-09-29 16:20:56 +02:00
// manual implementation required in Rust 1.13+, see `std::cmp::AssertParamIsEq`.
impl Eq for Signature {}
// also manual for the same reason, but the pretty printing might be useful.
impl fmt::Debug for Signature {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
f.debug_struct("Signature")
.field("r", &self.0[0..32].to_hex())
.field("s", &self.0[32..64].to_hex())
.field("v", &self.0[64..65].to_hex())
.finish()
}
}
impl fmt::Display for Signature {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "{}", self.to_hex())
}
}
impl FromStr for Signature {
type Err = Error;
2020-08-05 06:08:03 +02:00
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.from_hex() {
Ok(ref hex) if hex.len() == 65 => {
let mut data = [0; 65];
data.copy_from_slice(&hex[0..65]);
Ok(Signature(data))
}
_ => Err(Error::InvalidSignature),
}
}
}
impl Default for Signature {
fn default() -> Self {
Signature([0; 65])
}
}
2016-08-26 10:40:00 +02:00
impl Hash for Signature {
fn hash<H: Hasher>(&self, state: &mut H) {
H520::from(self.0).hash(state);
}
}
2016-08-26 11:27:54 +02:00
impl Clone for Signature {
fn clone(&self) -> Self {
Signature(self.0)
}
}
impl From<[u8; 65]> for Signature {
fn from(s: [u8; 65]) -> Self {
Signature(s)
}
}
impl Into<[u8; 65]> for Signature {
fn into(self) -> [u8; 65] {
self.0
}
}
impl From<Signature> for H520 {
fn from(s: Signature) -> Self {
H520::from(s.0)
}
}
impl From<H520> for Signature {
fn from(bytes: H520) -> Self {
Signature(bytes.into())
}
}
impl Deref for Signature {
type Target = [u8; 65];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Signature {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
pub fn sign(secret: &Secret, message: &Message) -> Result<Signature, Error> {
let context = &SECP256K1;
let sec = SecretKey::from_slice(context, &secret)?;
let s = context.sign_recoverable(&SecpMessage::from_slice(&message[..])?, &sec)?;
let (rec_id, data) = s.serialize_compact(context);
let mut data_arr = [0; 65];
2020-08-05 06:08:03 +02:00
// no need to check if s is low, it always is
data_arr[0..64].copy_from_slice(&data[0..64]);
data_arr[64] = rec_id.to_i32() as u8;
Ok(Signature(data_arr))
}
2016-06-20 10:02:02 +02:00
pub fn verify_public(
public: &Public,
signature: &Signature,
message: &Message,
) -> Result<bool, Error> {
let context = &SECP256K1;
let rsig = RecoverableSignature::from_compact(
context,
&signature[0..64],
RecoveryId::from_i32(signature[64] as i32)?,
)?;
let sig = rsig.to_standard(context);
2020-08-05 06:08:03 +02:00
let pdata: [u8; 65] = {
let mut temp = [4u8; 65];
temp[1..65].copy_from_slice(&**public);
temp
};
2020-08-05 06:08:03 +02:00
let publ = PublicKey::from_slice(context, &pdata)?;
match context.verify(&SecpMessage::from_slice(&message[..])?, &sig, &publ) {
Ok(_) => Ok(true),
Err(SecpError::IncorrectSignature) => Ok(false),
Err(x) => Err(Error::from(x)),
}
}
2016-06-20 10:02:02 +02:00
pub fn verify_address(
address: &Address,
signature: &Signature,
message: &Message,
) -> Result<bool, Error> {
let public = recover(signature, message)?;
2016-06-20 10:02:02 +02:00
let recovered_address = public_to_address(&public);
Ok(address == &recovered_address)
}
pub fn recover(signature: &Signature, message: &Message) -> Result<Public, Error> {
let context = &SECP256K1;
let rsig = RecoverableSignature::from_compact(
context,
&signature[0..64],
RecoveryId::from_i32(signature[64] as i32)?,
)?;
let pubkey = context.recover(&SecpMessage::from_slice(&message[..])?, &rsig)?;
2016-06-20 10:02:02 +02:00
let serialized = pubkey.serialize_vec(context, false);
2020-08-05 06:08:03 +02:00
2016-06-20 10:02:02 +02:00
let mut public = Public::default();
public.copy_from_slice(&serialized[1..65]);
Ok(public)
}
#[cfg(test)]
mod tests {
2016-06-20 10:02:02 +02:00
use super::{recover, sign, verify_address, verify_public, Signature};
use std::str::FromStr;
use Generator;
use Message;
2016-06-20 10:02:02 +02:00
use Random;
2020-08-05 06:08:03 +02:00
#[test]
fn vrs_conversion() {
// given
let keypair = Random.generate().unwrap();
let message = Message::default();
let signature = sign(keypair.secret(), &message).unwrap();
2020-08-05 06:08:03 +02:00
// when
2017-05-11 14:58:24 +02:00
let vrs = signature.clone().into_electrum();
let from_vrs = Signature::from_electrum(&vrs);
2020-08-05 06:08:03 +02:00
// then
assert_eq!(signature, from_vrs);
}
2020-08-05 06:08:03 +02:00
#[test]
fn signature_to_and_from_str() {
let keypair = Random.generate().unwrap();
let message = Message::default();
let signature = sign(keypair.secret(), &message).unwrap();
let string = format!("{}", signature);
let deserialized = Signature::from_str(&string).unwrap();
assert_eq!(signature, deserialized);
}
2020-08-05 06:08:03 +02:00
#[test]
2016-06-20 10:02:02 +02:00
fn sign_and_recover_public() {
let keypair = Random.generate().unwrap();
let message = Message::default();
let signature = sign(keypair.secret(), &message).unwrap();
assert_eq!(keypair.public(), &recover(&signature, &message).unwrap());
}
2020-08-05 06:08:03 +02:00
2016-06-20 10:02:02 +02:00
#[test]
fn sign_and_verify_public() {
let keypair = Random.generate().unwrap();
let message = Message::default();
let signature = sign(keypair.secret(), &message).unwrap();
assert!(verify_public(keypair.public(), &signature, &message).unwrap());
}
2020-08-05 06:08:03 +02:00
2016-06-20 10:02:02 +02:00
#[test]
fn sign_and_verify_address() {
let keypair = Random.generate().unwrap();
let message = Message::default();
let signature = sign(keypair.secret(), &message).unwrap();
2016-06-20 10:02:02 +02:00
assert!(verify_address(&keypair.address(), &signature, &message).unwrap());
}
}