diff options
author | Teddy Wing | 2018-11-07 08:08:00 +0100 |
---|---|---|
committer | Teddy Wing | 2018-11-07 08:55:52 +0100 |
commit | 70dcef3a47c11f921d8d742b2e1667e178a90b8f (patch) | |
tree | 974663d04cf802910a40016d7193f65903896861 | |
parent | 4aa1c293b4deb97e588268bbd00949d12a26135e (diff) | |
download | dome-key-web-70dcef3a47c11f921d8d742b2e1667e178a90b8f.tar.bz2 |
AquaticPrime: Add `plist` method
Working version of a function that generates a license plist XML string
from input data.
Made a complete and utter mess of the code, and the two tests in this
commit aren't really tests, they're just a way of executing the
function.
The function takes a serializable data type, sends the data to the
`sign` function, and produces an XML plist string of the input data plus
a field for the signature.
In order to accomplish this, I ended up with a kind of roundabout data
manipulation.
1. We start with the user data type.
2. That then gets serialised to an XML plist using the 'plist' crate's
'serde' serializer.
3. The serialized XML is then deserialized to a `Plist` instance.
4. The dict is extracted from the `Plist` and fed to `sign()` get a
signature from the data.
5. We add the signature to the dict as a `Plist::Data`, in accordance
with the Aquatic Prime license file format.
6. The full dict including the signature entry is serialized to XML and
returned from the function.
I ended up with this circuitous manipulation because I wanted to be able
to accept an arbitrary struct as input data, and serializing it seemed
to be the easiest way to get a plist dict from it. But we can't just use
that serialized result, because it doesn't contain the signature.
Getting a `Plist` from the data seemed to be the right way to go, as the
signature entry needs to be a plist `data` type, so we can't just insert
it into a `<String, String>` `HashMap`.
Now that it works, I'll be cleaning all of this up in further commits.
-rw-r--r-- | license-generator/Cargo.lock | 108 | ||||
-rw-r--r-- | license-generator/aquatic-prime/Cargo.toml | 3 | ||||
-rw-r--r-- | license-generator/aquatic-prime/src/lib.rs | 148 |
3 files changed, 258 insertions, 1 deletions
diff --git a/license-generator/Cargo.lock b/license-generator/Cargo.lock index 9a099e2..4dcc754 100644 --- a/license-generator/Cargo.lock +++ b/license-generator/Cargo.lock @@ -5,6 +5,9 @@ dependencies = [ "base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)", + "plist 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -30,6 +33,15 @@ dependencies = [ [[package]] name = "base64" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "base64" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ @@ -86,6 +98,14 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "humantime" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "lazy_static" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -132,11 +152,79 @@ version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "plist" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quick-error" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quote" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "rustc-demangle" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "safemem" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_derive" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.15.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "vcpkg" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -160,10 +248,19 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "xml-rs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [metadata] "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" "checksum base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "621fc7ecb8008f86d7fb9b95356cd692ce9514b80a86d85b397f32a22da7b9e2" +"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" "checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" @@ -172,13 +269,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fastcgi 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4159a0f48bea0281602e508eb070d7d7ba1f6ac2480f9db1a60a39274aea1cc" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +"checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" "checksum openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "5e1309181cdcbdb51bc3b6bedb33dfac2a83b3d585033d3f6d9e22e8c1928613" "checksum openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)" = "278c1ad40a89aa1e741a1eed089a2f60b18fab8089c3139b542140fc7d674106" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" +"checksum plist 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c7316832d9ac5da02786bdc89a3faf0ca07070212b388766e969078fd593edc" +"checksum proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "3d7b7eaaa90b4a90a932a9ea6666c95a389e424eff347f0f793979289429feee" +"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" +"checksum quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "63b5829244f52738cfee93b3a165c1911388675be000c888d2fae620dee8fa5b" "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" +"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" +"checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef" +"checksum serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "225de307c6302bec3898c51ca302fc94a7a1697ef0845fcee6448f33c032249c" +"checksum syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)" = "90c39a061e2f412a9f869540471ab679e85e50c6b05604daf28bc3060f75c430" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c1cb601d29fe2c2ac60a2b2e5e293994d87a1f6fa9687a31a15270f909be9c2" diff --git a/license-generator/aquatic-prime/Cargo.toml b/license-generator/aquatic-prime/Cargo.toml index 3106d76..2247930 100644 --- a/license-generator/aquatic-prime/Cargo.toml +++ b/license-generator/aquatic-prime/Cargo.toml @@ -6,3 +6,6 @@ version = "0.0.1" base64 = "0.10.0" error-chain = "0.12.0" openssl = "0.10.15" +plist = "0.3.0" +serde = "1.0.80" +serde_derive = "1.0.80" diff --git a/license-generator/aquatic-prime/src/lib.rs b/license-generator/aquatic-prime/src/lib.rs index c7f43a4..7aea16f 100644 --- a/license-generator/aquatic-prime/src/lib.rs +++ b/license-generator/aquatic-prime/src/lib.rs @@ -3,6 +3,11 @@ extern crate base64; #[macro_use] extern crate error_chain; extern crate openssl; +extern crate plist; +extern crate serde; + +#[macro_use] +extern crate serde_derive; mod errors { error_chain! { @@ -15,12 +20,15 @@ mod errors { } } -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; +use std::io::Cursor; use openssl::bn::BigNum; use openssl::rsa::Padding; use openssl::rsa::RsaPrivateKeyBuilder; use openssl::sha::sha1; +use plist::Plist; +use serde::ser::Serialize; use errors::*; @@ -78,6 +86,81 @@ impl<'a> AquaticPrime<'a> { Ok(base64::encode(&signature[..])) } + + // TODO: Should take a plistable object as input + // Serialize input_data to a Plist (input_data doesn't include signature field?) + // Get the BTreeMap out and send it to sign() + // Insert signature into Plist BTreeMap + // Output plist string + // + // fn plist(&self, input_data: HashMap<&str, &str>) -> Result<String> { + fn plist<T: Serialize>(&self, input_data: T) -> Result<String> { + // let signature = self.sign(input_data.clone()); + // let mut data: BTreeMap<&str, &str> = input_data + // .into_iter() + // .collect(); + // + // data.insert(); + // let mut tmp = String::with_capacity(600); + let mut tmp = Vec::with_capacity(600); + + plist::serde::serialize_to_xml(&mut tmp, &input_data).unwrap(); + // let xml = String::from_utf8(tmp).unwrap(); + + // println!("Serialized: {}", xml); + + // let le_plist: Plist = plist::serde::deserialize(Cursor::new(&tmp[..])).unwrap(); + let tmp2 = tmp.clone(); + let plist_data = Plist::read(Cursor::new(&tmp)).unwrap(); + println!("{:?}", plist_data); + + let mut plist_dict = plist_data.as_dictionary().unwrap().to_owned(); + + // let hash_data: BTreeMap<String, String> = data + // .into_iter() + // .map(|(k, v)| (k, String::from(v))) + // .collect(); + + // let hash_data: BTreeMap<&str, &str> = data.into_iter().collect(); + // self.sign(data); + // data.insert(); + + // let data_a = BTreeMap::new(); + // for (k, v) in data.iter() { + // data_a.insert(k, String::from(v)); + // } + + let data: HashMap<String, String> = plist::serde::deserialize(Cursor::new(&tmp2)).unwrap(); + println!("{:?}", data); + let mut data_a = HashMap::new(); + for (k, v) in data.iter() { + data_a.insert(k.as_ref(), v.as_ref()); + } + + let signature = self.sign(data_a).unwrap(); + println!("Signature: {}", signature); + + // Re-serialise to Plist + // Add signature as Data type + + plist_dict.insert("Signature".to_owned(), Plist::Data(signature.into_bytes())); + + let mut tmp_return = Cursor::new(Vec::with_capacity(600)); + // plist::serde::serialize_to_xml(&mut tmp_return, &plist_data).unwrap(); + // println!("Output: {}", tmp_return); + + { + let mut writer = plist::xml::EventWriter::new(&mut tmp_return); + // let plist_plist = Plist::Dictionary(plist_data); + for item in Plist::Dictionary(plist_dict).into_events() { + writer.write(&item).unwrap(); + } + } + + println!("Output: {}", String::from_utf8(tmp_return.into_inner()).unwrap()); + + Ok(String::new()) + } } @@ -121,4 +204,67 @@ mod tests { assert_eq!(signature.unwrap(), expected); } + + #[test] + fn plist_produces_a_license_plist_string() { + let public_key = "0xAAD0DC5705017D4AA1CD3FA194771E97B263E68308DC09D3D9297247D175CCD05DFE410B9426D3C8019BA6B92D34F21B454D8D8AC8CAD2FB37850987C02592012D658911442C27F4D9B050CFA3F7C07FF81CFEEBE33E1E43595B2ACCC2019DC7247829017A91D40020F9D8BF67300CE744263B4F34FF42E3A7BE3CF37C4004EB"; + let private_key = "0x71E092E4AE00FE31C1337FC10DA4BF0FCC4299ACB092B137E61BA185364E888AE9542B5D0D6F37DAABBD19D0C8CDF6BCD8DE5E5C85DC8CA77A58B1052AC3B6AA5C7EA2E58BD484050184D2E241CFCB1D6AB4AC8617499056060833D8F6699B9C54E3BAA36123AFD5B4DDE6F2ADFC08F6970C3BA5C80B9A0A04CB6C6B73DD512B"; + + let aquatic_prime = AquaticPrime { + public_key: public_key, + private_key: private_key, + }; + + let mut license_data = HashMap::new(); + license_data.insert("Email", "user@email.com"); + license_data.insert("Name", "Üsér Diacriticà"); + license_data.insert("lowercase key", "Keys should be sorted case-insensitive"); + + aquatic_prime.plist(license_data); + +r#"<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>Email</key> + <string>user@email.com</string> + <key>Name</key> + <string>Üsér Diacriticà</string> + <key>Signature</key> + <data> + RIhF/3CgyXzPg2wCQ5LShf6W9khtqPcqUDLAHcAZdOIcoeR7PoOHi15423kxq5jOh1lm + cztBoUJFu8mB45MHE0jmmbRw3qK6FJz9Py2gi1XvGOgH3GW713OCvQBE7vfBj4ZriP0+ + FS18nLfrtM6Xp0mAd1la4DD4oh7d35dlYTY= + </data> + <key>lowercase key</key> + <string>Keys should be sorted case-insensitive</string> +</dict> +</plist>"#; + } + + #[test] + fn plist_takes_a_generic_struct() { + let public_key = "0xAAD0DC5705017D4AA1CD3FA194771E97B263E68308DC09D3D9297247D175CCD05DFE410B9426D3C8019BA6B92D34F21B454D8D8AC8CAD2FB37850987C02592012D658911442C27F4D9B050CFA3F7C07FF81CFEEBE33E1E43595B2ACCC2019DC7247829017A91D40020F9D8BF67300CE744263B4F34FF42E3A7BE3CF37C4004EB"; + let private_key = "0x71E092E4AE00FE31C1337FC10DA4BF0FCC4299ACB092B137E61BA185364E888AE9542B5D0D6F37DAABBD19D0C8CDF6BCD8DE5E5C85DC8CA77A58B1052AC3B6AA5C7EA2E58BD484050184D2E241CFCB1D6AB4AC8617499056060833D8F6699B9C54E3BAA36123AFD5B4DDE6F2ADFC08F6970C3BA5C80B9A0A04CB6C6B73DD512B"; + + let aquatic_prime = AquaticPrime { + public_key: public_key, + private_key: private_key, + }; + + #[derive(Serialize)] + struct LicenseData<'a> { + name: &'a str, + email: &'a str, + // signature: Vec<u8>, + }; + + let license_data = LicenseData { + name: "User", + email: "user@example.com", + // signature: vec![], + }; + + aquatic_prime.plist(license_data); + } } |