sdk: enforce that `Keypair::from_bytes` bytes match secret-derived `Pubkey` (#32926)

This commit is contained in:
Trent Nelson 2023-08-21 22:40:07 -06:00 committed by GitHub
parent 6521a100f7
commit 9d83bb2a89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 17 deletions

View File

@ -44,7 +44,16 @@ impl Keypair {
/// Recovers a `Keypair` from a byte array
pub fn from_bytes(bytes: &[u8]) -> Result<Self, ed25519_dalek::SignatureError> {
ed25519_dalek::Keypair::from_bytes(bytes).map(Self)
let secret =
ed25519_dalek::SecretKey::from_bytes(&bytes[..ed25519_dalek::SECRET_KEY_LENGTH])?;
let public =
ed25519_dalek::PublicKey::from_bytes(&bytes[ed25519_dalek::SECRET_KEY_LENGTH..])?;
let expected_public = ed25519_dalek::PublicKey::from(&secret);
(public == expected_public)
.then_some(Self(ed25519_dalek::Keypair { secret, public }))
.ok_or(ed25519_dalek::SignatureError::from_source(String::from(
"keypair bytes do not specify same pubkey as derived from their secret key",
)))
}
/// Returns this `Keypair` as a byte array
@ -161,9 +170,8 @@ impl EncodableKeypair for Keypair {
/// Reads a JSON-encoded `Keypair` from a `Reader` implementor
pub fn read_keypair<R: Read>(reader: &mut R) -> Result<Keypair, Box<dyn error::Error>> {
let bytes: Vec<u8> = serde_json::from_reader(reader)?;
let dalek_keypair = ed25519_dalek::Keypair::from_bytes(&bytes)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?;
Ok(Keypair(dalek_keypair))
Keypair::from_bytes(&bytes)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()).into())
}
/// Reads a `Keypair` from a file

View File

@ -1265,9 +1265,9 @@ mod tests {
fn create_sample_transaction() -> Transaction {
let keypair = Keypair::from_bytes(&[
48, 83, 2, 1, 1, 48, 5, 6, 3, 43, 101, 112, 4, 34, 4, 32, 255, 101, 36, 24, 124, 23,
167, 21, 132, 204, 155, 5, 185, 58, 121, 75, 156, 227, 116, 193, 215, 38, 142, 22, 8,
14, 229, 239, 119, 93, 5, 218, 161, 35, 3, 33, 0, 36, 100, 158, 252, 33, 161, 97, 185,
62, 89, 99,
167, 21, 132, 204, 155, 5, 185, 58, 121, 75, 124, 76, 154, 235, 9, 194, 237, 253, 194,
191, 157, 234, 156, 225, 50, 195, 2, 9, 247, 111, 43, 33, 218, 128, 149, 245, 216, 35,
86, 157, 94, 186,
])
.unwrap();
let to = Pubkey::from([
@ -1354,16 +1354,16 @@ mod tests {
assert_eq!(
serialize(&create_sample_transaction()).unwrap(),
vec![
1, 71, 59, 9, 187, 190, 129, 150, 165, 21, 33, 158, 72, 87, 110, 144, 120, 79, 238,
132, 134, 105, 39, 102, 116, 209, 29, 229, 154, 36, 105, 44, 172, 118, 131, 22,
124, 131, 179, 142, 176, 27, 117, 160, 89, 102, 224, 204, 1, 252, 141, 2, 136, 0,
37, 218, 225, 129, 92, 154, 250, 59, 97, 178, 10, 1, 0, 1, 3, 156, 227, 116, 193,
215, 38, 142, 22, 8, 14, 229, 239, 119, 93, 5, 218, 161, 35, 3, 33, 0, 36, 100,
158, 252, 33, 161, 97, 185, 62, 89, 99, 1, 1, 1, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4, 1, 1, 1, 2, 2, 2, 4, 5, 6, 7, 8, 9, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 8, 7, 6, 5, 4, 2, 2, 2, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2,
2, 0, 1, 3, 1, 2, 3
1, 51, 31, 4, 198, 124, 166, 17, 196, 133, 226, 233, 135, 194, 189, 76, 152, 81,
42, 25, 196, 226, 163, 89, 189, 104, 151, 117, 71, 73, 70, 105, 83, 9, 27, 16, 141,
105, 150, 216, 41, 16, 37, 228, 71, 4, 39, 44, 168, 89, 182, 131, 41, 227, 47, 141,
12, 246, 100, 222, 208, 60, 105, 225, 2, 1, 0, 1, 3, 124, 76, 154, 235, 9, 194,
237, 253, 194, 191, 157, 234, 156, 225, 50, 195, 2, 9, 247, 111, 43, 33, 218, 128,
149, 245, 216, 35, 86, 157, 94, 186, 1, 1, 1, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4, 1, 1, 1, 2, 2, 2, 4, 5, 6, 7, 8, 9, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 8, 7, 6, 5, 4, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2,
0, 1, 3, 1, 2, 3
]
);
}