Keys and identities

[?]
Jun 1, 2021, 5:06 PM
EEBKW7VTILH6AGGV57ZIJ3DJGYHDSYBWGU3C7Q4WWAKSVNUGIYMQC

Dependencies

  • [2] VICI7FB3 Minor cleanup with default
  • [3] TFPETWTV Add config options for patch message templates
  • [4] IXC43DSH Fixing a bug in unrecord
  • [5] TVVW53HZ Conflict resolution
  • [6] GUL4M5FI Cleanup and formatting
  • [7] TPEH2XNB 1.0.0-alpha.28, with Tokio 1.0
  • [8] WZVCLZKY address clippy lints
  • [9] XWETQ4DE Upgrading versions
  • [10] 6YMDOZIB Refactoring apply
  • [11] BT2ZHPY4 Version bumps
  • [12] YN63NUZO Sanakirja 1.0
  • [13] 3WIQYEIS Fixing conflicts in Cargo.lock
  • [14] WEHUTJUK Lockfile update
  • [15] RXNT67OT Sanakirja version, and removing an unwrap
  • [16] I24UEJQL Various post-fire fixes
  • [17] IUGP6ZGB Add support for ~/.config/pijul even on macos
  • [18] OCBM7IFE New release: pijul-1.0.0-alpha.8
  • [19] SLJ3OHD4 unrecord: show list of changes if none were given as arguments
  • [20] I7VL7VPZ Minor cleanup
  • [21] QL6K2ZM3 Tags
  • [22] Q3GU26WD merge with changes from sanakirja v1.1.2
  • [23] XSEODPNE Fixing conflicts
  • [24] 4NNR32V6 conflicts
  • [25] XZYSNXG4 Fixing bugs in sanakirja-core, Cargo.lock update
  • [26] L4JXJHWX pijul/*: reorganize imports and remove extern crate
  • [27] AEPEFS7O Write help for each argument
  • [28] Y6EVFMTA Don't output files if they aren't in the current channel
  • [29] 7ZFRYVVQ Cargo.nix and formatting
  • [30] HDGRZISM Version updates
  • [31] V435QOJR Using path-slash to fix path issues on Windows
  • [32] A3DMBJJA Upgrading the `git` subcommand to the latest Sanakirja and Libpijul
  • [33] 7MNTFTDF Exit with an error when a change could not be signed
  • [34] T3S4P4ET Version updates
  • [35] AAXP2534 Tags: completing the subcommand
  • [36] H62VFFJE Cargo.nix, and solving conflicts
  • [37] PGERZ3KJ Channel renaming (also do not create a new channel when recording on a channel that doesn't exist)
  • [38] 6DOXSHWG Cleanup, and version bump
  • [39] LYTVEPH3 Avoid cloning into an existing path
  • [40] BZSC7VMY address clippy lints
  • [41] 4H2XTVJ2 Fix some mistakes in the docs
  • [42] 6HNRL5RT detect non-utf8 text files
  • [43] ZHABNS3S Canonicalize all paths
  • [44] 33SQMZYX New versions of dependencies
  • [45] ENKQ3QZG Forward the exit status messages from the SSH background loop to the client (solving hangs)
  • [46] SXEYMYF7 Fixing the bad changes in history (unfortunately, by rebooting).
  • [47] SAGSYAPX Various version bumps
  • [48] CCLLB7OI Upgrading to Sanakirja 0.15 + version bump
  • [49] JMBGCWM5 Fixing a zombie, probably due to the new conflict algorithm
  • [50] WIORLB47 Version bump
  • [51] JL4WKA5P Implement the Sanakirja concurrency model in a cross-process way
  • [52] B3QWIGDE Fixing the Git features with the latest Pijul (+ conflicts in Cargo.toml)
  • [53] F6V27C3M Fixing the "old file optimisation" in record, after the move to parallelisable records
  • [54] ZBNKSYA6 Fixing a bus error when starting a transaction on a full disk
  • [55] VO5OQW4W Removing anyhow in libpijul
  • [56] OU243LAB Support for staging
  • [57] JRENVH5D Reqwest 0.11
  • [58] UFCZKKLX Upgrading to the latest Sanakirja/Rand
  • [59] B5Z4IMEU Generating Cargo.nix for pijul 1.0.0-alpha.6
  • [60] I52XSRUH Massive cleanup, and simplification
  • [61] DJYHARZ7 Skipping old files when recording
  • [62] Q45QHPO4 Feedback on network stuff
  • [63] ZXTHL45O address clippy lints
  • [64] NS36CJCO Validating timestamps in record
  • [65] UDHP4ZVB Fixing SSH asynchronicity issues
  • [66] KWAGWB73 Adding extra dependencies from the config file
  • [*] SNZ3OAMC use native external subcommand support instead of hand-rolled one
  • [*] 5BB266P6 Optional colours in the global config file
  • [*] IIV3EL2X Cleanup, formatting, and fixing the Git feature
  • [*] OUWD436A Version bump
  • [*] 3M7WBE24 Re-adding anyhow in the tests of libpijul
  • [*] 23LVKATN Use pager crate for log output

Change contents

  • edit in pijul/src/main.rs at line 129
    [7.14]
    [68.25]
    /// Key management
    Key(Key),
  • edit in pijul/src/main.rs at line 220
    [7.64]
    [68.600]
    SubCommand::Key(key) => key.run().await,
  • replacement in pijul/src/config.rs at line 11
    [7.89960][7.89960:90002]()
    pub author: libpijul::change::Author,
    [7.89960]
    [7.781]
    pub author: Author,
  • edit in pijul/src/config.rs at line 18
    [69.66]
    [69.66]
    #[derive(Debug, Clone, Serialize, Deserialize)]
    pub struct Author {
    pub key_path: String,
    pub short_name: String,
    pub email: Option<String>,
    pub full_name: Option<String>,
    }
  • edit in pijul/src/config.rs at line 42
    [7.90005]
    [7.295]
    pub const GLOBAL_CONFIG_DIR: &str = ".pijulconfig";
  • edit in pijul/src/config.rs at line 45
    [7.90048]
    [7.90048]
    pub fn global_config_dir() -> Option<PathBuf> {
    if let Some(mut dir) = dirs_next::config_dir() {
    dir.push(CONFIG_DIR);
    Some(dir)
    } else {
    None
    }
    }
  • replacement in pijul/src/config.rs at line 56
    [7.90115][7.90115:90206]()
    if let Some(mut dir) = dirs_next::config_dir() {
    dir.push(CONFIG_DIR);
    [7.90115]
    [7.90206]
    if let Some(mut dir) = global_config_dir() {
  • replacement in pijul/src/config.rs at line 73
    [7.90437][7.90437:90487]()
    dir.push(".pijulconfig");
    [7.90437]
    [7.595]
    dir.push(GLOBAL_CONFIG_DIR);
  • replacement in pijul/src/commands/tag.rs at line 153
    [7.4750][7.4750:4794](),[7.4794][7.4794:4932](),[7.4932][7.4932:4995](),[7.4995][7.4995:5023](),[7.5023][7.5023:5062]()
    let authors = if let Some(a) = author {
    vec![libpijul::change::Author {
    name: a.to_string(),
    full_name: None,
    email: None,
    }]
    } else if let Ok(global) = crate::config::Global::load() {
    vec![global.author]
    } else {
    Vec::new()
    };
    [7.4750]
    [7.5062]
    let mut authors = Vec::new();
    if let Some(ref a) = author {
    authors.push(a.to_string());
    } else if let Some(mut dir) = crate::config::global_config_dir() {
    dir.push("publickey.json");
    if let Ok(key) = std::fs::File::open(&dir) {
    let k: libpijul::key::PublicKey = serde_json::from_reader(key).unwrap();
    authors.push(k.key)
    }
    }
  • replacement in pijul/src/commands/record.rs at line 15
    [7.192][7.1504:1573](),[7.2209][7.1504:1573](),[7.12657][7.1504:1573](),[7.101974][7.1504:1573](),[7.1573][7.102057:102092](),[7.102057][7.102057:102092]()
    use log::{debug, error};
    use serde_derive::{Deserialize, Serialize};
    use thrussh_keys::PublicKeyBase64;
    [7.12657]
    [7.102092]
    use log::debug;
  • edit in pijul/src/commands/record.rs at line 77
    [7.262][7.103721:103751](),[7.352][7.103721:103751](),[7.685][7.103721:103751](),[7.103721][7.103721:103751]()
    let sign = self.sign;
  • edit in pijul/src/commands/record.rs at line 134
    [7.13201]
    [7.104054]
    let key = if let Some(mut dir) = crate::config::global_config_dir() {
    dir.push("secretkey.json");
    if let Ok(key) = std::fs::File::open(&dir) {
    let k: libpijul::key::SecretKey = serde_json::from_reader(key)?;
    let pass = if k.encryption.is_some() {
    Some(rpassword::read_password_from_tty(Some(&format!(
    "Password for {:?}: ",
    dir
    )))?)
    } else {
    None
    };
    k.load(pass.as_deref())?
    } else {
    bail!("Secret key not found, please use `pijul key generate` and try again")
    }
    } else {
    bail!("Secret key not found, please use `pijul key generate` and try again")
    };
  • replacement in pijul/src/commands/record.rs at line 167
    [7.135][7.135:161](),[7.161][7.161:311](),[7.311][7.311:1144](),[7.1144][7.704:726](),[7.704][7.704:726](),[7.835][7.105083:105101](),[7.105083][7.105083:105101]()
    if sign {
    let mut key_path = dirs_next::home_dir().unwrap().join(".ssh");
    match sign_hash(&mut key_path, hash).await? {
    Some((pk, signature)) if !signature.is_empty() => {
    let sig = toml::Value::try_from(vec![Signature {
    public_key: pk,
    timestamp: change.header.timestamp,
    signature,
    }])?;
    let mut toml = toml::map::Map::new();
    toml.insert("signatures".to_string(), sig);
    change.unhashed = Some(toml.into());
    let hash2 = repo.changes.save_change(&change).unwrap();
    assert_eq!(hash2, hash);
    }
    _ => {
    bail!("Could not sign the change");
    }
    }
    }
    [7.135]
    [7.1145]
    change.unhashed = Some(serde_json::json!({
    "signature": key.sign_raw(&hash.to_bytes())?,
    }));
  • replacement in pijul/src/commands/record.rs at line 215
    [3.345][7.105419:105476](),[7.105419][7.105419:105476](),[7.105476][7.105476:105630](),[7.105630][3.346:399](),[3.399][3.399:439](),[3.439][7.105729:105780](),[7.105729][7.105729:105780]()
    let authors = if let Some(ref a) = self.author {
    vec![libpijul::change::Author {
    name: a.clone(),
    full_name: None,
    email: None,
    }]
    } else if let Ok(global) = config.as_ref() {
    vec![global.author.clone()]
    } else {
    Vec::new()
    };
    [3.345]
    [3.440]
    let mut authors = Vec::new();
    if let Some(ref a) = self.author {
    authors.push(a.clone());
    } else if let Some(mut dir) = crate::config::global_config_dir() {
    dir.push("publickey.json");
    if let Ok(key) = std::fs::File::open(&dir) {
    let k: libpijul::key::PublicKey = serde_json::from_reader(key).unwrap();
    authors.push(k.key)
    }
    }
  • edit in pijul/src/commands/record.rs at line 435
    [6.800][7.2904:2907](),[7.2904][7.2904:2907](),[7.2907][7.109867:110020](),[7.109867][7.109867:110020]()
    }
    #[derive(Debug, Serialize, Deserialize)]
    struct Signature {
    public_key: String,
    timestamp: chrono::DateTime<chrono::Utc>,
    signature: String,
  • edit in pijul/src/commands/record.rs at line 437
    [7.110023][7.110023:110043](),[7.110043][7.110043:110071](),[7.110071][7.2304:2330](),[7.2330][7.110107:110335](),[7.110107][7.110107:110335](),[7.110335][7.110335:110926](),[7.110926][7.110926:110966](),[7.110966][7.110966:110998](),[7.110998][7.110998:111089](),[7.111089][7.111089:111435](),[7.111435][7.111435:111454](),[7.111454][7.111454:111457]()
    async fn sign_hash(
    key_path: &mut PathBuf,
    hash: libpijul::Hash,
    ) -> Result<Option<(String, String)>, anyhow::Error> {
    let to_sign = hash.to_bytes();
    match thrussh_keys::agent::client::AgentClient::connect_env().await {
    Ok(agent) => {
    let mut agent = Some(agent);
    for k in &["id_ed25519.pub", "id_rsa.pub"] {
    key_path.push(k);
    if let Ok(key) = thrussh_keys::load_public_key(&key_path) {
    debug!("key");
    if let Some(a) = agent.take() {
    debug!("authenticate future");
    if let (_, Ok(sig)) = a.sign_request_base64(&key, &to_sign).await {
    key_path.pop();
    let key = key.public_key_base64();
    return Ok(Some((key, sig)));
    }
    }
    }
    key_path.pop();
    }
    }
    Err(e) => {
    error!("{:?}", e);
    }
    }
    for k in &["id_ed25519", "id_rsa"] {
    key_path.push(k);
    if let Some(k) = crate::remote::ssh::load_secret_key(&key_path, k) {
    key_path.pop();
    let pk = k.public_key_base64();
    return Ok(Some((pk, k.sign_detached(&to_sign)?.to_base64())));
    } else {
    key_path.pop();
    }
    }
    Ok(None)
    }
  • replacement in pijul/src/commands/record.rs at line 439
    [7.111592][7.111592:111613]()
    # comment to abort).
    [7.111592]
    [7.111613]
    # comment) to abort.
  • edit in pijul/src/commands/record.rs at line 441
    [7.102527][7.864:909](),[7.909][7.102527:102572](),[7.1289][7.102527:102572](),[7.102527][7.102527:102572]()
    /// Sign the change with the default key
    #[clap(short = 'S')]
    pub sign: bool,
  • resolve order conflict in pijul/src/commands/record.rs at line 441
    [7.111616]
  • edit in pijul/src/commands/mod.rs at line 57
    [70.91]
    [7.18549]
    mod key;
    pub use key::*;
  • file addition: key.rs (----------)
    [7.93386]
    use crate::config::*;
    use anyhow::bail;
    use chrono::Datelike;
    use clap::Clap;
    use log::debug;
    use std::io::Write;
    use std::path::Path;
    #[derive(Clap, Debug)]
    pub struct Key {
    #[clap(subcommand)]
    subcmd: Option<SubCommand>,
    }
    #[derive(Clap, Debug)]
    pub enum SubCommand {
    Generate {},
    }
    impl Key {
    pub async fn run(self) -> Result<(), anyhow::Error> {
    match self.subcmd {
    Some(SubCommand::Generate {}) => {
    if let Some(mut dir) = global_config_dir() {
    dir.push("secretkey.json");
    if std::fs::metadata(&dir).is_ok() {
    bail!("Cannot overwrite key file {:?}", dir)
    }
    debug!("creating file {:?}", dir);
    let mut f = open_secret_file(&dir)?;
    let expires = chrono::Utc::now();
    let expires = expires.with_year(expires.year() + 1).unwrap();
    let pass = rpassword::read_password_from_tty(Some(
    "Password for the new key (press enter to leave it unencrypted): ",
    ))?;
    let pass = if pass.is_empty() {
    None
    } else {
    Some(pass.as_ref())
    };
    let k = libpijul::key::SKey::generate(expires);
    serde_json::to_writer_pretty(&mut f, &k.save(pass))?;
    f.write_all(b"\n")?;
    let mut stderr = std::io::stderr();
    writeln!(stderr, "Wrote secret key in {:?}", dir)?;
    dir.pop();
    dir.push("publickey.json");
    debug!("creating file {:?}", dir);
    let mut f = std::fs::File::create(&dir)?;
    serde_json::to_writer_pretty(&mut f, &k.public_key())?;
    f.write_all(b"\n")?;
    }
    }
    None => {}
    }
    Ok(())
    }
    }
    #[cfg(unix)]
    fn open_secret_file(path: &Path) -> Result<std::fs::File, std::io::Error> {
    use std::fs::OpenOptions;
    use std::os::unix::fs::OpenOptionsExt;
    OpenOptions::new()
    .write(true)
    .create(true)
    .mode(0o600)
    .open(path)
    }
    #[cfg(not(unix))]
    fn open_secret_file(path: &Path) -> Result<std::fs::File, std::io::Error> {
    std::fs::File::create(path)
    }
  • edit in libpijul/src/lib.rs at line 33
    [7.27626]
    [7.27626]
    pub mod key;
  • file addition: key.rs (----------)
    [7.198146]
    use hmac::Hmac;
    use sha2::{Digest, Sha256};
    pub const CONTEXT: &'static [u8] = b"pijul";
    pub const VERSION: u64 = 0;
    #[derive(Debug, Error)]
    pub enum KeyError {
    #[error("Base 32 decoding error")]
    Encoding,
    #[error(transparent)]
    Dalek(#[from] ed25519_dalek::ed25519::Error),
    #[error("No password supplied")]
    NoPassword,
    #[error("The key expired")]
    Expired,
    }
    impl From<data_encoding::DecodePartial> for KeyError {
    fn from(_: data_encoding::DecodePartial) -> Self {
    KeyError::Encoding
    }
    }
    impl From<data_encoding::DecodeError> for KeyError {
    fn from(_: data_encoding::DecodeError) -> Self {
    KeyError::Encoding
    }
    }
    #[derive(Serialize, Deserialize)]
    pub struct SecretKey {
    pub version: u64,
    pub algorithm: Algorithm,
    pub expires: chrono::DateTime<chrono::Utc>,
    pub encryption: Option<Encryption>,
    pub key: String,
    }
    pub enum SKey {
    Ed25519 {
    key: ed25519_dalek::Keypair,
    expires: chrono::DateTime<chrono::Utc>,
    },
    }
    #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
    pub struct PublicKey {
    pub version: u64,
    pub algorithm: Algorithm,
    pub expires: chrono::DateTime<chrono::Utc>,
    pub signature: String,
    pub key: String,
    }
    #[derive(Debug)]
    pub enum PKey {
    Ed25519 {
    expires: chrono::DateTime<chrono::Utc>,
    signature: String,
    key: ed25519_dalek::PublicKey,
    },
    }
    #[test]
    fn sign_public_key() {
    use chrono::Datelike;
    let expires = chrono::Utc::now();
    let expires = expires.with_year(expires.year() + 1).unwrap();
    let sk = SKey::generate(expires);
    let pk = sk.public_key();
    println!("{:?}", pk);
    let pk = pk.load().unwrap();
    println!("{:?}", pk);
    }
    #[derive(Debug, Serialize, Deserialize)]
    pub struct Signature {
    pub version: u64,
    pub key: PublicKey,
    pub signature: String,
    pub date: chrono::DateTime<chrono::Utc>,
    }
    impl SKey {
    pub fn sign(&self, h: &[u8]) -> Result<Signature, KeyError> {
    Ok(Signature {
    version: VERSION,
    signature: self.sign_raw(h)?,
    key: self.public_key(),
    date: chrono::Utc::now(),
    })
    }
    pub fn sign_raw(&self, h: &[u8]) -> Result<String, KeyError> {
    match self {
    SKey::Ed25519 { key, expires } => {
    if expires <= &chrono::Utc::now() {
    return Err(KeyError::Expired);
    }
    let mut prehashed = ed25519_dalek::Sha512::new();
    prehashed.update(h);
    let sig = key.sign_prehashed(prehashed, Some(CONTEXT)).unwrap();
    Ok(data_encoding::BASE32_NOPAD.encode(&sig.to_bytes()))
    }
    }
    }
    pub fn generate(expires: chrono::DateTime<chrono::Utc>) -> Self {
    use rand::RngCore;
    let mut key = [0; 32];
    rand::thread_rng().fill_bytes(&mut key);
    SKey::Ed25519 {
    key: ed25519_dalek::Keypair::from_bytes(&key).unwrap(),
    expires,
    }
    }
    pub fn save(&self, password: Option<&str>) -> SecretKey {
    match self {
    SKey::Ed25519 { key, expires } => {
    let mut key = key.to_bytes();
    let encryption = if let Some(password) = password {
    use rand::Rng;
    let salt = rand::thread_rng()
    .sample_iter(&rand::distributions::Alphanumeric)
    .take(32)
    .collect();
    let enc = Encryption::Aes128(Kdf::Pbkdf2 { salt });
    enc.encrypt(password.as_bytes(), &mut key);
    Some(enc)
    } else {
    None
    };
    SecretKey {
    version: VERSION,
    algorithm: Algorithm::Ed25519,
    expires: expires.clone(),
    encryption,
    key: data_encoding::BASE32_NOPAD.encode(&key),
    }
    }
    }
    }
    pub fn public_key(&self) -> PublicKey {
    match self {
    SKey::Ed25519 { key, expires } => {
    let to_sign =
    bincode::serialize(&(Algorithm::Ed25519, expires.clone(), key.public)).unwrap();
    debug!("to_sign {:?}", to_sign);
    let mut prehashed = ed25519_dalek::Sha512::new();
    prehashed.update(&to_sign);
    let sig = key.sign_prehashed(prehashed, Some(CONTEXT)).unwrap();
    PublicKey {
    version: VERSION,
    algorithm: Algorithm::Ed25519,
    expires: expires.clone(),
    key: data_encoding::BASE32_NOPAD.encode(&key.public.clone().to_bytes()),
    signature: data_encoding::BASE32_NOPAD.encode(&sig.to_bytes()),
    }
    }
    }
    }
    pub fn pkey(&self) -> PKey {
    match self {
    SKey::Ed25519 { key, expires } => {
    let to_sign =
    bincode::serialize(&(Algorithm::Ed25519, expires.clone(), key.public)).unwrap();
    debug!("to_sign {:?}", to_sign);
    let mut prehashed = ed25519_dalek::Sha512::new();
    prehashed.update(&to_sign);
    let sig = key.sign_prehashed(prehashed, Some(CONTEXT)).unwrap();
    PKey::Ed25519 {
    expires: expires.clone(),
    key: key.public.clone(),
    signature: data_encoding::BASE32_NOPAD.encode(&sig.to_bytes()),
    }
    }
    }
    }
    }
    impl SecretKey {
    pub fn load(&self, pw: Option<&str>) -> Result<SKey, KeyError> {
    if self.expires <= chrono::Utc::now() {
    return Err(KeyError::Expired);
    }
    match self.algorithm {
    Algorithm::Ed25519 => {
    let mut key_enc = data_encoding::BASE32_NOPAD.decode(self.key.as_bytes())?;
    if let Some(ref enc) = self.encryption {
    let password = if let Some(ref pw) = pw {
    pw
    } else {
    return Err(KeyError::NoPassword);
    };
    enc.decrypt(password.as_bytes(), &mut key_enc);
    }
    Ok(SKey::Ed25519 {
    key: ed25519_dalek::Keypair::from_bytes(&key_enc)?,
    expires: self.expires,
    })
    }
    }
    }
    }
    impl PublicKey {
    pub fn fingerprint(&self) -> String {
    match self.algorithm {
    Algorithm::Ed25519 => {
    let signed =
    bincode::serialize(&(Algorithm::Ed25519, self.expires.clone(), &self.key))
    .unwrap();
    let mut prehashed = ed25519_dalek::Sha512::new();
    prehashed.update(&signed);
    data_encoding::BASE32_NOPAD.encode(&prehashed.finalize())
    }
    }
    }
    pub fn load(&self) -> Result<PKey, KeyError> {
    match self.algorithm {
    Algorithm::Ed25519 => {
    let key = ed25519_dalek::PublicKey::from_bytes(
    &data_encoding::BASE32_NOPAD.decode(self.key.as_bytes())?,
    )?;
    let mut signature = [0; 64];
    data_encoding::BASE32_NOPAD
    .decode_mut(self.signature.as_bytes(), &mut signature)?;
    let signature = ed25519_dalek::Signature::new(signature);
    let signed =
    bincode::serialize(&(Algorithm::Ed25519, self.expires.clone(), &key)).unwrap();
    debug!("signed {:?}", signed);
    key.verify_strict(&signed, &signature)?;
    Ok(PKey::Ed25519 {
    signature: self.signature.clone(),
    expires: self.expires.clone(),
    key,
    })
    }
    }
    }
    }
    impl PKey {
    pub fn save(&self) -> PublicKey {
    match self {
    PKey::Ed25519 {
    key,
    expires,
    signature,
    } => PublicKey {
    version: VERSION,
    algorithm: Algorithm::Ed25519,
    expires: expires.clone(),
    signature: signature.clone(),
    key: data_encoding::BASE32_NOPAD.encode(key.as_bytes()),
    },
    }
    }
    pub fn verify(
    &self,
    h: &[u8],
    signature: &str,
    date: &chrono::DateTime<chrono::Utc>,
    ) -> Result<(), KeyError> {
    match self {
    PKey::Ed25519 { key, expires, .. } => {
    if expires <= date {
    return Err(KeyError::Expired);
    }
    let mut sig = [0; 64];
    data_encoding::BASE32_NOPAD.decode_mut(signature.as_bytes(), &mut sig)?;
    let sig = ed25519_dalek::Signature::new(sig);
    let mut prehashed = ed25519_dalek::Sha512::new();
    prehashed.update(h);
    key.verify_prehashed(prehashed, Some(CONTEXT), &sig)?;
    Ok(())
    }
    }
    }
    }
    #[test]
    fn verify_test() {
    use chrono::Datelike;
    let expires = chrono::Utc::now();
    let expires = expires.with_year(expires.year() + 1).unwrap();
    let sk = SKey::generate(expires);
    let m = b"blabla";
    let signature = sk.sign(m).unwrap();
    signature.verify(m).unwrap();
    }
    impl Signature {
    pub fn verify(&self, h: &[u8]) -> Result<(), KeyError> {
    self.key.load()?.verify(h, &self.signature, &self.date)
    }
    }
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
    pub enum Algorithm {
    Ed25519,
    }
    #[derive(Serialize, Deserialize)]
    pub enum Encryption {
    Aes128(Kdf),
    }
    #[derive(Serialize, Deserialize)]
    pub enum Kdf {
    Pbkdf2 { salt: String },
    }
    impl Encryption {
    pub fn encrypt<'a>(&self, password: &[u8], bytes: &'a mut [u8]) {
    match self {
    Encryption::Aes128(Kdf::Pbkdf2 { ref salt }) => {
    let mut kdf = [0; 32];
    pbkdf2::pbkdf2::<Hmac<Sha256>>(password, salt.as_ref(), 10_000, &mut kdf);
    use aes::{
    cipher::FromBlockCipher, cipher::StreamCipher, Aes128, Aes128Ctr,
    NewBlockCipher,
    };
    let (a, b) = kdf.split_at(16);
    let cipher = Aes128::new(generic_array::GenericArray::from_slice(&a));
    let mut cipher = Aes128Ctr::from_block_cipher(
    cipher,
    generic_array::GenericArray::from_slice(b),
    );
    cipher.apply_keystream(bytes);
    }
    }
    }
    pub fn decrypt<'a>(&self, password: &[u8], bytes: &'a mut [u8]) {
    self.encrypt(password, bytes)
    }
    }
    #[test]
    fn encrypt_decrypt() {
    let enc = Encryption::Aes128(Kdf::Pbkdf2 {
    salt: "blabla".to_string(),
    });
    let b0 = b"very confidential secret".to_vec();
    let mut b = b0.clone();
    enc.encrypt(b"password", &mut b[..]);
    println!("{:?}", b);
    enc.decrypt(b"password", &mut b[..]);
    println!("{:?}", b);
    assert_eq!(b, b0);
    }
  • edit in libpijul/src/change.rs at line 32
    [7.36595]
    [7.36595]
    #[error(transparent)]
    Json(#[from] serde_json::Error),
  • replacement in libpijul/src/change.rs at line 111
    [7.833227][7.833227:833323](),[7.833323][7.833323:833365](),[7.833365][2.0:22](),[2.22][7.833404:833439](),[7.833404][7.833404:833439](),[7.833439][2.23:45](),[2.45][7.833478:833509](),[7.833478][7.833478:833509](),[7.833559][7.833559:833562](),[7.833562][7.833562:834123]()
    pub authors: Vec<Author>,
    }
    #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
    pub struct Author {
    pub name: String,
    #[serde(default)]
    pub full_name: Option<String>,
    #[serde(default)]
    pub email: Option<String>,
    }
    impl std::fmt::Display for Author {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
    if self.full_name.is_none() && self.email.is_none() {
    write!(fmt, "{:?}", self.name)
    } else {
    write!(fmt, "{{ name = {:?}", self.name)?;
    if let Some(ref f) = self.full_name {
    write!(fmt, ", full_name = {:?}", f)?;
    }
    if let Some(ref f) = self.email {
    write!(fmt, ", email = {:?}", f)?;
    }
    write!(fmt, " }}")
    }
    }
    [7.833227]
    [7.834123]
    pub authors: Vec<String>,
  • replacement in libpijul/src/change.rs at line 130
    [7.834579][7.834579:834618]()
    pub unhashed: Option<toml::Value>,
    [7.834579]
    [7.834618]
    pub unhashed: Option<serde_json::Value>,
  • replacement in libpijul/src/change.rs at line 149
    [7.138096][7.834952:834980](),[7.834952][7.834952:834980]()
    pub const VERSION: u64 = 4;
    [7.138096]
    [7.834980]
    pub const VERSION: u64 = 5;
  • replacement in libpijul/src/change.rs at line 1292
    [7.870686][7.870686:870741]()
    let s = toml::ser::to_string(un).unwrap();
    [7.870686]
    [7.870741]
    let s = serde_json::to_string(un).unwrap();
  • replacement in libpijul/src/change.rs at line 1419
    [7.875516][7.875516:875562]()
    Some(toml::de::from_slice(&out)?)
    [7.875516]
    [7.875562]
    Some(serde_json::from_slice(&out)?)
  • edit in libpijul/Cargo.toml at line 112
    [7.1023318]
    [7.1023318]
    serde_json = "1.0"
  • edit in libpijul/Cargo.toml at line 125
    [7.1023568]
    [7.1023568]
    ed25519-dalek = { version = "1.0", features = [ "serde" ] }
  • replacement in libpijul/Cargo.toml at line 133
    [7.1323][7.109304:109305](),[7.1023704][7.109304:109305]()
    [7.1323]
    [7.109305]
    pbkdf2 = { version = "*", default-features = false }
    aes = { version = "0.7", features = [ "ctr" ] }
    generic-array = "*"
    hmac = "*"
    sha2 = "*"
    rand = "0.5"
    rand_core = { version = "0.6", features = ["getrandom"] }
  • edit in Cargo.lock at line 19
    [7.1030901]
    [7.1030901]
    name = "aes"
    version = "0.7.4"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "495ee669413bfbe9e8cace80f4d3d78e6d8c8d99579f97fb93bde351b185f2d4"
    dependencies = [
    "cfg-if 1.0.0",
    "cipher",
    "cpufeatures",
    "ctr",
    "opaque-debug",
    ]
    [[package]]
  • replacement in Cargo.lock at line 37
    [7.1031102][7.1031102:1031113]()
    "memchr",
    [7.1031102]
    [7.1031113]
    "memchr 2.4.0",
  • replacement in Cargo.lock at line 119
    [7.1034193][7.1034193:1034211]()
    version = "0.3.7"
    [7.1034193]
    [7.1034211]
    version = "0.3.8"
  • replacement in Cargo.lock at line 121
    [7.1034276][7.1034276:1034354]()
    checksum = "e9ff35b701f3914bdb8fad3368d822c766ef2858b2583198e41639b936f09d3f"
    [7.1034276]
    [7.1034354]
    checksum = "b64485778c4f16a6a5a9d335e80d449ac6c70cdd6a06d2af18a6f6f775a125b3"
  • replacement in Cargo.lock at line 128
    [7.1034443][7.1034443:1034458]()
    "crypto-mac",
    [7.1034443]
    [7.1034458]
    "crypto-mac 0.8.0",
  • edit in Cargo.lock at line 130
    [7.1034469]
    [7.1034469]
    ]
    [[package]]
    name = "block-buffer"
    version = "0.9.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
    dependencies = [
    "generic-array",
  • replacement in Cargo.lock at line 147
    [7.1034677][7.1034677:1034688]()
    "memchr",
    [7.1034677]
    [7.1034688]
    "memchr 2.4.0",
  • replacement in Cargo.lock at line 152
    [7.1034720][7.151441:151459]()
    version = "3.6.1"
    [7.1034720]
    [7.1034738]
    version = "3.7.0"
  • replacement in Cargo.lock at line 154
    [7.1034803][7.151460:151538]()
    checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
    [7.1034803]
    [7.1034881]
    checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631"
  • replacement in Cargo.lock at line 176
    [7.1035288][7.151637:151656]()
    version = "1.0.67"
    [7.1035288]
    [7.1035307]
    version = "1.0.68"
  • replacement in Cargo.lock at line 178
    [7.1035372][7.151657:151735]()
    checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
    [7.1035372]
    [7.1035450]
    checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
  • replacement in Cargo.lock at line 203
    [7.6187][7.6187:6198]()
    "memchr",
    [7.6187]
    [7.6198]
    "memchr 2.4.0",
  • edit in Cargo.lock at line 221
    [7.1036624]
    [7.1036624]
    name = "cipher"
    version = "0.3.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
    dependencies = [
    "generic-array",
    ]
    [[package]]
  • edit in Cargo.lock at line 259
    [7.1037585]
    [7.4451]
    ]
    [[package]]
    name = "cloudabi"
    version = "0.0.3"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
    dependencies = [
    "bitflags",
  • edit in Cargo.lock at line 293
    [7.1038694]
    [7.1038694]
    name = "cpufeatures"
    version = "0.1.4"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "ed00c67cb5d0a7d64a44f6ad2668db7e7530311dd53ea79bcd4fb022c64911c8"
    dependencies = [
    "libc",
    ]
    [[package]]
  • replacement in Cargo.lock at line 323
    [7.117741][5.2935:2953]()
    version = "0.9.4"
    [7.117741]
    [7.117759]
    version = "0.9.5"
  • replacement in Cargo.lock at line 325
    [7.117824][5.2954:3032]()
    checksum = "52fb27eab85b17fbb9f6fd667089e07d6a2eb8743d02639ee7f6a7a7729c9c94"
    [7.117824]
    [7.117902]
    checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
  • replacement in Cargo.lock at line 336
    [7.902][5.3033:3051]()
    version = "0.8.4"
    [7.902]
    [7.920]
    version = "0.8.5"
  • replacement in Cargo.lock at line 338
    [7.985][5.3052:3130]()
    checksum = "4feb231f0d4d6af81aed15928e58ecf5816aa62a2393e2c82f46973e92a9a278"
    [7.985]
    [7.1063]
    checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
  • edit in Cargo.lock at line 340
    [7.1080][7.1080:1092]()
    "autocfg",
  • edit in Cargo.lock at line 355
    [7.1039684]
    [7.405]
    name = "crypto-mac"
    version = "0.11.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e"
    dependencies = [
    "generic-array",
    "subtle",
    ]
    [[package]]
  • edit in Cargo.lock at line 372
    [7.778]
    [7.490]
    ]
    [[package]]
    name = "ctr"
    version = "0.7.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "a232f92a03f37dd7d7dd2adc67166c77e9cd88de5b019b9a9eecfaeaf7bfd481"
    dependencies = [
    "cipher",
  • edit in Cargo.lock at line 470
    [7.1041772]
    [7.1041772]
    name = "ed25519"
    version = "1.1.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "8d0860415b12243916284c67a9be413e044ee6668247b99ba26d94b2bc06c8f6"
    dependencies = [
    "serde",
    "signature",
    ]
    [[package]]
    name = "ed25519-dalek"
    version = "1.0.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d"
    dependencies = [
    "curve25519-dalek",
    "ed25519",
    "rand 0.7.3",
    "serde",
    "serde_bytes",
    "sha2",
    "zeroize",
    ]
    [[package]]
  • replacement in Cargo.lock at line 561
    [7.1043005][5.3361:3379]()
    "redox_syscall",
    [7.1043005]
    [7.827]
    "redox_syscall 0.2.8",
  • replacement in Cargo.lock at line 625
    [7.1044436][7.692:725]()
    name = "funty"
    version = "1.1.0"
    [7.1044436]
    [7.725]
    name = "fuchsia-cprng"
    version = "0.1.1"
  • replacement in Cargo.lock at line 628
    [7.790][7.790:868]()
    checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
    [7.790]
    [7.868]
    checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
  • replacement in Cargo.lock at line 632
    [7.1044908][7.806:825]()
    version = "0.3.14"
    [7.1044908]
    [7.1044926]
    version = "0.3.15"
  • replacement in Cargo.lock at line 634
    [7.1044991][7.826:904]()
    checksum = "a9d5813545e459ad3ca1bff9915e9ad7f1a47dc6a91b627ce321d5863b7dd253"
    [7.1044991]
    [7.1045069]
    checksum = "0e7e43a803dae2fa37c1f6a8fe121e1f7bf9548b4dfc0522a42f34145dadfc27"
  • replacement in Cargo.lock at line 647
    [7.1045250][7.905:924]()
    version = "0.3.14"
    [7.1045250]
    [7.1045268]
    version = "0.3.15"
  • replacement in Cargo.lock at line 649
    [7.1045333][7.925:1003]()
    checksum = "ce79c6a52a299137a6013061e0cf0e688fce5d7f1bc60125f520912fdb29ec25"
    [7.1045333]
    [7.1045411]
    checksum = "e682a68b29a882df0545c143dc3646daefe80ba479bcdede94d5a703de2871e2"
  • replacement in Cargo.lock at line 657
    [7.1045499][7.1004:1023]()
    version = "0.3.14"
    [7.1045499]
    [7.1045517]
    version = "0.3.15"
  • replacement in Cargo.lock at line 659
    [7.1045582][7.1024:1102]()
    checksum = "098cd1c6dda6ca01650f1a37a794245eb73181d0d4d4e955e2f3c37db7af1815"
    [7.1045582]
    [7.1045660]
    checksum = "0402f765d8a89a26043b889b26ce3c4679d268fa6bb22cd7c6aad98340e179d1"
  • replacement in Cargo.lock at line 663
    [7.1045699][7.1103:1122]()
    version = "0.3.14"
    [7.1045699]
    [7.1045717]
    version = "0.3.15"
  • replacement in Cargo.lock at line 665
    [7.1045782][7.1123:1201]()
    checksum = "10f6cb7042eda00f0049b1d2080aa4b93442997ee507eb3828e8bd7577f94c9d"
    [7.1045782]
    [7.1045860]
    checksum = "badaa6a909fac9e7236d0620a2f57f7664640c56575b71a7552fbd68deafab79"
  • replacement in Cargo.lock at line 674
    [7.1045963][7.1202:1221]()
    version = "0.3.14"
    [7.1045963]
    [7.1045981]
    version = "0.3.15"
  • replacement in Cargo.lock at line 676
    [7.1046046][7.1222:1300]()
    checksum = "365a1a1fb30ea1c03a830fdb2158f5236833ac81fa0ad12fe35b29cddc35cb04"
    [7.1046046]
    [7.1046124]
    checksum = "acc499defb3b348f8d8f3f66415835a9131856ff7714bf10dadfc4ec4bdb29a1"
  • replacement in Cargo.lock at line 680
    [7.1046160][7.1301:1320]()
    version = "0.3.14"
    [7.1046160]
    [7.1046178]
    version = "0.3.15"
  • replacement in Cargo.lock at line 682
    [7.1046243][7.1321:1399]()
    checksum = "668c6733a182cd7deb4f1de7ba3bf2120823835b3bcfbeacf7d2c4a773c1bb8b"
    [7.1046243]
    [7.1046321]
    checksum = "a4c40298486cdf52cc00cd6d6987892ba502c7656a16a4192a9992b1ccedd121"
  • edit in Cargo.lock at line 684
    [7.1046338]
    [7.1046338]
    "autocfg",
  • replacement in Cargo.lock at line 693
    [7.1046429][7.1400:1419]()
    version = "0.3.14"
    [7.1046429]
    [7.1046447]
    version = "0.3.15"
  • replacement in Cargo.lock at line 695
    [7.1046512][7.1420:1498]()
    checksum = "5c5629433c555de3d82861a7a4e3794a4c40040390907cfbfd7143a92a426c23"
    [7.1046512]
    [7.1046590]
    checksum = "a57bead0ceff0d6dde8f465ecd96c9338121bb7717d3e7b108059531870c4282"
  • replacement in Cargo.lock at line 699
    [7.1046625][7.1499:1518]()
    version = "0.3.14"
    [7.1046625]
    [7.1046643]
    version = "0.3.15"
  • replacement in Cargo.lock at line 701
    [7.1046708][7.1519:1597]()
    checksum = "ba7aa51095076f3ba6d9a1f702f74bd05ec65f555d70d2033d55ba8d69f581bc"
    [7.1046708]
    [7.1046819]
    checksum = "8a16bef9fc1a4dddb5bee51c989e3fbba26569cbb0e31f5b303c184e3dd33dae"
  • replacement in Cargo.lock at line 705
    [7.1046854][7.1598:1617]()
    version = "0.3.14"
    [7.1046854]
    [7.1046872]
    version = "0.3.15"
  • replacement in Cargo.lock at line 707
    [7.1046937][7.1618:1696]()
    checksum = "3c144ad54d60f23927f0a6b6d816e4271278b64f005ad65e4e35291d2de9c025"
    [7.1046937]
    [7.1047015]
    checksum = "feb5c238d27e2bf94ffdfd27b2c29e3df4a68c4193bb6427384259e2bf191967"
  • edit in Cargo.lock at line 709
    [7.1047032]
    [7.1047032]
    "autocfg",
  • replacement in Cargo.lock at line 716
    [7.1047136][7.1047136:1047147]()
    "memchr",
    [7.1047136]
    [7.1347]
    "memchr 2.4.0",
  • replacement in Cargo.lock at line 753
    [7.242][7.153812:153830]()
    version = "0.2.2"
    [7.242]
    [7.260]
    version = "0.2.3"
  • replacement in Cargo.lock at line 755
    [7.325][7.153831:153909]()
    checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
    [7.325]
    [7.1047677]
    checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
  • replacement in Cargo.lock at line 770
    [7.1047978][7.1697:1717]()
    version = "0.13.18"
    [7.1047978]
    [7.1047998]
    version = "0.13.20"
  • replacement in Cargo.lock at line 772
    [7.1048063][7.1718:1796]()
    checksum = "b483c6c2145421099df1b4efd50e0f6205479a072199460eff852fa15e5603c7"
    [7.1048063]
    [7.1048141]
    checksum = "d9831e983241f8c5591ed53f17d874833e2fa82cac2625f3888c50cbfe136cba"
  • edit in Cargo.lock at line 837
    [7.1049706]
    [7.1049706]
    ]
    [[package]]
    name = "hmac"
    version = "0.11.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
    dependencies = [
    "crypto-mac 0.11.0",
    "digest",
  • replacement in Cargo.lock at line 879
    [7.1050396][7.2211:2229]()
    version = "1.0.0"
    [7.1050396]
    [7.1050414]
    version = "1.0.1"
  • replacement in Cargo.lock at line 881
    [7.1050479][7.2230:2308]()
    checksum = "05842d0d43232b23ccb7060ecb0f0626922c21f30012e97b767b30afd4a5d4b9"
    [7.1050479]
    [7.1050557]
    checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440"
  • replacement in Cargo.lock at line 906
    [7.1051305][7.2309:2328]()
    version = "0.14.7"
    [7.1051305]
    [7.1051324]
    version = "0.14.8"
  • replacement in Cargo.lock at line 908
    [7.1051389][7.2329:2407]()
    checksum = "1e5f105c494081baa3bf9e200b279e27ec1623895cd504c7dbef8d0b080fcf54"
    [7.1051389]
    [7.1051467]
    checksum = "d3f71a7eea53a3f8257a7b4795373ff886397178cd634430ea94e12d7fe4fe34"
  • replacement in Cargo.lock at line 962
    [7.1052495][7.1052495:1052506]()
    "memchr",
    [7.1052495]
    [7.1052506]
    "memchr 2.4.0",
  • edit in Cargo.lock at line 1026
    [7.6410][7.6410:6432](),[7.6432][5.3872:3890](),[7.900][7.6450:6515](),[5.3890][7.6450:6515](),[7.6450][7.6450:6515](),[7.6515][5.3891:3969](),[7.979][7.6593:6636](),[5.3969][7.6593:6636](),[7.6593][7.6593:6636](),[7.6636][7.980:997](),[7.997][7.6654:6686](),[7.6654][7.6654:6686](),[7.6686][7.1054528:1054541](),[7.1054528][7.1054528:1054541]()
    name = "lexical-core"
    version = "0.7.6"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
    dependencies = [
    "arrayvec",
    "bitflags",
    "cfg-if 1.0.0",
    "ryu",
    "static_assertions",
    ]
    [[package]]
  • replacement in Cargo.lock at line 1027
    [7.1054747][5.3970:3989]()
    version = "0.2.94"
    [7.1054747]
    [7.1054766]
    version = "0.2.95"
  • replacement in Cargo.lock at line 1029
    [7.1054831][5.3990:4068]()
    checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
    [7.1054831]
    [7.1054909]
    checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36"
  • replacement in Cargo.lock at line 1033
    [7.1054943][7.2901:2927]()
    version = "0.12.19+1.1.0"
    [7.1054943]
    [7.1054969]
    version = "0.12.21+1.1.0"
  • replacement in Cargo.lock at line 1035
    [7.1055034][7.2928:3006]()
    checksum = "f322155d574c8b9ebe991a04f6908bb49e68a79463338d24a43d6274cb6443e6"
    [7.1055034]
    [7.1055112]
    checksum = "86271bacd72b2b9e854c3dcfb82efd538f15f870e4c11af66900effb462f6825"
  • edit in Cargo.lock at line 1049
    [71.746]
    [72.8168]
    "aes",
  • edit in Cargo.lock at line 1063
    [71.867]
    [7.6702]
    "ed25519-dalek",
  • edit in Cargo.lock at line 1067
    [7.1055681]
    [7.1055681]
    "generic-array",
    "hmac",
  • edit in Cargo.lock at line 1074
    [4.1758]
    [7.1055730]
    "pbkdf2",
  • edit in Cargo.lock at line 1076
    [7.1055747]
    [7.1055756]
    "rand 0.5.6",
    "rand_core 0.6.2",
  • edit in Cargo.lock at line 1082
    [7.1055807]
    [7.1055807]
    "serde_json",
    "sha2",
  • replacement in Cargo.lock at line 1089
    [7.1055861][7.6719:6739]()
    "tree_magic_mini",
    [7.1055861]
    [5.4069]
    "tree_magic",
  • edit in Cargo.lock at line 1136
    [7.1781]
    [7.1056864]
    [[package]]
    name = "lock_api"
    version = "0.3.4"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75"
    dependencies = [
    "scopeguard",
    ]
  • edit in Cargo.lock at line 1178
    [7.1057738]
    [7.1057738]
    [[package]]
    name = "memchr"
    version = "1.0.2"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
    dependencies = [
    "libc",
    ]
  • replacement in Cargo.lock at line 1206
    [7.118123][7.3105:3123]()
    version = "0.6.3"
    [7.118123]
    [7.118141]
    version = "0.6.4"
  • replacement in Cargo.lock at line 1208
    [7.118206][7.3124:3202]()
    checksum = "f83fb6581e8ed1f85fd45c116db8405483899489e38406156c25eb743554361d"
    [7.118206]
    [7.118284]
    checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
  • replacement in Cargo.lock at line 1283
    [7.6768][7.1097:1115]()
    version = "6.1.2"
    [7.6768]
    [7.6786]
    version = "3.2.1"
  • replacement in Cargo.lock at line 1285
    [7.6851][7.1116:1194]()
    checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2"
    [7.6851]
    [7.6929]
    checksum = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b"
  • replacement in Cargo.lock at line 1287
    [7.6946][7.1195:1216](),[7.1216][7.6946:6992](),[7.6946][7.6946:6992]()
    "bitvec",
    "funty",
    "lexical-core",
    "memchr",
    "version_check",
    [7.6946]
    [7.1280]
    "memchr 1.0.2",
  • replacement in Cargo.lock at line 1301
    [7.1060567][7.1060567:1060585]()
    version = "0.2.6"
    [7.1060567]
    [7.1060585]
    version = "0.4.0"
  • replacement in Cargo.lock at line 1303
    [7.1060650][7.1060650:1060728]()
    checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
    [7.1060650]
    [7.1060728]
    checksum = "4e0d047c1062aa51e256408c560894e5251f08925980e53cf1aa5bd00eec6512"
  • edit in Cargo.lock at line 1352
    [7.1061891]
    [7.1061891]
    name = "opaque-debug"
    version = "0.3.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
    [[package]]
  • replacement in Cargo.lock at line 1373
    [7.1062216][7.1062216:1062234]()
    version = "0.1.2"
    [7.1062216]
    [7.1062234]
    version = "0.1.4"
  • replacement in Cargo.lock at line 1375
    [7.1062299][7.1062299:1062377]()
    checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
    [7.1062299]
    [7.1062377]
    checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a"
  • replacement in Cargo.lock at line 1398
    [7.1062871][7.1062871:1062889]()
    version = "2.2.0"
    [7.1062871]
    [7.1062889]
    version = "2.3.0"
  • replacement in Cargo.lock at line 1400
    [7.1062954][7.1062954:1063032]()
    checksum = "7edc011af0ae98b7f88cf7e4a83b70a54a75d2b8cb013d6efd02e5956207e9eb"
    [7.1062954]
    [7.1063032]
    checksum = "96eaebe22d9f12429b1af6a0b5dd411ccfc5cb5968710abbb8c512046be9df90"
  • edit in Cargo.lock at line 1413
    [73.1000]
    [73.1000]
    ]
    [[package]]
    name = "parking_lot"
    version = "0.10.2"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e"
    dependencies = [
    "lock_api 0.3.4",
    "parking_lot_core 0.7.2",
  • replacement in Cargo.lock at line 1432
    [7.1063286][7.1063286:1063320]()
    "lock_api",
    "parking_lot_core",
    [7.1063286]
    [7.1063320]
    "lock_api 0.4.4",
    "parking_lot_core 0.8.3",
    ]
    [[package]]
    name = "parking_lot_core"
    version = "0.7.2"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3"
    dependencies = [
    "cfg-if 0.1.10",
    "cloudabi",
    "libc",
    "redox_syscall 0.1.57",
    "smallvec",
    "winapi",
  • replacement in Cargo.lock at line 1459
    [7.1063591][5.4678:4696]()
    "redox_syscall",
    [7.1063591]
    [7.1063609]
    "redox_syscall 0.2.8",
  • edit in Cargo.lock at line 1469
    [4.1953]
    [7.1063843]
    [[package]]
    name = "pbkdf2"
    version = "0.8.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa"
    dependencies = [
    "crypto-mac 0.11.0",
    ]
  • replacement in Cargo.lock at line 1633
    [7.1067446][7.4031:4050]()
    version = "1.0.26"
    [7.1067446]
    [7.1067465]
    version = "1.0.27"
  • replacement in Cargo.lock at line 1635
    [7.1067530][7.4051:4129]()
    checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
    [7.1067530]
    [7.1067608]
    checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
  • replacement in Cargo.lock at line 1650
    [7.1068075][7.1413:1447]()
    name = "radium"
    version = "0.5.3"
    [7.1068075]
    [7.1447]
    name = "rand"
    version = "0.5.6"
  • replacement in Cargo.lock at line 1653
    [7.1512][7.1512:1590]()
    checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
    [7.1512]
    [7.1590]
    checksum = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9"
    dependencies = [
    "cloudabi",
    "fuchsia-cprng",
    "libc",
    "rand_core 0.3.1",
    "winapi",
    ]
  • edit in Cargo.lock at line 1709
    [7.1068609]
    [7.1068609]
    version = "0.3.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
    dependencies = [
    "rand_core 0.4.2",
    ]
    [[package]]
    name = "rand_core"
    version = "0.4.2"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
    [[package]]
    name = "rand_core"
  • replacement in Cargo.lock at line 1737
    [7.1340][7.156327:156347]()
    "getrandom 0.2.2",
    [7.1340]
    [7.1396]
    "getrandom 0.2.3",
  • edit in Cargo.lock at line 1760
    [7.1069063]
    [5.4701]
    version = "0.1.57"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
    [[package]]
    name = "redox_syscall"
  • replacement in Cargo.lock at line 1779
    [7.2688][7.156467:156487](),[7.156487][5.4799:4817]()
    "getrandom 0.2.2",
    "redox_syscall",
    [7.2688]
    [7.2732]
    "getrandom 0.2.3",
    "redox_syscall 0.2.8",
  • replacement in Cargo.lock at line 1790
    [7.1069710][7.1069710:1069721]()
    "memchr",
    [7.1069710]
    [7.1069721]
    "memchr 2.4.0",
  • replacement in Cargo.lock at line 1885
    [7.1072347][7.1072347:1072363]()
    "parking_lot",
    [7.1072347]
    [7.157020]
    "parking_lot 0.11.1",
  • edit in Cargo.lock at line 1892
    [7.157079][5.5114:5132]()
    version = "1.2.7"
  • edit in Cargo.lock at line 1894
    [7.157162][5.5133:5211]()
    checksum = "81ad8f3bbfb988e3ce4e5e73ee50f5d5a7f99a5e6dba4123b491feebb5da94d5"
  • replacement in Cargo.lock at line 1940
    [7.1073413][7.4745:4765]()
    version = "1.0.125"
    [7.1073413]
    [7.1073433]
    version = "1.0.126"
  • replacement in Cargo.lock at line 1942
    [7.1073498][7.4766:4844]()
    checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
    [7.1073498]
    [7.1073576]
    checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
  • edit in Cargo.lock at line 1945
    [7.1073610]
    [7.1073610]
    ]
    [[package]]
    name = "serde_bytes"
    version = "0.11.5"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "16ae07dd2f88a366f15bd0632ba725227018c69a1c8550a927324f8eb8368bb9"
    dependencies = [
    "serde",
  • replacement in Cargo.lock at line 1958
    [7.1073647][7.4845:4865]()
    version = "1.0.125"
    [7.1073647]
    [7.1073667]
    version = "1.0.126"
  • replacement in Cargo.lock at line 1960
    [7.1073732][7.4866:4944]()
    checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
    [7.1073732]
    [7.1073810]
    checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
  • edit in Cargo.lock at line 1991
    [7.1074561]
    [7.9594]
    name = "sha2"
    version = "0.9.5"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "b362ae5752fd2137731f9fa25fd4d9058af34666ca1966fb969119cc35719f12"
    dependencies = [
    "block-buffer",
    "cfg-if 1.0.0",
    "cpufeatures",
    "digest",
    "opaque-debug",
    ]
    [[package]]
  • edit in Cargo.lock at line 2013
    [7.9826]
    [7.1074561]
    name = "signature"
    version = "1.3.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "0f0242b8e50dd9accdd56170e94ca1ebd223b098eb9c83539a6e367d0f36ae68"
    [[package]]
  • replacement in Cargo.lock at line 2070
    [7.1076034][7.1604:1635]()
    name = "tap"
    version = "1.0.1"
    [7.1076034]
    [7.1635]
    name = "synstructure"
    version = "0.12.4"
  • replacement in Cargo.lock at line 2073
    [7.1700][7.1700:1778]()
    checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
    [7.1700]
    [7.1778]
    checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
    dependencies = [
    "proc-macro2",
    "quote",
    "syn",
    "unicode-xid",
    ]
  • replacement in Cargo.lock at line 2083
    [7.1076047][7.158061:158080]()
    version = "0.4.33"
    [7.1076047]
    [7.1076066]
    version = "0.4.35"
  • replacement in Cargo.lock at line 2085
    [7.1076131][7.158081:158159]()
    checksum = "c0bcfbd6a598361fda270d82469fff3d65089dc33e175c9a131f7b4cd395f228"
    [7.1076131]
    [7.1076209]
    checksum = "7d779dc6aeff029314570f666ec83f19df7280bb36ef338442cfa8c604021b80"
  • replacement in Cargo.lock at line 2101
    [7.119563][5.5313:5331]()
    "redox_syscall",
    [7.119563]
    [7.1076541]
    "redox_syscall 0.2.8",
  • replacement in Cargo.lock at line 2117
    [7.5506][7.158185:158204]()
    version = "0.1.16"
    [7.5506]
    [7.5525]
    version = "0.1.17"
  • replacement in Cargo.lock at line 2119
    [7.5590][7.158205:158283]()
    checksum = "86ca8ced750734db02076f44132d802af0b33b09942331f4459dde8636fd2406"
    [7.5590]
    [7.5668]
    checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
  • replacement in Cargo.lock at line 2136
    [7.1077299][7.158284:158303]()
    version = "1.0.24"
    [7.1077299]
    [7.1077318]
    version = "1.0.25"
  • replacement in Cargo.lock at line 2138
    [7.1077383][7.158304:158382]()
    checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
    [7.1077383]
    [7.1077461]
    checksum = "fa6f76457f59514c7eeb4e59d891395fab0b2fd1d40723ae737d64153392e9c6"
  • replacement in Cargo.lock at line 2145
    [7.1077536][7.158383:158402]()
    version = "1.0.24"
    [7.1077536]
    [7.1077555]
    version = "1.0.25"
  • replacement in Cargo.lock at line 2147
    [7.1077620][7.158403:158481]()
    checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
    [7.1077620]
    [7.1077698]
    checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d"
  • replacement in Cargo.lock at line 2174
    [7.1078238][5.5332:5351]()
    version = "0.32.9"
    [7.1078238]
    [7.351]
    version = "0.32.10"
  • replacement in Cargo.lock at line 2176
    [7.416][5.5352:5430]()
    checksum = "72d58952cd321b79c05e8c999b81ed6094b627157c415679fa297007a4a84da9"
    [7.416]
    [7.1078400]
    checksum = "cb1b66e306cd9ab12f999ecc97a932ef56c2c91797ee190d23020a9fca942c37"
  • replacement in Cargo.lock at line 2207
    [7.1078612][5.5431:5450]()
    version = "0.20.4"
    [7.1078612]
    [7.1078631]
    version = "0.20.6"
  • replacement in Cargo.lock at line 2209
    [7.1078696][5.5451:5529]()
    checksum = "ca573360d2c7d31df13c747663e69d7210aa732744feeeb808c8889f40934d02"
    [7.1078696]
    [7.1078774]
    checksum = "56bed0381d0c5755086157488cb53d1fee935d00815d4d329541e72ef07e75f7"
  • replacement in Cargo.lock at line 2269
    [7.1080033][7.5480:5498]()
    version = "1.5.0"
    [7.1080033]
    [7.4153]
    version = "1.6.1"
  • replacement in Cargo.lock at line 2271
    [7.4218][7.5499:5577]()
    checksum = "83f0c8e7c0addab50b663055baf787d0af7f413a46e6e7fb9559a4e4db7137a5"
    [7.4218]
    [7.4296]
    checksum = "0a38d31d7831c6ed7aad00aa4c12d9375fd225a6dd77da1d25b707346319a975"
  • replacement in Cargo.lock at line 2276
    [7.4350][7.4350:4361]()
    "memchr",
    [7.4350]
    [7.1900]
    "memchr 2.4.0",
  • replacement in Cargo.lock at line 2288
    [7.1080410][7.158908:158926]()
    version = "1.1.0"
    [7.1080410]
    [7.1080428]
    version = "1.2.0"
  • replacement in Cargo.lock at line 2290
    [7.1080493][7.158927:159005]()
    checksum = "caf7b11a536f46a809a8a9f0bb4237020f70ecbf115b842360afb127ea2fda57"
    [7.1080493]
    [7.1080571]
    checksum = "c49e3df43841dafb86046472506755d8501c5615673955f6aa17181125d13c37"
  • replacement in Cargo.lock at line 2309
    [7.1080894][7.5578:5596]()
    version = "0.6.6"
    [7.1080894]
    [7.1080912]
    version = "0.6.7"
  • replacement in Cargo.lock at line 2311
    [7.1080977][7.5597:5675]()
    checksum = "940a12c99365c31ea8dd9ba04ec1be183ffe4920102bb7122c2f515437601e8e"
    [7.1080977]
    [7.1081055]
    checksum = "1caa0b0c8d94a049db56b5acf8cba99dc0623aab1b26d5b5f5e2d945846b3592"
  • replacement in Cargo.lock at line 2357
    [7.7451][7.7451:7476](),[7.7476][5.5728:5746]()
    name = "tree_magic_mini"
    version = "3.0.0"
    [7.7451]
    [7.7494]
    name = "tree_magic"
    version = "0.2.3"
  • replacement in Cargo.lock at line 2360
    [7.7559][5.5747:5825]()
    checksum = "0687683589ce7d3912e6bf52c1620d970fbed86c27e12118ca779a3780bbf888"
    [7.7559]
    [7.7637]
    checksum = "b1d99367ce3e553a84738f73bd626ccca541ef90ae757fdcdc4cbe728e6cb629"
  • replacement in Cargo.lock at line 2365
    [7.7686][5.5826:5840]()
    "once_cell",
    [7.7686]
    [7.7686]
    "parking_lot 0.10.2",
  • replacement in Cargo.lock at line 2403
    [7.1083214][7.159416:159435]()
    version = "0.1.17"
    [7.1083214]
    [7.1083233]
    version = "0.1.18"
  • replacement in Cargo.lock at line 2405
    [7.1083298][7.159436:159514]()
    checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef"
    [7.1083298]
    [7.1083376]
    checksum = "33717dca7ac877f497014e10d73f3acf948c342bee31b5ca7892faf94ccc6b49"
  • replacement in Cargo.lock at line 2446
    [7.1084476][7.159613:159633]()
    "getrandom 0.2.2",
    [7.1084476]
    [7.1084485]
    "getrandom 0.2.3",
  • replacement in Cargo.lock at line 2451
    [7.1084515][7.5873:5892]()
    version = "0.2.12"
    [7.1084515]
    [7.1084534]
    version = "0.2.13"
  • replacement in Cargo.lock at line 2453
    [7.1084599][7.5893:5971]()
    checksum = "cbdbff6266a24120518560b5dc983096efb98462e51d0d68169895b237be3e5d"
    [7.1084599]
    [7.1084677]
    checksum = "025ce40a007e1907e58d5bc1a594def78e5573bb0b1160bc389634e8f12e4faa"
  • edit in Cargo.lock at line 2643
    [7.1090066][7.1890:2077]()
    [[package]]
    name = "wyz"
    version = "0.2.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
  • replacement in Cargo.lock at line 2655
    [7.1090311][7.1090311:1090329]()
    version = "0.3.2"
    [7.1090311]
    [7.1090329]
    version = "0.4.0"
  • replacement in Cargo.lock at line 2657
    [7.1090394][7.1090394:1090472]()
    checksum = "0de7bff972b4f2a06c85f6d8454b09df153af7e3a4ec2aac81db1b105b684ddb"
    [7.1090394]
    [7.1090472]
    checksum = "e262a29d0e61ccf2b6190d7050d4b237535fc76ce4c1210d9caa316f71dffa75"
  • edit in Cargo.lock at line 2668
    [7.7166]
    [7.1090709]
    dependencies = [
    "zeroize_derive",
    ]
    [[package]]
    name = "zeroize_derive"
    version = "1.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "a2c1e130bebaeab2f23886bf9acbaca14b092408c452543c857f66399cd6dab1"
    dependencies = [
    "proc-macro2",
    "quote",
    "syn",
    "synstructure",
    ]
  • edit in Cargo.lock at line 2695
    [7.1091001][7.1091001:1091003](),[7.1033914][7.444:460](),[7.460][5.2638:2657](),[5.2657][7.479:544](),[7.479][7.479:544](),[7.544][5.2658:2736](),[5.2736][7.622:676](),[7.622][7.622:676]()
    ]
    name = "bitvec"
    version = "0.19.5"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321"
    dependencies = [
    "funty",
    "radium",
    "tap",
    "wyz",
  • resolve order conflict in Cargo.lock at line 2695
    [7.1091001]
    [7.676]
  • edit in Cargo.lock at line 2696
    [7.678][7.678:691]()
    [[package]]