public GetPassword GetPasswordGetter(string password) { var hasher = new HasherV2(password); var getgenpw = new PasswordGenerator(hasher.Hash, new StringifierV1().Stringify); var getaeppw = new PasswordGenerator(hasher.Hash, new StringifierVaep().Stringify); return(entry => { if (entry is StoredEntry stored) { return stored.password; } if (entry is GeneratedEntry gen) { if (GENERATED_PFP_TYPE.Equals(gen.type)) { return getgenpw.Get(gen); } else if (GENERATED_AEP_TYPE.Equals(gen.type)) { return getaeppw.Get(gen); } } throw new ArgumentException($"Unsupported entry for {entry.name}@{entry.site}"); }); }
public IList <BaseEntry> Load(Stream stream, string password) { var json = new JsonConvert(); var reader = new StreamReader(stream); var backup = json.Deserialize <DeserializedBackup>(reader.ReadToEnd()); if (!PFP_APPLICATION.Equals(backup.application)) { throw new ReaderException($"Unsupported application {backup.application}"); } if (!(backup.format == 2 || backup.format == 3)) { throw new ReaderException($"Unsupported format version {backup.format}"); } if (!(backup.data.ContainsKey(SALT_KEY) || backup.data.ContainsKey(HMAC_KEY))) { throw new ReaderException($"Invalid format"); } string str; var hasher = new HasherV2(password); var cipher = new CipherV1(hasher.Hash, backup.data[SALT_KEY]); var decrypt = GetDecryptFn(cipher); try { str = decrypt(backup.data[HMAC_KEY]); } catch (InvalidCipherTextException e) { if (e.Message.Equals(MAC_MESSAGE)) { throw new ReaderException("Wrong master password"); } else { throw; } } backup.data.Remove(SALT_KEY); backup.data.Remove(HMAC_KEY); var result = new List <BaseEntry>(); foreach (var item in backup.data) { if (!item.Key.StartsWith(STORAGE_PREFIX)) { continue; } str = decrypt(item.Value); result.Add(json.Deserialize <BaseEntry>(str)); } return(result); }
public void Save(Stream stream, string password, IList <BaseEntry> entries) { var backup = new DeserializedBackup { application = PFP_APPLICATION, format = 2, data = new Dictionary <string, string>() }; entries = Util.GenerateSiteEntries(entries); var salt = Util.GenerateRandom(SALT_LENGTH); var hmac = Util.GenerateRandom(HMAC_LENGTH); var json = new JsonConvert(); var hasher = new HasherV2(password); var digest = new DigesterV1(hmac); var cipher = new CipherV1(hasher.Hash, salt); var encrypt = GetEncryptFn(cipher); backup.data.Add(SALT_KEY, salt); backup.data.Add(HMAC_KEY, encrypt(json.Serialize(hmac))); foreach (var entry in entries) { var data = encrypt(json.Serialize(entry)); var key = STORAGE_PREFIX + digest.Digest(entry.site); if (entry is PassEntry pass) { key += ":" + digest.Digest(pass.site + "\0" + pass.name + "\0" + pass.revision); } backup.data.Add(key, data); } var writer = new StreamWriter(stream); var str = json.Serialize(backup); writer.Write(str); writer.Flush(); }