Skip to content
This repository was archived by the owner on Nov 20, 2023. It is now read-only.

Commit af3f815

Browse files
authored
Fix RLP decoding and structure, secp256k1 verification (#17)
1 parent 281009f commit af3f815

File tree

6 files changed

+119
-49
lines changed

6 files changed

+119
-49
lines changed

src/builder.rs

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub struct EnrBuilder<K: EnrKey> {
1212
seq: u64,
1313

1414
/// The key-value pairs for the ENR record.
15+
/// Values are stored as RLP encoded bytes.
1516
content: BTreeMap<Key, Vec<u8>>,
1617

1718
/// Pins the generic key types.
@@ -38,19 +39,24 @@ impl<K: EnrKey> EnrBuilder<K> {
3839
}
3940

4041
/// Adds an arbitrary key-value to the `ENRBuilder`.
41-
pub fn add_value(&mut self, key: impl AsRef<[u8]>, value: Vec<u8>) -> &mut Self {
42-
self.content.insert(key.as_ref().to_vec(), value);
42+
pub fn add_value(&mut self, key: impl AsRef<[u8]>, value: &[u8]) -> &mut Self {
43+
self.add_value_rlp(key, rlp::encode(&value))
44+
}
45+
46+
/// Adds an arbitrary key-value where the value is raw RLP encoded bytes.
47+
pub fn add_value_rlp(&mut self, key: impl AsRef<[u8]>, rlp: Vec<u8>) -> &mut Self {
48+
self.content.insert(key.as_ref().to_vec(), rlp);
4349
self
4450
}
4551

4652
/// Adds an `ip` field to the `ENRBuilder`.
4753
pub fn ip(&mut self, ip: IpAddr) -> &mut Self {
4854
match ip {
4955
IpAddr::V4(addr) => {
50-
self.content.insert(b"ip".to_vec(), addr.octets().to_vec());
56+
self.add_value("ip", &addr.octets());
5157
}
5258
IpAddr::V6(addr) => {
53-
self.content.insert(b"ip6".to_vec(), addr.octets().to_vec());
59+
self.add_value("ip6", &addr.octets());
5460
}
5561
}
5662
self
@@ -62,36 +68,32 @@ impl<K: EnrKey> EnrBuilder<K> {
6268
6369
/// Adds an `Id` field to the `ENRBuilder`.
6470
pub fn id(&mut self, id: &str) -> &mut Self {
65-
self.content.insert("id".into(), id.as_bytes().to_vec());
71+
self.add_value("id", &id.as_bytes());
6672
self
6773
}
6874
*/
6975

7076
/// Adds a `tcp` field to the `ENRBuilder`.
7177
pub fn tcp(&mut self, tcp: u16) -> &mut Self {
72-
self.content
73-
.insert("tcp".into(), tcp.to_be_bytes().to_vec());
78+
self.add_value("tcp", &tcp.to_be_bytes());
7479
self
7580
}
7681

7782
/// Adds a `tcp6` field to the `ENRBuilder`.
7883
pub fn tcp6(&mut self, tcp: u16) -> &mut Self {
79-
self.content
80-
.insert("tcp6".into(), tcp.to_be_bytes().to_vec());
84+
self.add_value("tcp6", &tcp.to_be_bytes());
8185
self
8286
}
8387

8488
/// Adds a `udp` field to the `ENRBuilder`.
8589
pub fn udp(&mut self, udp: u16) -> &mut Self {
86-
self.content
87-
.insert("udp".into(), udp.to_be_bytes().to_vec());
90+
self.add_value("udp", &udp.to_be_bytes());
8891
self
8992
}
9093

9194
/// Adds a `udp6` field to the `ENRBuilder`.
9295
pub fn udp6(&mut self, udp: u16) -> &mut Self {
93-
self.content
94-
.insert("udp6".into(), udp.to_be_bytes().to_vec());
96+
self.add_value("udp6", &udp.to_be_bytes());
9597
self
9698
}
9799

@@ -102,7 +104,8 @@ impl<K: EnrKey> EnrBuilder<K> {
102104
stream.append(&self.seq);
103105
for (k, v) in &self.content {
104106
stream.append(k);
105-
stream.append(v);
107+
// The values are stored as raw RLP encoded bytes
108+
stream.append_raw(v, 1);
106109
}
107110
stream.drain()
108111
}
@@ -120,7 +123,7 @@ impl<K: EnrKey> EnrBuilder<K> {
120123

121124
/// Adds a public key to the ENR builder.
122125
fn add_public_key(&mut self, key: &K::PublicKey) {
123-
self.add_value(key.enr_key(), key.encode());
126+
self.add_value(key.enr_key(), &key.encode());
124127
}
125128

126129
/// Constructs an ENR from the `EnrBuilder`.
@@ -133,8 +136,17 @@ impl<K: EnrKey> EnrBuilder<K> {
133136
return Err(EnrError::UnsupportedIdentityScheme);
134137
}
135138

136-
self.content
137-
.insert("id".into(), self.id.as_bytes().to_vec());
139+
// Sanitize all data, ensuring all RLP data is correctly formatted.
140+
for (key, value) in &self.content {
141+
if rlp::Rlp::new(value).data().is_err() {
142+
return Err(EnrError::InvalidRLPData(
143+
String::from_utf8_lossy(key).into(),
144+
));
145+
}
146+
}
147+
148+
let id_bytes = &self.id.as_bytes().to_vec();
149+
self.add_value("id", id_bytes);
138150

139151
self.add_public_key(&key.public());
140152
let rlp_content = self.rlp_content();

src/keys/ed25519.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ impl EnrKey for ed25519::Keypair {
3030
let pubkey_bytes = content
3131
.get(ENR_KEY.as_bytes())
3232
.ok_or_else(|| DecoderError::Custom("Unknown signature"))?;
33+
34+
// Decode the RLP
35+
let pubkey_bytes = rlp::Rlp::new(pubkey_bytes).data()?;
36+
3337
ed25519::PublicKey::from_bytes(pubkey_bytes)
3438
.map_err(|_| DecoderError::Custom("Invalid ed25519 Signature"))
3539
}

src/keys/k256.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ impl EnrKey for SigningKey {
3939
.get(ENR_KEY.as_bytes())
4040
.ok_or_else(|| DecoderError::Custom("Unknown signature"))?;
4141

42+
// Decode the RLP
43+
let pubkey_bytes = rlp::Rlp::new(pubkey_bytes).data()?;
44+
4245
// should be encoded in compressed form, i.e 33 byte raw secp256k1 public key
4346
Ok(VerifyKey::new(pubkey_bytes)
4447
.map_err(|_| DecoderError::Custom("Invalid Secp256k1 Signature"))?)

src/keys/libsecp256k1.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ impl EnrKey for secp256k1::SecretKey {
3535
let pubkey_bytes = content
3636
.get(ENR_KEY.as_bytes())
3737
.ok_or_else(|| DecoderError::Custom("Unknown signature"))?;
38+
39+
// Decode the RLP
40+
let pubkey_bytes = rlp::Rlp::new(pubkey_bytes).data()?;
41+
3842
// should be encoded in compressed form, i.e 33 byte raw secp256k1 public key
3943
secp256k1::PublicKey::parse_slice(
4044
pubkey_bytes,
@@ -48,11 +52,12 @@ impl EnrPublicKey for secp256k1::PublicKey {
4852
/// Verify a raw message, given a public key for the v4 identity scheme.
4953
fn verify_v4(&self, msg: &[u8], sig: &[u8]) -> bool {
5054
let msg = digest(msg);
51-
secp256k1::Signature::parse_slice(sig)
52-
.and_then(|sig| {
53-
secp256k1::Message::parse_slice(&msg).map(|m| secp256k1::verify(&m, &sig, self))
54-
})
55-
.is_ok()
55+
if let Ok(sig) = secp256k1::Signature::parse_slice(sig) {
56+
if let Ok(msg) = secp256k1::Message::parse_slice(&msg) {
57+
return secp256k1::verify(&msg, &sig, self);
58+
}
59+
}
60+
false
5661
}
5762

5863
/// Encodes the public key into compressed form, if possible.

src/keys/rust_secp256k1.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ impl EnrKey for c_secp256k1::SecretKey {
3131
.get(ENR_KEY.as_bytes())
3232
.ok_or_else(|| DecoderError::Custom("Unknown signature"))?;
3333
// should be encoded in compressed form, i.e 33 byte raw secp256k1 public key
34+
// Decode the RLP
35+
let pubkey_bytes = rlp::Rlp::new(pubkey_bytes).data()?;
3436
c_secp256k1::PublicKey::from_slice(pubkey_bytes)
3537
.map_err(|_| DecoderError::Custom("Invalid Secp256k1 Signature"))
3638
}
@@ -39,12 +41,14 @@ impl EnrKey for c_secp256k1::SecretKey {
3941
impl EnrPublicKey for c_secp256k1::PublicKey {
4042
fn verify_v4(&self, msg: &[u8], sig: &[u8]) -> bool {
4143
let msg = digest(msg);
42-
c_secp256k1::Signature::from_compact(sig)
43-
.and_then(|sig| {
44-
c_secp256k1::Message::from_slice(&msg)
45-
.map(|m| c_secp256k1::Secp256k1::new().verify(&m, &sig, self))
46-
})
47-
.is_ok()
44+
if let Ok(sig) = c_secp256k1::Signature::from_compact(sig) {
45+
if let Ok(msg) = c_secp256k1::Message::from_slice(&msg) {
46+
return c_secp256k1::Secp256k1::new()
47+
.verify(&msg, &sig, self)
48+
.is_ok();
49+
}
50+
}
51+
false
4852
}
4953

5054
fn encode(&self) -> Vec<u8> {

0 commit comments

Comments
 (0)