1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// The MIT License (MIT)
//
// Copyright (c) 2016 Marvin Böcker
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

//! This crate is a simple digital signature crate and can be used to verify data integrity by
//! using public-key cryptography. It uses the "super-fast, super-secure" elliptic curve and
//! digital signature algorithm [Ed25519](https://ed25519.cr.yp.to/).
//!
//! It provides the struct `Certificate`, which holds the public key, metadata and a signature.
//!
//! # The basics
//! A `Certificate` can be signed by a master key, or another `Certificate`. The top-most `Certificate`
//! must be signed with the master key, or it will not be valid. For validation, the master public
//! key will be given. This way, a `Certificate` can only be valid, if it has been signed with a
//! trust chain, which top-most `Certificate` has been signed with the right private key.
//!
//! See also [here](https://en.wikipedia.org/wiki/EdDSA).
//!
//! ## Other crates
//!
//! To use the edcert ecosystem, there are a few other crates to make your life simpler:
//!
//! - [edcert-letter](https://crates.io/crates/edcert-letter), which provides a container for
//!    signed data, Letter<T>.
//! - [edcert-restrevoke](https://crates.io/crates/edcert-restrevoke), which provides a REST-based
//!   revokation system.
//! - [edcert-compressor](https://crates.io/crates/edcert-compressor), which provides methods to
//!   (de)compress `Certificate`s using JSON/LZMA and manages loading/saving certificates for you.
//! - [edcert-tools](https://crates.io/crates/edcert-tools), which provides a binary for
//!   generation, signing, validation, etc using edcert (and all of the above).

#![deny(missing_docs)]

// External crates.
extern crate chrono;
extern crate rustc_serialize;
extern crate sodiumoxide;

// Internal modules
mod bytescontainer;
pub mod ed25519;

// External modules
pub mod certificate;
pub mod fingerprint;
pub mod meta;
pub mod signature;

// Validation
pub mod validator;
pub mod root_validator;
pub mod trust_validator;

// Revokation
pub mod revoker;

/// This is a simple copy function. This should be equivalent to memcpy.
pub fn copy_bytes(dest: &mut [u8], src: &[u8], start_dest: usize, start_src: usize, len: usize) {
    let end_dest = start_dest + len;
    let end_src = start_src + len;
    dest[start_dest..end_dest].copy_from_slice(&src[start_src..end_src]);
}

#[test]
fn test_readme_example() {
    use chrono::Timelike;
    use chrono::UTC;
    use chrono::duration::Duration;
    use meta::Meta;
    use certificate::Certificate;
    use validator::Validator;
    use root_validator::RootValidator;
    use trust_validator::TrustValidator;
    use revoker::NoRevoker;
    use fingerprint::Fingerprint;

    // create random master key
    let (mpk, msk) = ed25519::generate_keypair();

    // create random certificate
    let meta = Meta::new_empty();
    let expires = UTC::now()
        .checked_add(Duration::days(90))
        .expect("Failed to add 90 days to expiration date.")
        .with_nanosecond(0)
        .unwrap();
    let mut cert = Certificate::generate_random(meta, expires);

    // sign certificate with master key
    cert.sign_with_master(&msk);

    // we can use a RootValidator, which analyzes the trust chain.
    // in this case, the top-most certificate must be signed with the right private key for mpk.
    let cv = RootValidator::new(&mpk, NoRevoker);

    // now we use the CV to validate certificates
    assert_eq!(true, cv.is_valid(&cert).is_ok());

    // we could also use a TrustValidator. It's like RootValidator, but you can also give trusted
    // certificates. If the chain contains one of these, the upper certificates aren't checked
    // with the master public key. We can give any 32 byte key here, it doesn't matter.
    let mut tcv = TrustValidator::new(NoRevoker);
    tcv.add_trusted_certificates(vec![cert.fingerprint()]);

    // even though we gave a wrong master key, this certificate is valid, because it is trusted.
    assert_eq!(true, tcv.is_valid(&cert).is_ok());

    // now we sign data with it
    let data = [1; 42];

    // and sign the data with the certificate
    let signature = cert.sign(&data)
        .expect("This fails, if no private key is known to the certificate.");

    // the signature must be valid
    assert_eq!(true, cert.verify(&data, &signature));
}