diff --git a/src/kernel_sdk/CHANGES.md b/src/kernel_sdk/CHANGES.md index a80827206e24dd4a37824471b161c576a6e869de..3f288b7c14ddc655a40fb4d8ca3a758ebae6aa2a 100644 --- a/src/kernel_sdk/CHANGES.md +++ b/src/kernel_sdk/CHANGES.md @@ -20,6 +20,7 @@ simplify kernel upgrades. - Update `Runtime::store_write` to write the whole slice; previously errored on slices longer than 2KB. - Remove uses of `proto-nairobi` feature flag. Feature flag remains on crates, but does nothing. +- Implements `PublicKeySignatureVerifier` for `PublicKey`. ### Installer client/kernel diff --git a/src/kernel_sdk/encoding/src/public_key.rs b/src/kernel_sdk/encoding/src/public_key.rs index 16e06156a743583f4c7109f552b2034e45ec1a31..3e7d90268fc880fbc0740a6df0fd963bb6c0eeb1 100644 --- a/src/kernel_sdk/encoding/src/public_key.rs +++ b/src/kernel_sdk/encoding/src/public_key.rs @@ -5,7 +5,10 @@ //! Public Key of Layer1. use std::fmt::Display; -use tezos_crypto_rs::hash::{PublicKeyEd25519, PublicKeyP256, PublicKeySecp256k1}; +use tezos_crypto_rs::hash::{ + PublicKeyEd25519, PublicKeyP256, PublicKeySecp256k1, Signature, +}; +use tezos_crypto_rs::{CryptoError, PublicKeySignatureVerifier}; use tezos_data_encoding::enc::BinWriter; use tezos_data_encoding::encoding::HasEncoding; use tezos_data_encoding::nom::NomReader; @@ -80,6 +83,23 @@ impl TryFrom<&str> for PublicKey { } } +impl PublicKeySignatureVerifier for PublicKey { + type Signature = Signature; + type Error = CryptoError; + + fn verify_signature( + &self, + signature: &Self::Signature, + msg: &[u8], + ) -> Result { + match self { + PublicKey::Ed25519(ed25519) => ed25519.verify_signature(signature, msg), + PublicKey::Secp256k1(secp256k1) => secp256k1.verify_signature(signature, msg), + PublicKey::P256(p256) => p256.verify_signature(signature, msg), + } + } +} + #[cfg(test)] mod test { use super::*; @@ -182,4 +202,108 @@ mod test { assert_eq!(2_u8, bin[0]); assert_eq!(public_key, deserde_pk); } + + #[test] + fn tz1_signature_signature_verification_succeeds() { + let tz1 = PublicKey::from_b58check( + "edpkvWR5truf7AMF3PZVCXx7ieQLCW4MpNDzM3VwPfmFWVbBZwswBw", + ) + .expect("public key decoding should work"); + let sig: Signature = Signature::from_base58_check( + "sigdGBG68q2vskMuac4AzyNb1xCJTfuU8MiMbQtmZLUCYydYrtTd5Lessn1EFLTDJzjXoYxRasZxXbx6tHnirbEJtikcMHt3" + ).expect("signature decoding should work"); + let msg = hex::decode( + "bcbb7b77cb0712e4cd02160308cfd53e8dde8a7980c4ff28b62deb12304913c2", + ) + .expect("payload decoding should work"); + + let result = tz1 + .verify_signature(&sig, &msg) + .expect("signature should be correct"); + assert!(result); + } + + #[test] + fn tz1_signature_signature_verification_fails() { + let tz1 = PublicKey::from_b58check( + "edpkuDMUm7Y53wp4gxeLBXuiAhXZrLn8XB1R83ksvvesH8Lp8bmCfK", + ) + .expect("public key decoding should work"); + let sig = Signature::from_base58_check( + "sigdGBG68q2vskMuac4AzyNb1xCJTfuU8MiMbQtmZLUCYydYrtTd5Lessn1EFLTDJzjXoYxRasZxXbx6tHnirbEJtikcMHt3" + ).expect("signature decoding should work"); + let msg = hex::decode( + "bcbb7b77cb0712e4cd02160308cfd53e8dde8a7980c4ff28b62deb12304913c2", + ) + .expect("payload decoding should work"); + + let result = tz1.verify_signature(&sig, &msg); + assert!(result.is_err()); + } + + #[test] + fn tz2_signature_signature_verification_succeeds() { + let tz2 = PublicKey::from_b58check( + "sppk7cwkTzCPptCSxSTvGNg4uqVcuTbyWooLnJp4yxJNH5DReUGxYvs", + ) + .expect("public key decoding should work"); + let sig = Signature::from_base58_check("sigrJ2jqanLupARzKGvzWgL1Lv6NGUqDovHKQg9MX4PtNtHXgcvG6131MRVzujJEXfvgbuRtfdGbXTFaYJJjuUVLNNZTf5q1").expect("signature decoding should work"); + let msg = hex::decode( + "5538e2cc90c9b053a12e2d2f3a985aff1809eac59501db4d644e4bb381b06b4b", + ) + .expect("payload decoding should work"); + + let result = tz2.verify_signature(&sig, &msg).unwrap(); + assert!(result); + } + + #[test] + fn tz2_signature_signature_verification_fails() { + let tz2 = "sppk7Zik17H7AxECMggqD1FyXUQdrGRFtz9X7aR8W2BhaJoWwSnPEGA"; + let tz2 = PublicKey::from_b58check(tz2).expect("parsing should world"); + let sig = Signature::from_base58_check("sigrJ2jqanLupARzKGvzWgL1Lv6NGUqDovHKQg9MX4PtNtHXgcvG6131MRVzujJEXfvgbuRtfdGbXTFaYJJjuUVLNNZTf5q1").expect("signature decoding should work"); + let msg = hex::decode( + "5538e2cc90c9b053a12e2d2f3a985aff1809eac59501db4d644e4bb381b06b4b", + ) + .expect("payload decoding should work"); + + let result = tz2.verify_signature(&sig, &msg).unwrap(); + assert!(!result); + } + + #[test] + fn tz3_signature_signature_verification_succeeds() { + let tz3 = PublicKey::from_b58check( + "p2pk67Cwb5Ke6oSmqeUbJxURXMe3coVnH9tqPiB2xD84CYhHbBKs4oM", + ) + .expect("decoding public key should work"); + let sig = Signature::from_base58_check( + "sigNCaj9CnmD94eZH9C7aPPqBbVCJF72fYmCFAXqEbWfqE633WNFWYQJFnDUFgRUQXR8fQ5tKSfJeTe6UAi75eTzzQf7AEc1" + ).expect("signature decoding should work"); + let msg = hex::decode( + "5538e2cc90c9b053a12e2d2f3a985aff1809eac59501db4d644e4bb381b06b4b", + ) + .expect("payload decoding should work"); + + let result = tz3.verify_signature(&sig, &msg).unwrap(); + assert!(result); + } + + #[test] + fn tz3_signature_signature_verification_fails() { + let tz3 = PublicKey::from_b58check( + "p2pk67VpBjWwoPULwXCpayec6rFxaAKv8VjJ8cVMHmLDCYARu31zx5Z", + ) + .expect("decoding public key should work"); + let sig = Signature::from_base58_check( + "sigNCaj9CnmD94eZH9C7aPPqBbVCJF72fYmCFAXqEbWfqE633WNFWYQJFnDUFgRUQXR8fQ5tKSfJeTe6UAi75eTzzQf7AEc1" + ).expect("signature decoding should work"); + let msg = hex::decode( + "5538e2cc90c9b053a12e2d2f3a985aff1809eac59501db4d644e4bb381b06b4b", + ) + .expect("payload decoding should work"); + + let result = tz3.verify_signature(&sig, &msg).unwrap(); + assert!(!result); + } }