tezos_smart_rollup_encoding/
public_key.rs1use std::fmt::Display;
8use tezos_crypto_rs::hash::{
9 PublicKeyEd25519, PublicKeyP256, PublicKeySecp256k1, Signature,
10};
11use tezos_crypto_rs::{CryptoError, PublicKeySignatureVerifier};
12use tezos_data_encoding::enc::BinWriter;
13use tezos_data_encoding::encoding::HasEncoding;
14use tezos_data_encoding::nom::NomReader;
15
16use crypto::base58::{FromBase58Check, FromBase58CheckError};
17use crypto::hash::{Hash, HashTrait, HashType};
18
19#[derive(Debug, Clone, PartialEq, Eq, HasEncoding, BinWriter, NomReader)]
21pub enum PublicKey {
22 Ed25519(PublicKeyEd25519),
24 Secp256k1(PublicKeySecp256k1),
26 P256(PublicKeyP256),
28}
29
30impl Display for PublicKey {
31 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32 match self {
33 Self::Ed25519(tz1) => write!(f, "{}", tz1),
34 Self::Secp256k1(tz2) => write!(f, "{}", tz2),
35 Self::P256(tz3) => write!(f, "{}", tz3),
36 }
37 }
38}
39
40impl PublicKey {
41 pub fn from_b58check(data: &str) -> Result<Self, FromBase58CheckError> {
43 let bytes = data.from_base58check()?;
44 let public_key = if bytes
45 .starts_with(HashType::PublicKeyEd25519.base58check_prefix())
46 {
47 PublicKey::Ed25519(PublicKeyEd25519::from_b58check(data)?)
48 } else if bytes.starts_with(HashType::PublicKeySecp256k1.base58check_prefix()) {
49 PublicKey::Secp256k1(PublicKeySecp256k1::from_b58check(data)?)
50 } else if bytes.starts_with(HashType::PublicKeyP256.base58check_prefix()) {
51 PublicKey::P256(PublicKeyP256::from_b58check(data)?)
52 } else {
53 return Err(FromBase58CheckError::InvalidBase58);
54 };
55 Ok(public_key)
56 }
57
58 pub fn to_b58check(&self) -> String {
60 match self {
61 Self::Ed25519(tz1) => tz1.to_b58check(),
62 Self::Secp256k1(tz2) => tz2.to_b58check(),
63 Self::P256(tz3) => tz3.to_b58check(),
64 }
65 }
66}
67
68impl From<PublicKey> for Hash {
69 fn from(pkh: PublicKey) -> Self {
70 match pkh {
71 PublicKey::Ed25519(tz1) => tz1.into(),
72 PublicKey::Secp256k1(tz2) => tz2.into(),
73 PublicKey::P256(tz3) => tz3.into(),
74 }
75 }
76}
77
78impl TryFrom<&str> for PublicKey {
79 type Error = FromBase58CheckError;
80
81 fn try_from(value: &str) -> Result<Self, Self::Error> {
82 Self::from_b58check(value)
83 }
84}
85
86impl PublicKeySignatureVerifier for PublicKey {
87 type Signature = Signature;
88 type Error = CryptoError;
89
90 fn verify_signature(
91 &self,
92 signature: &Self::Signature,
93 msg: &[u8],
94 ) -> Result<bool, Self::Error> {
95 match self {
96 PublicKey::Ed25519(ed25519) => ed25519.verify_signature(signature, msg),
97 PublicKey::Secp256k1(secp256k1) => secp256k1.verify_signature(signature, msg),
98 PublicKey::P256(p256) => p256.verify_signature(signature, msg),
99 }
100 }
101}
102
103#[cfg(test)]
104mod test {
105 use super::*;
106
107 #[test]
108 fn tz1_b58check() {
109 let tz1 = "edpkuDMUm7Y53wp4gxeLBXuiAhXZrLn8XB1R83ksvvesH8Lp8bmCfK";
110
111 let pkh = PublicKey::from_b58check(tz1);
112
113 assert!(matches!(pkh, Ok(PublicKey::Ed25519(_))));
114
115 let tz1_from_pkh = pkh.unwrap().to_b58check();
116
117 assert_eq!(tz1, &tz1_from_pkh);
118 }
119
120 #[test]
121 fn tz2_b58check() {
122 let tz2 = "sppk7Zik17H7AxECMggqD1FyXUQdrGRFtz9X7aR8W2BhaJoWwSnPEGA";
123
124 let public_key = PublicKey::from_b58check(tz2);
125
126 assert!(matches!(public_key, Ok(PublicKey::Secp256k1(_))));
127
128 let tz2_from_pk = public_key.unwrap().to_b58check();
129
130 assert_eq!(tz2, &tz2_from_pk);
131 }
132
133 #[test]
134 fn tz3_b58check() {
135 let tz3 = "p2pk67VpBjWwoPULwXCpayec6rFxaAKv8VjJ8cVMHmLDCYARu31zx5Z";
136
137 let public_key = PublicKey::from_b58check(tz3);
138
139 assert!(matches!(public_key, Ok(PublicKey::P256(_))));
140
141 let tz3_from_pk = public_key.unwrap().to_b58check();
142
143 assert_eq!(tz3, &tz3_from_pk);
144 }
145
146 #[test]
147 fn tz1_encoding() {
148 let tz1 = "edpkuDMUm7Y53wp4gxeLBXuiAhXZrLn8XB1R83ksvvesH8Lp8bmCfK";
149
150 let public_key = PublicKey::from_b58check(tz1).expect("expected valid tz1 hash");
151
152 let mut bin = Vec::new();
153 public_key
154 .bin_write(&mut bin)
155 .expect("serialization should work");
156
157 let deserde_pk = NomReader::nom_read(bin.as_slice())
158 .expect("deserialization should work")
159 .1;
160
161 assert_eq!(0_u8, bin[0]);
163 assert_eq!(public_key, deserde_pk);
164 }
165
166 #[test]
167 fn tz2_encoding() {
168 let tz2 = "sppk7Zik17H7AxECMggqD1FyXUQdrGRFtz9X7aR8W2BhaJoWwSnPEGA";
169
170 let public_key = PublicKey::from_b58check(tz2).expect("expected valid tz2 hash");
171
172 let mut bin = Vec::new();
173 public_key
174 .bin_write(&mut bin)
175 .expect("serialization should work");
176
177 let deserde_pk = NomReader::nom_read(bin.as_slice())
178 .expect("deserialization should work")
179 .1;
180
181 assert_eq!(1_u8, bin[0]);
183 assert_eq!(public_key, deserde_pk);
184 }
185
186 #[test]
187 fn tz3_encoding() {
188 let tz3 = "p2pk67VpBjWwoPULwXCpayec6rFxaAKv8VjJ8cVMHmLDCYARu31zx5Z";
189
190 let public_key = PublicKey::from_b58check(tz3).expect("expected valid tz3 hash");
191
192 let mut bin = Vec::new();
193 public_key
194 .bin_write(&mut bin)
195 .expect("serialization should work");
196
197 let deserde_pk = NomReader::nom_read(bin.as_slice())
198 .expect("deserialization should work")
199 .1;
200
201 assert_eq!(2_u8, bin[0]);
203 assert_eq!(public_key, deserde_pk);
204 }
205
206 #[test]
207 fn tz1_signature_signature_verification_succeeds() {
208 let tz1 = PublicKey::from_b58check(
209 "edpkvWR5truf7AMF3PZVCXx7ieQLCW4MpNDzM3VwPfmFWVbBZwswBw",
210 )
211 .expect("public key decoding should work");
212 let sig: Signature = Signature::from_base58_check(
213 "sigdGBG68q2vskMuac4AzyNb1xCJTfuU8MiMbQtmZLUCYydYrtTd5Lessn1EFLTDJzjXoYxRasZxXbx6tHnirbEJtikcMHt3"
214 ).expect("signature decoding should work");
215 let msg = hex::decode(
216 "bcbb7b77cb0712e4cd02160308cfd53e8dde8a7980c4ff28b62deb12304913c2",
217 )
218 .expect("payload decoding should work");
219
220 let result = tz1
221 .verify_signature(&sig, &msg)
222 .expect("signature should be correct");
223 assert!(result);
224 }
225
226 #[test]
227 fn tz1_signature_signature_verification_fails() {
228 let tz1 = PublicKey::from_b58check(
229 "edpkuDMUm7Y53wp4gxeLBXuiAhXZrLn8XB1R83ksvvesH8Lp8bmCfK",
230 )
231 .expect("public key decoding should work");
232 let sig = Signature::from_base58_check(
233 "sigdGBG68q2vskMuac4AzyNb1xCJTfuU8MiMbQtmZLUCYydYrtTd5Lessn1EFLTDJzjXoYxRasZxXbx6tHnirbEJtikcMHt3"
234 ).expect("signature decoding should work");
235 let msg = hex::decode(
236 "bcbb7b77cb0712e4cd02160308cfd53e8dde8a7980c4ff28b62deb12304913c2",
237 )
238 .expect("payload decoding should work");
239
240 let result = tz1.verify_signature(&sig, &msg);
241 assert!(result.is_err());
242 }
243
244 #[test]
245 fn tz2_signature_signature_verification_succeeds() {
246 let tz2 = PublicKey::from_b58check(
247 "sppk7cwkTzCPptCSxSTvGNg4uqVcuTbyWooLnJp4yxJNH5DReUGxYvs",
248 )
249 .expect("public key decoding should work");
250 let sig = Signature::from_base58_check("sigrJ2jqanLupARzKGvzWgL1Lv6NGUqDovHKQg9MX4PtNtHXgcvG6131MRVzujJEXfvgbuRtfdGbXTFaYJJjuUVLNNZTf5q1").expect("signature decoding should work");
251 let msg = hex::decode(
252 "5538e2cc90c9b053a12e2d2f3a985aff1809eac59501db4d644e4bb381b06b4b",
253 )
254 .expect("payload decoding should work");
255
256 let result = tz2.verify_signature(&sig, &msg).unwrap();
257 assert!(result);
258 }
259
260 #[test]
261 fn tz2_signature_signature_verification_fails() {
262 let tz2 = "sppk7Zik17H7AxECMggqD1FyXUQdrGRFtz9X7aR8W2BhaJoWwSnPEGA";
263 let tz2 = PublicKey::from_b58check(tz2).expect("parsing should world");
264 let sig = Signature::from_base58_check("sigrJ2jqanLupARzKGvzWgL1Lv6NGUqDovHKQg9MX4PtNtHXgcvG6131MRVzujJEXfvgbuRtfdGbXTFaYJJjuUVLNNZTf5q1").expect("signature decoding should work");
265 let msg = hex::decode(
266 "5538e2cc90c9b053a12e2d2f3a985aff1809eac59501db4d644e4bb381b06b4b",
267 )
268 .expect("payload decoding should work");
269
270 let result = tz2.verify_signature(&sig, &msg).unwrap();
271 assert!(!result);
272 }
273
274 #[test]
275 fn tz3_signature_signature_verification_succeeds() {
276 let tz3 = PublicKey::from_b58check(
277 "p2pk67Cwb5Ke6oSmqeUbJxURXMe3coVnH9tqPiB2xD84CYhHbBKs4oM",
278 )
279 .expect("decoding public key should work");
280 let sig = Signature::from_base58_check(
281 "sigNCaj9CnmD94eZH9C7aPPqBbVCJF72fYmCFAXqEbWfqE633WNFWYQJFnDUFgRUQXR8fQ5tKSfJeTe6UAi75eTzzQf7AEc1"
282 ).expect("signature decoding should work");
283 let msg = hex::decode(
284 "5538e2cc90c9b053a12e2d2f3a985aff1809eac59501db4d644e4bb381b06b4b",
285 )
286 .expect("payload decoding should work");
287
288 let result = tz3.verify_signature(&sig, &msg).unwrap();
289 assert!(result);
290 }
291
292 #[test]
293 fn tz3_signature_signature_verification_fails() {
294 let tz3 = PublicKey::from_b58check(
295 "p2pk67VpBjWwoPULwXCpayec6rFxaAKv8VjJ8cVMHmLDCYARu31zx5Z",
296 )
297 .expect("decoding public key should work");
298 let sig = Signature::from_base58_check(
299 "sigNCaj9CnmD94eZH9C7aPPqBbVCJF72fYmCFAXqEbWfqE633WNFWYQJFnDUFgRUQXR8fQ5tKSfJeTe6UAi75eTzzQf7AEc1"
300 ).expect("signature decoding should work");
301 let msg = hex::decode(
302 "5538e2cc90c9b053a12e2d2f3a985aff1809eac59501db4d644e4bb381b06b4b",
303 )
304 .expect("payload decoding should work");
305
306 let result = tz3.verify_signature(&sig, &msg).unwrap();
307 assert!(!result);
308 }
309}