crypto_utils/
verification.rs

1// Copyright (C) Polytope Labs Ltd.
2// SPDX-License-Identifier: Apache-2.0
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// 	http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use alloc::vec::Vec;
17use anyhow::anyhow;
18use codec::{Decode, DecodeWithMemTracking, Encode};
19
20#[derive(
21	Debug, Clone, Encode, Decode, DecodeWithMemTracking, scale_info::TypeInfo, PartialEq, Eq,
22)]
23pub enum Signature {
24	/// An Evm Address and signature
25	Evm { address: Vec<u8>, signature: Vec<u8> },
26	/// An Sr25519 public key and signature
27	Sr25519 { public_key: Vec<u8>, signature: Vec<u8> },
28	/// An Ed25519 public key and signature
29	Ed25519 { public_key: Vec<u8>, signature: Vec<u8> },
30}
31
32impl Signature {
33	/// verify the signature with the public key in the enum or optionally provide a public key
34	/// to be used to verify the signature
35	pub fn verify(
36		&self,
37		msg: &[u8; 32],
38		public_key_op: Option<Vec<u8>>,
39	) -> Result<Vec<u8>, anyhow::Error> {
40		match self {
41			Signature::Evm { signature, .. } => {
42				if signature.len() != 65 {
43					Err(anyhow!("Invalid Signature"))?
44				}
45
46				let mut sig = [0u8; 65];
47				sig.copy_from_slice(&signature);
48				let pub_key = sp_io::crypto::secp256k1_ecdsa_recover(&sig, msg)
49					.map_err(|_| anyhow!("Signature Verification failed"))?;
50				let signer = sp_io::hashing::keccak_256(&pub_key[..])[12..].to_vec();
51				Ok(signer)
52			},
53			Signature::Sr25519 { signature, public_key } => {
54				Self::verify_sr25519(signature, public_key, msg, &public_key_op)?;
55				Ok(public_key_op.unwrap_or(public_key.clone()))
56			},
57			Signature::Ed25519 { signature, public_key, .. } => {
58				let signature =
59					signature.as_slice().try_into().map_err(|_| anyhow!("Invalid Signature"))?;
60				let pub_key = public_key_op
61					.clone()
62					.unwrap_or(public_key.clone())
63					.as_slice()
64					.try_into()
65					.map_err(|_| anyhow!("Invalid Public Key"))?;
66				if !sp_io::crypto::ed25519_verify(&signature, msg, &pub_key) {
67					Err(anyhow!("Signature Verification failed"))?
68				}
69				Ok(public_key_op.unwrap_or(public_key.clone()))
70			},
71		}
72	}
73
74	fn verify_sr25519(
75		signature: &Vec<u8>,
76		public_key: &Vec<u8>,
77		msg: &[u8; 32],
78		public_key_op: &Option<Vec<u8>>,
79	) -> Result<[u8; 32], anyhow::Error> {
80		let signature =
81			signature.as_slice().try_into().map_err(|_| anyhow!("Invalid Signature"))?;
82
83		let pub_key = public_key_op
84			.clone()
85			.unwrap_or(public_key.clone())
86			.as_slice()
87			.try_into()
88			.map_err(|_| anyhow!("Invalid Public Key"))?;
89
90		if !sp_io::crypto::sr25519_verify(&signature, msg, &pub_key) {
91			return Err(anyhow!("Sr25519 signature verification failed"));
92		}
93
94		Ok(pub_key.into())
95	}
96
97	pub fn verify_and_get_sr25519_pubkey(
98		&self,
99		msg: &[u8; 32],
100		public_key_op: Option<Vec<u8>>,
101	) -> Result<[u8; 32], anyhow::Error> {
102		match self {
103			Signature::Sr25519 { public_key, signature } =>
104				Self::verify_sr25519(signature, public_key, msg, &public_key_op),
105			_ => Err(anyhow!("Signature is not of type Sr25519")),
106		}
107	}
108
109	pub fn signer(&self) -> Vec<u8> {
110		match self {
111			Signature::Evm { address, .. } => address.clone(),
112			Signature::Sr25519 { public_key, .. } => public_key.clone(),
113			Signature::Ed25519 { public_key, .. } => public_key.clone(),
114		}
115	}
116}