Skip to content
This repository has been archived by the owner on Jul 3, 2022. It is now read-only.

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
vks committed Aug 10, 2016
0 parents commit 2ed76e6
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target
95 changes: 95 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "mpw"
version = "0.0.1"
authors = ["Vinzent Steinberg <[email protected]>"]

[dependencies]
rust-crypto = "0.2"
lazy_static = "0.2"
byteorder = "0.5"

[profile.dev]
opt-level = 2 # otherwise the tests run for too long
71 changes: 71 additions & 0 deletions src/algorithm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
extern crate crypto;
extern crate byteorder;

use std::io::{Read, Write};
use std::convert::TryInto;

use self::crypto::scrypt::{scrypt, ScryptParams};
use self::crypto::digest::Digest;
use self::crypto::sha2::Sha256;
use self::byteorder::{BigEndian, WriteBytesExt};

lazy_static! {
static ref scrypt_params: ScryptParams = ScryptParams::new(15, 8, 2);
}

#[derive(Clone, Copy)]
enum SiteVariant {
/// Generate the password to login with.
Password,
/// Generate the login name to log in as.
Login,
/// Generate the answer to a security question.
Answer,
}

fn scope_for_variant(variant: SiteVariant) -> &'static str {
match variant {
SiteVariant::Password => "com.lyndir.masterpassword",
SiteVariant::Login => "com.lyndir.masterpassword.login",
SiteVariant::Answer => "com.lyndir.masterpassword.answer",
}
}

pub fn master_key_for_user_v3(full_name: &[u8], master_password: &[u8]) -> Vec<u8> {
let mut master_key_salt = Vec::new();
master_key_salt.write_all(scope_for_variant(SiteVariant::Password).as_bytes());
let master_key_salt_len = full_name.len().try_into().unwrap();
// TODO little or big endian?
master_key_salt.write_u32::<BigEndian>(master_key_salt_len).unwrap();
master_key_salt.write_all(full_name).unwrap();
assert!(!master_key_salt.is_empty());
println!("master key salt: {}", id_for_buf(&master_key_salt));

let mut master_key = vec![0; 64];
scrypt(master_password, &master_key_salt, &scrypt_params, &mut master_key);
println!("master key: {}", id_for_buf(&master_key));

master_key
}

pub fn id_for_buf(buf: &[u8]) -> String {
let mut hasher = Sha256::new();
hasher.input(buf);
let hex = hasher.result_str();
hex
}

#[test]
fn test_key_for_user_v3() {
let full_name = "John Doe";
let master_password = "password";
let master_key = master_key_for_user_v3(
full_name.as_bytes(),
master_password.as_bytes()
);
let expected_master_key: [u8; 64] = [27, 177, 181, 88, 106, 115, 177, 174, 150, 213, 214, 9,
53, 44, 141, 132, 20, 254, 89, 228, 224, 58, 95, 52, 226, 174, 130, 64, 244, 84, 216, 6, 136,
210, 95, 208, 201, 115, 81, 48, 112, 177, 183, 129, 50, 44, 115, 10, 86, 114, 44, 225, 160,
170, 250, 210, 194, 87, 12, 220, 20, 36, 120, 232];
assert_eq!(&master_key[..], &expected_master_key as &[u8]);
}
10 changes: 10 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#![feature(try_from)]

#[macro_use]
extern crate lazy_static;

mod algorithm;
use algorithm::*;

fn main() {
}

0 comments on commit 2ed76e6

Please sign in to comment.