Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const int _saltSize = 48; // 16 is often recommended, better safe than sorry
- const int _keySize = 48;
- const int _iterations = 1048576; // maybe randomize + store?
- private static byte[] Hash(string password, int iterations, byte[] salt = null)
- {
- var pass = password.ToBytes();
- var saltAndHash = new byte[0];
- if (salt == null) // if encrypting, store salt
- {
- salt = new CryptoRandom().NextBytes(_saltSize);
- saltAndHash = Utils.Combine(saltAndHash, salt);
- }
- int blockSize = 8; // maybe 16 with less iterations considering modern GPUs?
- int parallel = 1;
- return Utils.Combine(saltAndHash, SCrypt.ComputeDerivedKey(pass, salt, iterations, blockSize, parallel, null, _keySize));
- }
- internal static void SaveMasterKey(Keyring k, string password, string file)
- {
- // Keyring is simply holding the session keys in CngKey props
- var hashed = Hash(password, _iterations);
- var saltSegment = new ArraySegment<byte>(hashed, 0, _saltSize);
- var passSegment = new ArraySegment<byte>(hashed, _saltSize, _keySize);
- var blob = k.SenderDHM.GetPrivateBlob();
- using (var fs = new FileStream(file, FileMode.Create, FileAccess.Write))
- {
- fs.Write(saltSegment.ToArray(), 0, _saltSize);
- using (var etm = new EtM_EncryptTransform(passSegment.ToArray(), saltSegment))
- using (var cs = new CryptoStream(fs, etm, CryptoStreamMode.Write))
- cs.Write(blob, 0, blob.Length);
- }
- }
- internal static Keyring LoadMasterKey(string password, string file)
- {
- var salt = new byte[_saltSize];
- Keyring k = new Keyring();
- using (var fs = new FileStream(file, FileMode.Open, FileAccess.Read))
- {
- fs.Read(salt, 0, _saltSize);
- var hashed = Hash(password, _iterations, salt);
- if (Authenticate(file, hashed, salt))
- {
- using (var etm = new EtM_DecryptTransform(hashed, salt.AsArraySegment()))
- using (var cs = new CryptoStream(fs, etm, CryptoStreamMode.Read))
- {
- byte[] blob = new byte[152];
- cs.Read(blob, 0, blob.Length);
- k.SenderDHM = blob.ToPrivateKeyFromBlob();
- }
- }
- }
- return k;
- }
- private static bool Authenticate(string file, byte[] key, byte[] salt)
- {
- using (var fs = new FileStream(file, FileMode.Open, FileAccess.Read))
- using (var etm = new EtM_DecryptTransform(key, salt.AsArraySegment(), authenticateOnly: true))
- {
- fs.Position = salt.Length;
- using (var cs = new CryptoStream(fs, etm, CryptoStreamMode.Read)) cs.CopyTo(Stream.Null);
- if (!etm.IsComplete) throw new Exception("Authentication failed.");
- }
- return true;
- }
- internal static void EncryptText(string text, Keyring k, string file, bool forSender)
- {
- SharedEphemeralBundle ephemeralBundle;
- if (forSender) ephemeralBundle = k.SenderDHM.GetSharedEphemeralDhmSecret();
- else ephemeralBundle = k.ReceiverDHM.GetSharedEphemeralDhmSecret();
- var ephemeralPublic = ephemeralBundle.EphemeralDhmPublicKeyBlob;
- var ephemeralSymmetric = ephemeralBundle.SharedSecret;
- var textBytes = text.ToBytes();
- using (var fs = new FileStream(file, FileMode.Create, FileAccess.Write))
- {
- fs.Write(ephemeralPublic, 0, ephemeralPublic.Length);
- using (var etm = new EtM_EncryptTransform(ephemeralSymmetric))
- using (var cs = new CryptoStream(fs, etm, CryptoStreamMode.Write))
- cs.Write(textBytes, 0, textBytes.Length);
- }
- }
- internal static string DecryptText(string file, Keyring k)
- {
- string decrypted = null;
- var ephemeralPublic = new byte[104];
- using (var fs = new FileStream(file, FileMode.Open, FileAccess.Read))
- {
- fs.Read(ephemeralPublic, 0, 104);
- var ephemeralSymmetric = k.SenderDHM.GetSharedDhmSecret(ephemeralPublic.ToPublicKeyFromBlob());
- if (Authenticate(file, ephemeralSymmetric, 104))
- {
- using (var etm = new EtM_DecryptTransform(ephemeralSymmetric))
- using (var cs = new CryptoStream(fs, etm, CryptoStreamMode.Read))
- {
- var decrypt = new byte[fs.Length - 104];
- cs.Read(decrypt, 0, decrypt.Length);
- decrypted = decrypt.FromBytes();
- }
- }
- }
- return decrypted;
- }
- // overloading the above similar
- private static bool Authenticate(string file, byte[] key, int offset)
- {
- using (var fs = new FileStream(file, FileMode.Open, FileAccess.Read))
- using (var etm = new EtM_DecryptTransform(key, authenticateOnly: true))
- {
- fs.Position = offset;
- using (var cs = new CryptoStream(fs, etm, CryptoStreamMode.Read)) cs.CopyTo(Stream.Null);
- if (!etm.IsComplete) throw new Exception("Authentication failed.");
- }
- return true;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement