diff --git a/CHANGELOG.md b/CHANGELOG.md index 45f8695a1e..7c3a57c329 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added -- Nothing. +- Add `FromBase58CheckError::IncorrectBase58Prefix` variant. ### Changed @@ -24,7 +24,8 @@ parameterized by the lifetime of the input byte slice. ### Fixed -- Nothing. +- Fix prefix used in `SeedEd25519` encoding. +- Add explicit prefix check during base58check decoding. ### Security diff --git a/crypto/src/base58.rs b/crypto/src/base58.rs index 4cdcb762d5..84d6d76ca9 100644 --- a/crypto/src/base58.rs +++ b/crypto/src/base58.rs @@ -23,6 +23,9 @@ pub enum FromBase58CheckError { DataTooLong, #[error("mismatched data lenght: expected {expected}, actual {actual}")] MismatchedLength { expected: usize, actual: usize }, + /// Prefix does not match expected. + #[error("incorrect base58 prefix for hash type")] + IncorrectBase58Prefix, } /// Possible errors for ToBase58Check diff --git a/crypto/src/hash.rs b/crypto/src/hash.rs index 802174f379..d738b562f3 100644 --- a/crypto/src/hash.rs +++ b/crypto/src/hash.rs @@ -36,7 +36,7 @@ mod prefix_bytes { pub const PUBLIC_KEY_SECP256K1: [u8; 4] = [3, 254, 226, 86]; pub const PUBLIC_KEY_P256: [u8; 4] = [3, 178, 139, 127]; pub const PUBLIC_KEY_BLS: [u8; 4] = [6, 149, 135, 204]; - pub const SEED_ED25519: [u8; 4] = [43, 246, 78, 7]; + pub const SEED_ED25519: [u8; 4] = [13, 15, 58, 7]; pub const SECRET_KEY_ED25519: [u8; 4] = [43, 246, 78, 7]; pub const SECRET_KEY_BLS: [u8; 4] = [3, 150, 192, 40]; pub const ED22519_SIGNATURE_HASH: [u8; 5] = [9, 245, 205, 134, 18]; @@ -482,7 +482,11 @@ impl HashType { return Ok(hash.to_vec()); } } + } else if !hash.starts_with(self.base58check_prefix()) { + println!("expected: {:?}, found: {hash:?}", self.base58check_prefix()); + return Err(FromBase58CheckError::IncorrectBase58Prefix); } + let expected_len = self.size() + self.base58check_prefix().len(); if expected_len != hash.len() { return Err(FromBase58CheckError::MismatchedLength { @@ -490,6 +494,7 @@ impl HashType { actual: hash.len(), }); } + // prefix is not present in a binary representation hash.drain(0..self.base58check_prefix().len()); Ok(hash) @@ -1056,9 +1061,10 @@ mod tests { } #[test] - fn test_b58_to_hash_mismatched_lenght() -> Result<(), anyhow::Error> { - let b58 = HashType::ChainId.hash_to_b58check(&[0, 0, 0, 0])?; - let result = HashType::BlockHash.b58check_to_hash(&b58); + fn test_b58_to_hash_mismatched_length() -> Result<(), anyhow::Error> { + let b58 = "BwKZdq9yAc1ucmPPoUeRxRQRUeks64eswrLoSa2eZipYwB3UftmTd1pmg4uyiwU6Ge3guh7CoZdpL4YPm35Ajvu5gQu5mYwEgwA8UmjZNaXV7ecc7qkcoe6xro"; + let result = HashType::BlockHash.b58check_to_hash(b58); + println!("{result:?}"); assert!(matches!( result, Err(FromBase58CheckError::MismatchedLength { @@ -1268,6 +1274,23 @@ mod tests { ); } + #[test] + fn from_base58check_incorrect_prefix() { + let h = ContractTz1Hash::from_base58_check("tz4FENGt5zkiGaHPm1ya4MgLomgkL1k7Dy7q"); + + assert!(matches!( + h, + Err(FromBase58CheckError::IncorrectBase58Prefix) + )); + + let h = ContractTz4Hash::from_base58_check("tz1ei4WtWEMEJekSv8qDnu9PExG6Q8HgRGr3"); + + assert!(matches!( + h, + Err(FromBase58CheckError::IncorrectBase58Prefix) + )); + } + #[test] fn block_payload_hash() { let operation_0 = "oom9d3PpjjaMzgg9mZ1pDrF8kjdyzDb41Bd2XE6Y3kRtFHXLku3";