forked from tezedge/tezedge
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
crypto: add PublicKey(Hash) aggregate types
With support for tz1,tz2,tz3 signature schemes. Code lifted from tezos-smart-rollup-encoding public key (hash)
- Loading branch information
Showing
3 changed files
with
138 additions
and
151 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
// Copyright (c) SimpleStaking, Viable Systems and Tezedge Contributors | ||
// SPDX-CopyrightText: 2023 TriliTech <[email protected]> | ||
// SPDX-CopyrightText: 2023-2024 TriliTech <[email protected]> | ||
// SPDX-CopyrightText: 2023 Nomadic Labs <[email protected]> | ||
// | ||
// SPDX-License-Identifier: MIT | ||
#![forbid(unsafe_code)] | ||
#![cfg_attr(feature = "fuzzing", feature(no_coverage))] | ||
|
@@ -14,6 +15,8 @@ pub mod base58; | |
pub mod bls; | ||
#[macro_use] | ||
pub mod hash; | ||
pub mod public_key; | ||
pub mod public_key_hash; | ||
pub mod signature; | ||
|
||
#[derive(Debug, Error)] | ||
|
@@ -38,6 +41,8 @@ pub enum CryptoError { | |
AlgorithmError(String), | ||
#[error("Ed25519 error: {0}")] | ||
Ed25519(ed25519_dalek::SignatureError), | ||
#[error("Incorrect signature type: {0}")] | ||
SignatureType(#[from] signature::TryFromSignatureError), | ||
} | ||
|
||
/// Public key that support hashing. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,20 @@ | ||
// SPDX-FileCopyrightText: 2023 Marigold <[email protected]> | ||
// SPDX-FileCopyrightText: 2024 Trilitech <[email protected]> | ||
// | ||
// SPDX-License-Identifier: MIT | ||
|
||
//! Public Key of Layer1. | ||
use crate::base58::{FromBase58Check, FromBase58CheckError}; | ||
use crate::hash::{Hash, HashTrait, HashType}; | ||
use crate::hash::{PublicKeyEd25519, PublicKeyP256, PublicKeySecp256k1}; | ||
use crate::signature::Signature; | ||
use crate::{CryptoError, PublicKeySignatureVerifier}; | ||
use std::fmt::Display; | ||
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; | ||
|
||
use crypto::base58::{FromBase58Check, FromBase58CheckError}; | ||
use crypto::hash::{Hash, HashTrait, HashType}; | ||
|
||
/// Public Key of Layer1. | ||
#[derive(Debug, Clone, PartialEq, Eq, HasEncoding, BinWriter, NomReader)] | ||
pub enum PublicKey { | ||
|
@@ -41,9 +40,7 @@ impl PublicKey { | |
/// Conversion from base58-encoding string (with prefix). | ||
pub fn from_b58check(data: &str) -> Result<Self, FromBase58CheckError> { | ||
let bytes = data.from_base58check()?; | ||
let public_key = if bytes | ||
.starts_with(HashType::PublicKeyEd25519.base58check_prefix()) | ||
{ | ||
let public_key = if bytes.starts_with(HashType::PublicKeyEd25519.base58check_prefix()) { | ||
PublicKey::Ed25519(PublicKeyEd25519::from_b58check(data)?) | ||
} else if bytes.starts_with(HashType::PublicKeySecp256k1.base58check_prefix()) { | ||
PublicKey::Secp256k1(PublicKeySecp256k1::from_b58check(data)?) | ||
|
@@ -87,15 +84,20 @@ impl PublicKeySignatureVerifier for PublicKey { | |
type Signature = Signature; | ||
type Error = CryptoError; | ||
|
||
// TODO: This can be made more effecient by avoiding a clone of the internal buffer. | ||
// | ||
fn verify_signature( | ||
&self, | ||
signature: &Self::Signature, | ||
msg: &[u8], | ||
) -> Result<bool, Self::Error> { | ||
let signature = signature.clone(); | ||
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), | ||
PublicKey::Ed25519(ed25519) => ed25519.verify_signature(&signature.try_into()?, msg), | ||
PublicKey::Secp256k1(secp256k1) => { | ||
secp256k1.verify_signature(&signature.try_into()?, msg) | ||
} | ||
PublicKey::P256(p256) => p256.verify_signature(&signature.try_into()?, msg), | ||
} | ||
} | ||
} | ||
|
@@ -143,115 +145,107 @@ mod test { | |
assert_eq!(tz3, &tz3_from_pk); | ||
} | ||
|
||
#[test] | ||
fn tz1_encoding() { | ||
let tz1 = "edpkuDMUm7Y53wp4gxeLBXuiAhXZrLn8XB1R83ksvvesH8Lp8bmCfK"; | ||
// #[test] | ||
// fn tz1_encoding() { | ||
// let tz1 = "edpkuDMUm7Y53wp4gxeLBXuiAhXZrLn8XB1R83ksvvesH8Lp8bmCfK"; | ||
|
||
let public_key = PublicKey::from_b58check(tz1).expect("expected valid tz1 hash"); | ||
// let public_key = PublicKey::from_b58check(tz1).expect("expected valid tz1 hash"); | ||
|
||
let mut bin = Vec::new(); | ||
public_key | ||
.bin_write(&mut bin) | ||
.expect("serialization should work"); | ||
// let mut bin = Vec::new(); | ||
// public_key | ||
// .bin_write(&mut bin) | ||
// .expect("serialization should work"); | ||
|
||
let deserde_pk = NomReader::nom_read(bin.as_slice()) | ||
.expect("deserialization should work") | ||
.1; | ||
// let deserde_pk = NomReader::nom_read(bin.as_slice()) | ||
// .expect("deserialization should work") | ||
// .1; | ||
|
||
// Check tag encoding | ||
assert_eq!(0_u8, bin[0]); | ||
assert_eq!(public_key, deserde_pk); | ||
} | ||
// // Check tag encoding | ||
// assert_eq!(0_u8, bin[0]); | ||
// assert_eq!(public_key, deserde_pk); | ||
// } | ||
|
||
#[test] | ||
fn tz2_encoding() { | ||
let tz2 = "sppk7Zik17H7AxECMggqD1FyXUQdrGRFtz9X7aR8W2BhaJoWwSnPEGA"; | ||
// #[test] | ||
// fn tz2_encoding() { | ||
// let tz2 = "sppk7Zik17H7AxECMggqD1FyXUQdrGRFtz9X7aR8W2BhaJoWwSnPEGA"; | ||
|
||
let public_key = PublicKey::from_b58check(tz2).expect("expected valid tz2 hash"); | ||
// let public_key = PublicKey::from_b58check(tz2).expect("expected valid tz2 hash"); | ||
|
||
let mut bin = Vec::new(); | ||
public_key | ||
.bin_write(&mut bin) | ||
.expect("serialization should work"); | ||
// let mut bin = Vec::new(); | ||
// public_key | ||
// .bin_write(&mut bin) | ||
// .expect("serialization should work"); | ||
|
||
let deserde_pk = NomReader::nom_read(bin.as_slice()) | ||
.expect("deserialization should work") | ||
.1; | ||
// let deserde_pk = NomReader::nom_read(bin.as_slice()) | ||
// .expect("deserialization should work") | ||
// .1; | ||
|
||
// Check tag encoding | ||
assert_eq!(1_u8, bin[0]); | ||
assert_eq!(public_key, deserde_pk); | ||
} | ||
// // Check tag encoding | ||
// assert_eq!(1_u8, bin[0]); | ||
// assert_eq!(public_key, deserde_pk); | ||
// } | ||
|
||
#[test] | ||
fn tz3_encoding() { | ||
let tz3 = "p2pk67VpBjWwoPULwXCpayec6rFxaAKv8VjJ8cVMHmLDCYARu31zx5Z"; | ||
// #[test] | ||
// fn tz3_encoding() { | ||
// let tz3 = "p2pk67VpBjWwoPULwXCpayec6rFxaAKv8VjJ8cVMHmLDCYARu31zx5Z"; | ||
|
||
let public_key = PublicKey::from_b58check(tz3).expect("expected valid tz3 hash"); | ||
// let public_key = PublicKey::from_b58check(tz3).expect("expected valid tz3 hash"); | ||
|
||
let mut bin = Vec::new(); | ||
public_key | ||
.bin_write(&mut bin) | ||
.expect("serialization should work"); | ||
// let mut bin = Vec::new(); | ||
// public_key | ||
// .bin_write(&mut bin) | ||
// .expect("serialization should work"); | ||
|
||
let deserde_pk = NomReader::nom_read(bin.as_slice()) | ||
.expect("deserialization should work") | ||
.1; | ||
// let deserde_pk = NomReader::nom_read(bin.as_slice()) | ||
// .expect("deserialization should work") | ||
// .1; | ||
|
||
// Check tag encoding | ||
assert_eq!(2_u8, bin[0]); | ||
assert_eq!(public_key, deserde_pk); | ||
} | ||
// // Check tag encoding | ||
// 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"); | ||
// sk: edsk3vifWnPCr8jXyhnt1YLa5KeNYTPfHENDq9gxqAA8ERkvEigYMe | ||
let tz1 = | ||
PublicKey::from_b58check("edpkurrsBe7UjF59ciHHmBRnS76WHx3YNL9m7owYta6ticPrdP9DG4") | ||
.expect("public key decoding should work"); | ||
let sig: Signature = Signature::from_base58_check( | ||
"sigdGBG68q2vskMuac4AzyNb1xCJTfuU8MiMbQtmZLUCYydYrtTd5Lessn1EFLTDJzjXoYxRasZxXbx6tHnirbEJtikcMHt3" | ||
"edsigtoeXp3xFtGugwCTDSDuifQ9Ka81X4gXFoxRQ6Xao2Ryc3yioptrKMfNy5c9pHhbA9Xn3sYZdx2SPiCGTFXjjXx9xKCPDoq" | ||
).expect("signature decoding should work"); | ||
let msg = hex::decode( | ||
"bcbb7b77cb0712e4cd02160308cfd53e8dde8a7980c4ff28b62deb12304913c2", | ||
) | ||
.expect("payload decoding should work"); | ||
|
||
let msg = b"hello, world"; | ||
|
||
let result = tz1 | ||
.verify_signature(&sig, &msg) | ||
.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 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 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 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 msg = hex::decode("5538e2cc90c9b053a12e2d2f3a985aff1809eac59501db4d644e4bb381b06b4b") | ||
.expect("payload decoding should work"); | ||
|
||
let result = tz2.verify_signature(&sig, &msg).unwrap(); | ||
assert!(result); | ||
|
@@ -262,46 +256,38 @@ mod test { | |
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 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 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 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 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 msg = hex::decode("5538e2cc90c9b053a12e2d2f3a985aff1809eac59501db4d644e4bb381b06b4b") | ||
.expect("payload decoding should work"); | ||
|
||
let result = tz3.verify_signature(&sig, &msg).unwrap(); | ||
assert!(!result); | ||
|
Oops, something went wrong.