Skip to content

Commit

Permalink
Merge pull request #426 from flavio/ecdsa-flexible-parsing
Browse files Browse the repository at this point in the history
Make ECDSA key parsing more flexible
  • Loading branch information
webern authored Jan 26, 2022
2 parents 9a0897c + eb1bdb8 commit d9f0cb8
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 3 deletions.
11 changes: 11 additions & 0 deletions tough/src/schema/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,15 @@ mod tests {
))
.is_err());
}

/// Ensure that we can deserialize a root.json file that has hex-encoded ECDSA keys. This uses
/// sigstore's root.json file taken from here:
/// https://sigstore-tuf-root.storage.googleapis.com/2.root.json
#[test]
fn ecdsa_hex_encoded_keys() {
assert!(serde_json::from_str::<Signed<Root>>(include_str!(
"../../tests/data/hex-encoded-ecdsa-sig-keys/root.json"
))
.is_ok());
}
}
26 changes: 26 additions & 0 deletions tough/src/schema/decoded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,32 @@ impl Encode for EcdsaPem {
}
}

/// [`Decode`]/[`Encode`] implementation for ECDSA public keys.
/// This is a flexible implementation, it will try to decode the key assuming
/// it is PEM encoded, if the decode fails it will then try to decode it
/// assuming it's Hex encoded.
/// The official TUF specification suggests ECDSA keys to be PEM encoded,
/// however the go-tuf implementation encodes them as Hex numbers.
/// This flexible decoder tries to cover both cases in a transparent way.
#[derive(Debug, Clone, Copy)]
pub struct EcdsaFlex {}

impl Decode for EcdsaFlex {
fn decode(s: &str) -> Result<Vec<u8>, Error> {
if s.starts_with("-----BEGIN ") {
EcdsaPem::decode(s)
} else {
Hex::decode(s)
}
}
}

impl Encode for EcdsaFlex {
fn encode(b: &[u8]) -> String {
EcdsaPem::encode(b)
}
}

// =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^=

