edcert_compressor/
certificate_compressor.rsuse edcert;
use edcert::certificate::Certificate;
use lzma;
static CERTIFICATE_COMPRESSOR_FORMAT_VERSION: [u8; 3] = [1, 1, 0];
pub struct CertificateCompressor;
impl CertificateCompressor {
fn get_version_from_bytes(bytes: &[u8]) -> String {
if bytes == b"ert" {
"1.0.0".to_string()
} else {
let major = bytes[0];
let minor = bytes[1];
let patch = bytes[2];
format!("{}.{}.{}", major, minor, patch)
}
}
fn get_bytes_from_version() -> [u8; 3] {
CERTIFICATE_COMPRESSOR_FORMAT_VERSION
}
pub fn decode(compressed: &[u8]) -> Result<Certificate, &'static str> {
use rustc_serialize::json;
use semver::Version;
use semver::VersionReq;
let mut bytes: Vec<u8> = Vec::new();
bytes.extend_from_slice(compressed);
let version = CertificateCompressor::get_version_from_bytes(&bytes[3..6]);
let version = Version::parse(&version).expect("Failed to parse file format version");
let vreq = VersionReq::parse("^1.0.0").expect("Failed to parse version requirement.");
if vreq.matches(&version) {
let magic: [u8; 6] = [0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00];
edcert::copy_bytes(&mut bytes[0..6], &magic, 0, 0, 6);
let o = lzma::decompress(&bytes[..]);
if o.is_err() {
return Err("Failed to decompress certificate");
}
let o = String::from_utf8(o.unwrap());
if o.is_err() {
return Err("Failed to read UTF8 from decompressed vector");
}
let o = json::decode(&o.unwrap());
if o.is_err() {
Err("Failed to decode JSON")
} else {
Ok(o.unwrap())
}
} else {
Err("Incompatible file format. File corrupted or old Edcert?")
}
}
pub fn encode(cert: &Certificate) -> Vec<u8> {
use rustc_serialize::json;
let jsoncode = json::encode(cert).expect("Failed to encode certificate");
let mut compressed = lzma::compress(jsoncode.as_bytes(), 6).expect("failed to compress");
let magic = b"edc";
let version = &CertificateCompressor::get_bytes_from_version()[..];
edcert::copy_bytes(&mut compressed[0..6], magic, 0, 0, 3);
edcert::copy_bytes(&mut compressed[3..6], version, 0, 0, 3);
compressed
}
}
#[test]
fn test_en_and_decoder() {
use rustc_serialize::json;
let cert: Certificate = json::decode(r#"
{
"meta": {
"values": {}
},
"public_key": "0000000000000000000000000000000000000000000000000000000000000000",
"private_key": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"expires": "2020-01-01T00:00:00+00:00",
"signature": null
}"#).unwrap();
let bytes = CertificateCompressor::encode(&cert);
assert_eq!(&bytes[0..3], b"edc");
assert_eq!(&bytes[3..6], CERTIFICATE_COMPRESSOR_FORMAT_VERSION);
let cert2 = CertificateCompressor::decode(&bytes).unwrap();
assert_eq!(cert, cert2);
}
#[test]
fn test_decode_no_version() {
use rustc_serialize::json;
let cert: Certificate = json::decode(r#"
{
"meta": {
"values": {}
},
"public_key": "0000000000000000000000000000000000000000000000000000000000000000",
"private_key": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"expires": "2020-01-01T00:00:00+00:00",
"signature": null
}"#).unwrap();
let mut bytes = CertificateCompressor::encode(&cert);
bytes[3] = 0x65;
bytes[4] = 0x72;
bytes[5] = 0x74;
let cert2 = CertificateCompressor::decode(&bytes).unwrap();
assert_eq!(cert, cert2);
}
#[test]
#[should_panic]
fn test_decode_old_version() {
use rustc_serialize::json;
let cert: Certificate = json::decode(r#"
{
"meta": {
"values": {}
},
"public_key": "0000000000000000000000000000000000000000000000000000000000000000",
"private_key": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"expires": "2020-01-01T00:00:00+00:00",
"signature": null
}"#).unwrap();
let mut bytes = CertificateCompressor::encode(&cert);
bytes[3] = 0;
bytes[4] = 1;
bytes[5] = 0;
CertificateCompressor::decode(&bytes).unwrap();
}
#[test]
#[should_panic]
fn test_decode_new_version() {
use rustc_serialize::json;
let cert: Certificate = json::decode(r#"
{
"meta": {
"values": {}
},
"public_key": "0000000000000000000000000000000000000000000000000000000000000000",
"private_key": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"expires": "2020-01-01T00:00:00+00:00",
"signature": null
}"#).unwrap();
let mut bytes = CertificateCompressor::encode(&cert);
let mut version = CERTIFICATE_COMPRESSOR_FORMAT_VERSION;
version[0] += 1;
version[1] = 0;
version[2] = 0;
edcert::copy_bytes(&mut bytes[3..6], &version, 0, 0, 3);
CertificateCompressor::decode(&bytes).unwrap();
}