public MeshNode(Stream s, string password, string profileFolder, TorController torController) { _password = password; _profileFolder = profileFolder; switch (s.ReadByte()) //version { case 1: //read headers and init decryptor Aes decryptionAlgo = Aes.Create(); decryptionAlgo.Key = MeshNetwork.GetKdfValue32(Encoding.UTF8.GetBytes(password), s.ReadBytes(32), 1, 1 * 1024 * 1024); //salt decryptionAlgo.IV = s.ReadBytes(16); //IV decryptionAlgo.Padding = PaddingMode.ISO10126; decryptionAlgo.Mode = CipherMode.CBC; byte[] hmac = s.ReadBytes(32); //hmac long cipherTextStartPosition = s.Position; //authenticate data in Encrypt-then-MAC (EtM) mode using (HMAC aeHmac = new HMACSHA256(decryptionAlgo.Key)) { byte[] computedHmac = aeHmac.ComputeHash(s); if (!BinaryNumber.Equals(hmac, computedHmac)) { throw new CryptographicException("Invalid password or data tampered."); } } //decrypt data and init node s.Position = cipherTextStartPosition; CryptoStream cS = new CryptoStream(s, decryptionAlgo.CreateDecryptor(), CryptoStreamMode.Read); InitMeshNode(new BinaryReader(cS), torController); break; case -1: throw new EndOfStreamException(); default: throw new InvalidDataException("MeshNode format version not supported."); } }
public void SaveTo(Stream s) { //generate salt for KDF byte[] salt = new byte[32]; _rng.GetBytes(salt); //create encryptor Aes encryptionAlgo = Aes.Create(); encryptionAlgo.Key = MeshNetwork.GetKdfValue32(Encoding.UTF8.GetBytes(_password), salt, 1, 1 * 1024 * 1024); encryptionAlgo.GenerateIV(); encryptionAlgo.Padding = PaddingMode.ISO10126; encryptionAlgo.Mode = CipherMode.CBC; //write headers s.WriteByte((byte)1); //version s.Write(salt); //salt s.Write(encryptionAlgo.IV); //IV s.Write(new byte[32]); //placeholder for HMAC long cipherTextStartPosition = s.Position; //write encrypted data { CryptoStream cS = new CryptoStream(s, encryptionAlgo.CreateEncryptor(), CryptoStreamMode.Write); BufferedStream bS = new BufferedStream(cS); WriteTo(new BinaryWriter(bS)); bS.Flush(); cS.FlushFinalBlock(); } //write hmac for authenticated encryption Encrypt-then-MAC (EtM) mode using (HMAC aeHmac = new HMACSHA256(encryptionAlgo.Key)) { s.Position = cipherTextStartPosition; byte[] hmac = aeHmac.ComputeHash(s); //write hmac s.Position = cipherTextStartPosition - 32; s.Write(hmac); } }