impl<'de, T: Decode> Deserialize<'de> for Decoded<T> {
Expand Down
6 changes: 3 additions & 3 deletions tough/src/schema/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

//! Handles cryptographic keys and their serialization in TUF metadata files.

use crate::schema::decoded::{Decoded, EcdsaPem, Hex, RsaPem};
use crate::schema::decoded::{Decoded, EcdsaFlex, Hex, RsaPem};
use crate::schema::error::{self, Result};
use olpc_cjson::CanonicalFormatter;
use ring::digest::{digest, SHA256};
Expand Down Expand Up @@ -121,7 +121,7 @@ pub enum EcdsaScheme {
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
pub struct EcdsaKey {
/// The public key.
pub public: Decoded<EcdsaPem>,
pub public: Decoded<EcdsaFlex>,

/// Any additional fields read during deserialization; will not be used.
#[serde(flatten)]
Expand Down Expand Up @@ -204,7 +204,7 @@ impl FromStr for Key {
} else {
Err(KeyParseError(()))
}
} else if let Ok(public) = serde_plain::from_str::<Decoded<EcdsaPem>>(s) {
} else if let Ok(public) = serde_plain::from_str::<Decoded<EcdsaFlex>>(s) {
Ok(Key::Ecdsa {
keyval: EcdsaKey {
public,
Expand Down
144 changes: 144 additions & 0 deletions tough/tests/data/hex-encoded-ecdsa-sig-keys/root.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
{
"signatures": [
{
"keyid": "2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97",
"sig": "3046022100d3ea59490b253beae0926c6fa63f54336dea1ed700555be9f27ff55cd347639c0221009157d1ba012cead81948a4ab777d355451d57f5c4a2d333fc68d2e3f358093c2"
},
{
"keyid": "bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62",
"sig": "304502206eaef40564403ce572c6d062e0c9b0aab5e0223576133e081e1b495e8deb9efd02210080fd6f3464d759601b4afec596bbd5952f3a224cd06ed1cdfc3c399118752ba2"
},
{
"keyid": "eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b",
"sig": "304502207baace02f56d8e6069f10b6ff098a26e7f53a7f9324ad62cffa0557bdeb9036c022100fb3032baaa090d0040c3f2fd872571c84479309b773208601d65948df87a9720"
},
{
"keyid": "f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb",
"sig": "304402205180c01905505dd88acd7a2dad979dd75c979b3722513a7bdedac88c6ae8dbeb022056d1ddf7a192f0b1c2c90ff487de2fb3ec9f0c03f66ea937c78d3b6a493504ca"
},
{
"keyid": "f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209",
"sig": "3046022100c8806d4647c514d80fd8f707d3369444c4fd1d0812a2d25f828e564c99790e3f022100bb51f12e862ef17a7d3da2ac103bebc5c7e792237006c4cafacd76267b249c2f"
}
],
"signed": {
"_type": "root",
"consistent_snapshot": false,
"expires": "2022-05-11T19:09:02.663975009Z",
"keys": {
"2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97": {
"keyid_hash_algorithms": [
"sha256",
"sha512"
],
"keytype": "ecdsa-sha2-nistp256",
"keyval": {
"public": "04cbc5cab2684160323c25cd06c3307178a6b1d1c9b949328453ae473c5ba7527e35b13f298b41633382241f3fd8526c262d43b45adee5c618fa0642c82b8a9803"
},
"scheme": "ecdsa-sha2-nistp256"
},
"b6710623a30c010738e64c5209d367df1c0a18cf90e6ab5292fb01680f83453d": {
"keyid_hash_algorithms": [
"sha256",
"sha512"
],
"keytype": "ecdsa-sha2-nistp256",
"keyval": {
"public": "04fa1a3e42f2300cd3c5487a61509348feb1e936920fef2f83b7cd5dbe7ba045f538725ab8f18a666e6233edb7e0db8766c8dc336633449c5e1bbe0c182b02df0b"
},
"scheme": "ecdsa-sha2-nistp256"
},
"bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62": {
"keyid_hash_algorithms": [
"sha256",
"sha512"
],
"keytype": "ecdsa-sha2-nistp256",
"keyval": {
"public": "04a71aacd835dc170ba6db3fa33a1a33dee751d4f8b0217b805b9bd3242921ee93672fdcfd840576c5bb0dc0ed815edf394c1ee48c2b5e02485e59bfc512f3adc7"
},
"scheme": "ecdsa-sha2-nistp256"
},
"eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b": {
"keyid_hash_algorithms": [
"sha256",
"sha512"
],
"keytype": "ecdsa-sha2-nistp256",
"keyval": {
"public": "04117b33dd265715bf23315e368faa499728db8d1f0a377070a1c7b1aba2cc21be6ab1628e42f2cdd7a35479f2dce07b303a8ba646c55569a8d2a504ba7e86e447"
},
"scheme": "ecdsa-sha2-nistp256"
},
"f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb": {
"keyid_hash_algorithms": [
"sha256",
"sha512"
],
"keytype": "ecdsa-sha2-nistp256",
"keyval": {
"public": "04cc1cd53a61c23e88cc54b488dfae168a257c34fac3e88811c55962b24cffbfecb724447999c54670e365883716302e49da57c79a33cd3e16f81fbc66f0bcdf48"
},
"scheme": "ecdsa-sha2-nistp256"
},
"f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209": {
"keyid_hash_algorithms": [
"sha256",
"sha512"
],
"keytype": "ecdsa-sha2-nistp256",
"keyval": {
"public": "048a78a44ac01099890d787e5e62afc29c8ccb69a70ec6549a6b04033b0a8acbfb42ab1ab9c713d225cdb52b858886cf46c8e90a7f3b9e6371882f370c259e1c5b"
},
"scheme": "ecdsa-sha2-nistp256"
},
"fc61191ba8a516fe386c7d6c97d918e1d241e1589729add09b122725b8c32451": {
"keyid_hash_algorithms": [
"sha256",
"sha512"
],
"keytype": "ecdsa-sha2-nistp256",
"keyval": {
"public": "044c7793ab74b9ddd713054e587b8d9c75c5f6025633d0fef7ca855ed5b8d5a474b23598fe33eb4a63630d526f74d4bdaec8adcb51993ed65652d651d7c49203eb"
},
"scheme": "ecdsa-sha2-nistp256"
}
},
"roles": {
"root": {
"keyids": [
"2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97",
"bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62",
"eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b",
"f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb",
"f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209"
],
"threshold": 3
},
"snapshot": {
"keyids": [
"fc61191ba8a516fe386c7d6c97d918e1d241e1589729add09b122725b8c32451"
],
"threshold": 1
},
"targets": {
"keyids": [
"2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97",
"bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62",
"eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b",
"f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb",
"f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209"
],
"threshold": 3
},
"timestamp": {
"keyids": [
"b6710623a30c010738e64c5209d367df1c0a18cf90e6ab5292fb01680f83453d"
],
"threshold": 1
}
},
"spec_version": "1.0",
"version": 2
}
}

0 comments on commit d9f0cb8

Please sign in to comment.