Esempio n. 1
0
        /// <summary>
        /// Duplicates Python hash library pbkdf2_hmac for hash_name = 'sha512' and dklen = None
        ///
        /// Performance can be improved by pre-computing _trans_36 and _trans_5c.
        /// Unlike Python's hash functions, .NET doesn't currently support copying state between blocks.
        /// This results in having to recompute hash of innerSeed and outerSeed on each iteration.
        /// </summary>
        /// <param name="password"></param>
        /// <param name="salt"></param>
        /// <param name="iterations"></param>
        /// <returns></returns>
        public static UInt512 PbKdf2HmacSha512(ReadOnlyByteSpan password, ReadOnlyByteSpan salt, int iterations)
        {
            if (iterations < 1)
            {
                throw new ArgumentException();
            }

            byte[] passwordBytes = password;

            using var inner = new SHA512Managed();
            using var outer = new SHA512Managed();

            const int blocksize = 128; // match python hash library sha512 block size.

            if (passwordBytes.Length > blocksize)
            {
                inner.TransformFinalBlock(passwordBytes, 0, passwordBytes.Length);
                passwordBytes = inner.Hash;
                //inner.Initialize();
            }

            if (passwordBytes.Length < blocksize)
            {
                Array.Resize(ref passwordBytes, blocksize);
            }

            var trans36 = new byte[256];
            var trans5C = new byte[256];

            for (var i = 0; i < 256; i++)
            {
                trans36[i] = (byte)(i ^ 0x36);
                trans5C[i] = (byte)(i ^ 0x5c);
            }

            var innerSeed = passwordBytes.Select(pb => trans36[pb]).ToArray();
            var outerSeed = passwordBytes.Select(pb => trans5C[pb]).ToArray();

            var hash  = new UInt512();
            var xhash = new UInt512();

            var data = new byte[salt.Length + 4];

            salt.CopyTo(data);
            1.AsReadOnlySpan(bigEndian: true).CopyTo(data.AsSpan(salt.Length));
            var dataSpan = data.AsSpan();

            for (var i = 0; i < iterations; i++)
            {
                inner.TransformBlock(innerSeed);
                outer.TransformBlock(outerSeed);
                inner.TransformFinalBlock(dataSpan, hash.Span);
                outer.TransformFinalBlock(hash.Span, hash.Span);
                dataSpan = hash.Span;
                xhash    = i == 0 ? hash : xhash ^ hash;
            }

            return(xhash);
        }
Esempio n. 2
0
 /// <summary>
 /// Computes a SHA512 hash
 /// </summary>
 /// <param name="text">String or filename of file hash</param>
 /// <returns>Hexadecimal SHA512 hash string</returns>
 public static string SHA512(string s)
 {
     if (System.IO.File.Exists(s))
     {
         int    offset = 0;
         byte[] block  = new byte[ZefieLib.Data.BlockSize];
         byte[] hash;
         using (BufferedStream f = new BufferedStream(new FileStream(s, FileMode.Open, FileAccess.Read)))
         {
             using (SHA512 shaM = new SHA512Managed())
             {
                 // For each block:
                 while (offset + block.Length < f.Length)
                 {
                     f.Position = offset;
                     f.Read(block, 0, ZefieLib.Data.BlockSize);
                     offset += shaM.TransformBlock(block, 0, block.Length, null, 0);
                 }
                 int remain = (int)(f.Length - (long)offset);
                 block      = new byte[remain];
                 f.Position = offset;
                 _          = f.Read(block, 0, remain);
                 _          = shaM.TransformFinalBlock(block, 0, block.Length);
                 hash       = shaM.Hash;
             }
         }
         return(ZefieLib.Data.BytesToHex(hash));
     }
     else
     {
         return(SHA512(Encoding.UTF8.GetBytes(s)));
     }
 }
Esempio n. 3
0
        internal static byte[] GetHmacKey64(byte[] pbKey, ulong uBlockIndex)
        {
            if (pbKey == null)
            {
                throw new ArgumentNullException("pbKey");
            }
            Debug.Assert(pbKey.Length == 64);

            // We are computing the HMAC using SHA-256, whose internal
            // block size is 512 bits; thus create a key that is 512
            // bits long (using SHA-512)

            byte[] pbBlockKey;
            using (SHA512Managed h = new SHA512Managed())
            {
                byte[] pbIndex = MemUtil.UInt64ToBytes(uBlockIndex);

                h.TransformBlock(pbIndex, 0, pbIndex.Length, pbIndex, 0);
                h.TransformBlock(pbKey, 0, pbKey.Length, pbKey, 0);
                h.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0);

                pbBlockKey = h.Hash;
            }

#if DEBUG
            byte[] pbZero = new byte[64];
            Debug.Assert((pbBlockKey.Length == 64) && !MemUtil.ArraysEqual(
                             pbBlockKey, pbZero));    // Ensure we own pbBlockKey
#endif
            return(pbBlockKey);
        }
Esempio n. 4
0
 /// <summary>
 /// Given a string for a site name, generate the registry subkey name
 /// </summary>
 /// <param name="site">The site name to get the key from</param>
 /// <returns>The generated registry key string, or null on failure</returns>
 public static string GenerateKeyFromSite(string site)
 {
     try
     {
         // Otherwise, only bother if we have a site to work with:
         if (!String.IsNullOrEmpty(site) && site.Length > 0)
         {
             // Get the SHA-512 of the site name.  We'll also include the user's
             // username and the machine name as a salt.  We really should change
             // the encoding here to something like UTF-8, but we'll leave this
             // at the default to keep from breaking the user's data.
             SHA512Managed hasher   = new SHA512Managed();
             byte[]        keyBytes = Encoding.Default.GetBytes(site + Environment.UserName +
                                                                Environment.MachineName);
             keyBytes = hasher.TransformFinalBlock(keyBytes, 0, keyBytes.Length);
             // Convert the binary hash to Base64, then chop it down to 255 characters
             // if it's too long.  Windows registry keys can only be 255 characters
             // in length.
             string key = Convert.ToBase64String(keyBytes);
             if (key.Length > 255)
             {
                 return(key.Substring(0, 255));
             }
             else
             {
                 return(key);
             }
         }
         else
         {
             return(null);
         }
     }
     catch { return(null); }
 }
Esempio n. 5
0
        /// <summary>
        /// Hashes data from a stream.
        /// </summary>
        /// <param name="es">The input stream.</param>
        /// <param name="length">The number of bytes to hash.</param>
        /// <returns>The hashed digest.</returns>
        /// <remarks>
        /// The method will hash length bytes of the stream from the current position
        /// and the stream position will be restored before the method
        /// returns.
        /// </remarks>
        public static byte[] Compute(EnhancedStream es, long length)
        {
            var  sha512 = new SHA512Managed();
            long streamPos;

            byte[] buf;
            int    cb;

            streamPos = es.Position;
            buf       = new byte[8192];

            while (length > 0)
            {
                cb = (int)(length > buf.Length ? buf.Length : length);
                if (es.Read(buf, 0, cb) < cb)
                {
                    throw new InvalidOperationException("Read past end of stream.");
                }

                sha512.TransformBlock(buf, 0, cb, buf, 0);
                length -= cb;
            }

            sha512.TransformFinalBlock(buf, 0, 0);
            es.Seek(streamPos, SeekOrigin.Begin);

            return(sha512.Hash);
        }
Esempio n. 6
0
        public byte[] CreateChecksum(string filePath)
        {
            using (var hashAlgorithm = new SHA512Managed())
            {
                using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 1024 * 1024))
                {
                    fileStream.Position = 0;
                    long bytesToHash = 1024 * 1024;

                    var buf = new byte[4 * 1024];
                    while (bytesToHash > 0)
                    {
                        var bytesRead = fileStream.Read(buf, 0, (int)Math.Min(bytesToHash, buf.Length));
                        hashAlgorithm.TransformBlock(buf, 0, bytesRead, null, 0);
                        bytesToHash -= bytesRead;
                        if (bytesRead == 0)
                        {
                            throw new InvalidOperationException("Unexpected end of stream");
                        }
                    }
                    hashAlgorithm.TransformFinalBlock(buf, 0, 0);
                    var hash = hashAlgorithm.Hash;
                    return(hash);
                }
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Given a size in bytes, generate an initialization vector (IV) for encryption
        /// </summary>
        /// <param name="size">Size of the output byte array</param>
        /// <returns>An array of bytes to be used as the IV</returns>
        private static byte[] GenerateIV(int size, string key)
        {
            // Use SHA-512 to generate a pseudo-random IV.  We'll use the user's username and
            // the machine name as the key data; this isn't really super secure, but it should
            // at least be unique per user/machine.  Note that we're using the system default
            // encoding here, rather than UTF-8; this is a bit of legacy code, and we can't
            // really change this without breaking existing parameters.  Since this is an
            // internal thing, so it shouldn't be a problem.
            SHA512Managed hasher = new SHA512Managed();

            byte[] iv = Encoding.Default.GetBytes(key + Environment.UserName +
                                                  Environment.MachineName);
            hasher.TransformFinalBlock(iv, 0, iv.Length);
            iv = hasher.Hash;
            // SHA-512 is probably overkill for the IV we need.  So given the size value,
            // chop of only the number of bytes we need and return those.
            if (iv.Length > size)
            {
                byte[] slice = new byte[size];
                Array.Copy(iv, 0, slice, 0, size);
                return(slice);
            }
            else
            {
                return(iv);
            }
        }
 public static string GEtSHA512Hash(string plainMessage)
 {
     byte[] bytes = Encoding.UTF8.GetBytes(plainMessage);
     using (HashAlgorithm algorithm = new SHA512Managed())
     {
         algorithm.TransformFinalBlock(bytes, 0, bytes.Length);
         return(Convert.ToBase64String(algorithm.Hash));
     }
 }
        /// <summary>
        /// 使用 SHA512算法哈希
        /// </summary>
        /// <param name="plainMessage"></param>
        /// <returns></returns>
        public static string GetSHA512Hash(string plainMessage)
        {
            var data = Encoding.UTF8.GetBytes(plainMessage);

            using (HashAlgorithm sha = new SHA512Managed())
            {
                sha.TransformFinalBlock(data, 0, data.Length);
                return(Convert.ToBase64String(sha.Hash));
            }
        }
Esempio n. 10
0
        private void DeriveCipher()
        {
            SHA512Managed sha = new SHA512Managed();

            sha.TransformBlock(_secretKey, 0, _secretKey.Length, _secretKey, 0);
            sha.TransformFinalBlock(_cipherSalt, 0, _cipherSalt.Length);

            _aes         = new AesManaged();
            _aes.KeySize = (int)AesKeyBits;
            _aes.IV      = _iv;
            _aes.Key     = new byte[AesKeyBits / 8];
            Array.Copy(sha.Hash, _aes.Key, _aes.Key.Length);
            _aes.Mode = CipherMode.CBC;
        }
Esempio n. 11
0
    public static byte[] GenerateSharedSecret(byte[] server_pub_key, out byte[] client_pub_key)
    {
        byte[] client_sec_key = RandomBytes(32);
        client_pub_key = ScalarMultBase(client_sec_key);

        byte [] q = ScalarMult(client_sec_key, server_pub_key);

        var h = new SHA512Managed();

        h.TransformBlock(q, 0, q.Length, q, 0);
        h.TransformBlock(client_pub_key, 0, client_pub_key.Length, client_pub_key, 0);
        h.TransformBlock(server_pub_key, 0, server_pub_key.Length, server_pub_key, 0);
        h.TransformFinalBlock(q, 0, 0);
        return(h.Hash);
    }
Esempio n. 12
0
        private void DeriveCipher()
        {
            SHA512Managed sha = new SHA512Managed();

            sha.TransformBlock(_secretKey, 0, _secretKey.Length, _secretKey, 0);
            sha.TransformFinalBlock(_cipherSalt, 0, _cipherSalt.Length);

            _aes = new AesManaged
            {
                KeySize = (int)AesKeyBits,
                IV      = _iv,
                Key     = sha.Hash.Take((int)(AesKeyBits / 8)).ToArray(),
                Mode    = CipherMode.CBC
            };
        }
        /// <summary>
        /// Given the user's password, generate a salt which will be mixed with the password
        /// when setting up the encryption parameters
        /// </summary>
        /// <param name="password">A string containing the user's password</param>
        /// <returns>An array of bytes containing the raw salt value</returns>
        private static byte[] GenerateSaltFromPassword(string password)
        {
            // Get the password as Unicode (UTF-8) bytes:
            byte[] salt = Encoding.UTF8.GetBytes(password);
            // Try to hash password multiple times using a really strong hash.
            // This should give us some really random-ish data for the salt.
            SHA512Managed hasher = new SHA512Managed();

            for (int i = 0; i < SALT_ITERATION_COUNT; i++)
            {
                // .NET notes:  This isn't quite as simple as the Java version.  Each
                // time we use the hash engine, it must be initialized.  We then have
                // to tell it to transform the final block, which effectively gets it
                // to hash the whole thing.  Then we have to update our salt reference
                // to the new value.
                hasher.Initialize();
                hasher.TransformFinalBlock(salt, 0, salt.Length);
                salt = hasher.Hash;
            }
            return(salt);
        }
Esempio n. 14
0
        private byte[] GetSystemEntropy()
        {
            SHA512Managed h = new SHA512Managed();

            byte[] pb4 = new byte[4];
            byte[] pb8 = new byte[8];

            GAction <byte[], bool> f = delegate(byte[] pbValue, bool bClearValue)
            {
                if (pbValue == null)
                {
                    Debug.Assert(false); return;
                }
                if (pbValue.Length == 0)
                {
                    return;
                }
                h.TransformBlock(pbValue, 0, pbValue.Length, pbValue, 0);
                if (bClearValue)
                {
                    MemUtil.ZeroByteArray(pbValue);
                }
            };
            Action <int> fI32 = delegate(int iValue)
            {
                MemUtil.Int32ToBytesEx(iValue, pb4, 0);
                f(pb4, false);
            };
            Action <long> fI64 = delegate(long lValue)
            {
                MemUtil.Int64ToBytesEx(lValue, pb8, 0);
                f(pb8, false);
            };
            Action <string> fStr = delegate(string strValue)
            {
                if (strValue == null)
                {
                    Debug.Assert(false); return;
                }
                if (strValue.Length == 0)
                {
                    return;
                }
                f(StrUtil.Utf8.GetBytes(strValue), false);
            };

            fI32(Environment.TickCount);
            fI64(DateTime.UtcNow.ToBinary());

#if !KeePassLibSD && !NETSTANDARD2_0
            // In try-catch for systems without GUI;
            // https://sourceforge.net/p/keepass/discussion/329221/thread/20335b73/
            try
            {
                Point pt = Cursor.Position;
                fI32(pt.X);
                fI32(pt.Y);
            }
            catch (Exception) { Debug.Assert(NativeLib.IsUnix()); }
#endif

            try
            {
                fI32((int)NativeLib.GetPlatformID());
#if KeePassUAP
                fStr(EnvironmentExt.OSVersion.VersionString);
#else
                fStr(Environment.OSVersion.VersionString);
#endif

                fI32(Environment.ProcessorCount);

#if !KeePassUAP && !NETSTANDARD2_0
                fStr(Environment.CommandLine);
                fI64(Environment.WorkingSet);
#endif
            }
            catch (Exception) { Debug.Assert(false); }

            try
            {
                foreach (DictionaryEntry de in Environment.GetEnvironmentVariables())
                {
                    fStr(de.Key as string);
                    fStr(de.Value as string);
                }
            }
            catch (Exception) { Debug.Assert(false); }

            try
            {
#if KeePassUAP
                f(DiagnosticsExt.GetProcessEntropy(), true);
#elif !KeePassLibSD && !NETSTANDARD2_0
                using (Process p = Process.GetCurrentProcess())
                {
                    fI64(p.Handle.ToInt64());
                    fI32(p.HandleCount);
                    fI32(p.Id);
                    fI64(p.NonpagedSystemMemorySize64);
                    fI64(p.PagedMemorySize64);
                    fI64(p.PagedSystemMemorySize64);
                    fI64(p.PeakPagedMemorySize64);
                    fI64(p.PeakVirtualMemorySize64);
                    fI64(p.PeakWorkingSet64);
                    fI64(p.PrivateMemorySize64);
                    fI64(p.StartTime.ToBinary());
                    fI64(p.VirtualMemorySize64);
                    fI64(p.WorkingSet64);

                    // Not supported in Mono 1.2.6:
                    // fI32(p.SessionId);
                }
#endif
            }
            catch (Exception) { Debug.Assert(NativeLib.IsUnix()); }

            try
            {
                CultureInfo ci = CultureInfo.CurrentCulture;
                if (ci != null)
                {
                    fI32(ci.GetHashCode());
                }
                else
                {
                    Debug.Assert(false);
                }
            }
            catch (Exception) { Debug.Assert(false); }

            f(Guid.NewGuid().ToByteArray(), false);
            f(GetCspRandom(), true);

            h.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0);
            byte[] pbHash = h.Hash;
            h.Clear();
            MemUtil.ZeroByteArray(pb4);
            MemUtil.ZeroByteArray(pb8);
            return(pbHash);
        }
Esempio n. 15
0
 public static void SHA512(this ReadOnlySpan <byte> data, Span <byte> hash)
 {
     using (var sha = new SHA512Managed()) {
         sha.TransformFinalBlock(data, hash);
     }
 }
        public static ServiceManifestType SetHashVersion(this ServiceManifestType srv, string baseDir, string targetDir, int maxHashLength)
        {
            SHA512Managed sha;
            List <byte>   configHash = new List <byte>();
            int           offset     = 0;

            if (srv.CodePackage != null)
            {
                foreach (var cv in srv.CodePackage)
                {
                    sha    = new SHA512Managed();
                    offset = 0;

                    var path = cv.Name == "Code" ? targetDir : Path.Combine(baseDir, "PackageRoot", cv.Name);

                    foreach (var f in Directory.GetFiles(path, "*.dll").Concat(Directory.GetFiles(path, "*.exe")))
                    {
                        var b = File.ReadAllBytes(f);
                        sha.TransformBlock(b, offset, b.Length, b, offset);
                    }

                    sha.TransformFinalBlock(new byte[0], offset, 0);
                    cv.Version += "." + Uri.EscapeDataString(Convert.ToBase64String(sha.Hash));
                    configHash.AddRange(sha.Hash);
                }
            }

            if (srv.ConfigPackage != null)
            {
                foreach (var cv in srv.ConfigPackage)
                {
                    sha    = new SHA512Managed();
                    offset = 0;

                    foreach (var f in Directory.GetFiles(Path.Combine(baseDir, "PackageRoot", cv.Name)))
                    {
                        var b = File.ReadAllBytes(f);
                        sha.TransformBlock(b, offset, b.Length, b, offset);
                    }

                    sha.TransformFinalBlock(new byte[0], offset, 0);
                    cv.Version += "." + Uri.EscapeDataString(Convert.ToBase64String(sha.Hash));
                    configHash.AddRange(sha.Hash);
                }
            }

            if (srv.DataPackage != null)
            {
                foreach (var cv in srv.DataPackage)
                {
                    sha    = new SHA512Managed();
                    offset = 0;

                    foreach (var f in Directory.GetFiles(Path.Combine(baseDir, "PackageRoot", cv.Name)))
                    {
                        var b = File.ReadAllBytes(f);
                        sha.TransformBlock(b, offset, b.Length, b, offset);
                    }

                    sha.TransformFinalBlock(new byte[0], offset, 0);
                    cv.Version += "." + Uri.EscapeDataString(Convert.ToBase64String(sha.Hash));
                    configHash.AddRange(sha.Hash);
                }
            }

            srv.Version += "." + Uri.EscapeDataString(Convert.ToBase64String(new SHA512Managed().ComputeHash(configHash.ToArray())));
            return(srv);
        }
 public static void Sha512(this ReadOnlyByteSequence data, ByteSpan hash)
 {
     using var sha = new SHA512Managed();
     sha.TransformFinalBlock(data, hash);
 }
Esempio n. 18
0
 /// <summary>
 /// Gets the final <see cref="SHA512Value"/>.
 /// Once this value has been read this stream should be disposed.
 /// </summary>
 /// <returns>The final SHA512 value.</returns>
 public SHA512Value GetFinalResult()
 {
     _sha512.TransformFinalBlock(Array.Empty <byte>(), 0, 0);
     return(new SHA512Value(_sha512.Hash));
 }
Esempio n. 19
0
        /// <summary>
        /// Duplicates Python hashlib's pbkdf2_hmac for hash_name = 'sha512' and dklen = None
        ///
        /// Performance can be improved by precomputing _trans_36 and _trans_5c.
        /// Unlike Python's hash functions, .NET doesn't currently support copying state between blocks.
        /// This results in having to recompute hash of innerSeed and outerSeed on each iteration.
        /// </summary>
        /// <param name="password"></param>
        /// <param name="salt"></param>
        /// <param name="iterations"></param>
        /// <returns></returns>
        public static KzUInt512 pbkdf2_hmac_sha512(ReadOnlySpan <byte> password, ReadOnlySpan <byte> salt, int iterations)
        {
            if (iterations < 1)
            {
                throw new ArgumentException();
            }

            var _password = password.ToArray();

            using var inner = new SHA512Managed();
            using var outer = new SHA512Managed();

            var blocksize = 128; // match python hashlib's sha512 blocksize.

            if (_password.Length > blocksize)
            {
                inner.TransformFinalBlock(_password, 0, _password.Length);
                _password = inner.Hash;
                //inner.Initialize();
            }

            if (_password.Length < blocksize)
            {
                Array.Resize(ref _password, blocksize);
            }

            var _trans_36 = new byte[256];
            var _trans_5c = new byte[256];

            for (var i = 0; i < 256; i++)
            {
                _trans_36[i] = (byte)(i ^ 0x36);
                _trans_5c[i] = (byte)(i ^ 0x5c);
            }

            var innerSeed = _password.Select(pb => _trans_36[pb]).ToArray();
            var outerSeed = _password.Select(pb => _trans_5c[pb]).ToArray();

            var hash  = new KzUInt512();
            var xhash = new KzUInt512();

            var data = new byte[salt.Length + 4];

            salt.CopyTo(data);
            var loop = 1;

            loop.AsReadOnlySpan(bigEndian: true).CopyTo(data.AsSpan(salt.Length));
            var dataSpan = data.AsSpan();

            for (var i = 0; i < iterations; i++)
            {
                inner.TransformBlock(innerSeed);
                outer.TransformBlock(outerSeed);
                inner.TransformFinalBlock(dataSpan, hash.Span);
                outer.TransformFinalBlock(hash.Span, hash.Span);
                dataSpan = hash.Span;
                xhash    = i == 0 ? hash : xhash ^ hash;
            }

            return(xhash);
        }
Esempio n. 20
0
        static void Main(string[] args)
        {
            if (args == null || args.Length < 1 || (args[0].ToLower() != "e" && args[0].ToLower() != "d"))
            {
                Console.Error.WriteLine("Usage:");
                Console.Error.WriteLine(" To encrypt: AesCrypt.exe e <file path>");
                Console.Error.WriteLine(" To decrypt: AesCrypt.exe d <file path> <iv> <key>");
                return;
            }

            if (args[0].ToLower() == "e")
            {
                // ENCRYPTION

                if (args.Length < 2)
                {
                    Console.Error.WriteLine("Usage: AesCrypt.exe e <file path>");
                }

                string   fileToEncrypt = args[1];
                FileInfo inpFile       = new FileInfo(fileToEncrypt);
                if (!inpFile.Exists)
                {
                    Console.Error.WriteLine("File does not exist");
                    return;
                }

                byte[] fileName = Encoding.UTF8.GetBytes(inpFile.FullName);

                string rootDir    = Path.GetDirectoryName(fileToEncrypt);
                string randomName = Guid.NewGuid().ToString("N");
                string tempName   = Path.Combine(rootDir, randomName);
                string finalHash;

                if (File.Exists(tempName))
                {
                    Console.Error.WriteLine("ERROR: temporary file exists, wtf how does that even happen");
                    return;
                }

                using (FileStream inp = File.Open(fileToEncrypt, FileMode.Open, FileAccess.Read, FileShare.Read))
                    using (FileStream oup = File.Create(tempName))
                        using (AesManaged enc = new AesManaged())
                        {
                            enc.KeySize = 256;
                            enc.Mode    = CipherMode.CBC;

                            enc.GenerateIV();
                            enc.GenerateKey();

                            SHA512Managed originalHash = new SHA512Managed();
                            originalHash.Initialize();

                            SHA512Managed cryptedHash = new SHA512Managed();
                            using (CryptoStream hashStream = new CryptoStream(oup, cryptedHash, CryptoStreamMode.Write))
                                using (CryptoStream cs = new CryptoStream(hashStream, enc.CreateEncryptor(), CryptoStreamMode.Write))
                                {
                                    // crypted file structure: {name length x2}{full file name}{data length x8}{data}{sha512 hash of data x64}

                                    byte[] lenFileName = BitConverter.GetBytes((ushort)fileName.Length);
                                    cs.Write(lenFileName, 0, lenFileName.Length);

                                    cs.Write(fileName, 0, fileName.Length);

                                    byte[] fileSizeBits = BitConverter.GetBytes(inpFile.Length);
                                    cs.Write(fileSizeBits, 0, fileSizeBits.Length);

                                    byte[] data = new byte[64 * 1024];
                                    int    bytesRead;
                                    long   bytesHashed = 0;
                                    do
                                    {
                                        // pull data from original file
                                        bytesRead = inp.Read(data, 0, data.Length);

                                        // send it to crypted stream
                                        cs.Write(data, 0, bytesRead);

                                        // also hash it for decryption verification purposes
                                        bytesHashed += originalHash.TransformBlock(data, 0, bytesRead, data, 0);
                                    } while (bytesRead > 0);

                                    // write original hash into crypted file so we can verify it after decryption
                                    originalHash.TransformFinalBlock(data, 0, 0);
                                    cs.Write(originalHash.Hash, 0, originalHash.Hash.Length);
                                }

                            finalHash = Base32.ToBase32String(cryptedHash.Hash);

                            string iv  = Convert.ToBase64String(enc.IV);
                            string key = Convert.ToBase64String(enc.Key);

                            Console.Out.WriteLine("{0} {1} {2}", finalHash, iv, key);
                        }

                File.Move(tempName, Path.Combine(rootDir, finalHash));
            }
            else
            {
                // DECRYPTION

                if (args.Length < 4)
                {
                    Console.Error.WriteLine("Usage: AesCrypt.exe d <file path> <iv> <key>");
                    return;
                }

                FileInfo encFile = new FileInfo(args[1]);
                if (!encFile.Exists)
                {
                    Console.Error.WriteLine("File does not exist");
                    return;
                }

                byte[] iv = Convert.FromBase64String(args[2]);
                if (iv == null || iv.Length < 1)
                {
                    Console.Error.WriteLine("ERROR: invalid iv");
                    return;
                }
                byte[] key = Convert.FromBase64String(args[3]);
                if (key == null || key.Length < 1)
                {
                    Console.Error.WriteLine("ERROR: invalid key");
                    return;
                }

                using (FileStream inp = encFile.OpenRead())
                    using (AesManaged aes = new AesManaged())
                    {
                        aes.KeySize = 256;
                        aes.Mode    = CipherMode.CBC;

                        aes.IV  = iv;
                        aes.Key = key;

                        using (CryptoStream cs = new CryptoStream(inp, aes.CreateDecryptor(), CryptoStreamMode.Read))
                        {
                            // crypted file structure: {name length x4}{full file name}{data length x8}{data}{sha512 hash of data x64}

                            byte[] nameLengthBits = new byte[2];
                            if (cs.Read(nameLengthBits, 0, 2) != 2)
                            {
                                Console.Error.WriteLine("ERROR: Failed reading file name size");
                                return;
                            }
                            ushort nameLength = BitConverter.ToUInt16(nameLengthBits, 0);

                            byte[] originalName = new byte[nameLength];
                            if (cs.Read(originalName, 0, nameLength) != nameLength)
                            {
                                Console.Error.WriteLine("ERROR: Failed reading file name");
                                return;
                            }
                            string fileName = Encoding.UTF8.GetString(originalName);

                            byte[] dataLengthBits = new byte[8];
                            if (cs.Read(dataLengthBits, 0, dataLengthBits.Length) != dataLengthBits.Length)
                            {
                                Console.Error.WriteLine("ERROR: Failed reading data length");
                                return;
                            }
                            long dataLength = BitConverter.ToInt64(dataLengthBits, 0);

                            string outputFileName = Path.Combine(Directory.GetCurrentDirectory(), Path.GetFileName(fileName));
                            if (File.Exists(outputFileName))
                            {
                                Console.Error.WriteLine("ERROR: '{0}' already exists, exiting", outputFileName);
                                return;
                            }

                            Console.Out.WriteLine("Decrypting what was originally called '{0}' ({1:N0} bytes)", fileName, dataLength);
                            byte[] decryptedHash;
                            long   totalRead = 0;
                            using (FileStream outputStream = new FileStream(outputFileName, FileMode.CreateNew, FileAccess.Write, FileShare.Read))
                                using (SHA512Managed hasher = new SHA512Managed())
                                {
                                    byte[] buffer         = new byte[ReadBufferSize];
                                    long   bytesRemaining = dataLength;
                                    while (bytesRemaining > 0)
                                    {
                                        int readingThisRound = ReadBufferSize < bytesRemaining ? ReadBufferSize : (int)bytesRemaining;
                                        int bytesRead        = cs.Read(buffer, 0, readingThisRound);
                                        totalRead += bytesRead;

                                        // dump decrypted data to file
                                        outputStream.Write(buffer, 0, bytesRead);

                                        // run it through the grinder for verification later
                                        int hashProgress = hasher.TransformBlock(buffer, 0, bytesRead, buffer, 0);
                                        Debug.Assert(hashProgress == bytesRead, "Hash calculation out of whack with file IO, wtf is going on");

                                        bytesRemaining -= bytesRead;
                                    }

                                    hasher.TransformFinalBlock(buffer, 0, 0);
                                    decryptedHash = hasher.Hash;
                                }

                            byte[] originalHashBits = new byte[64];
                            if (cs.Read(originalHashBits, 0, originalHashBits.Length) != originalHashBits.Length)
                            {
                                Console.Error.WriteLine("ERROR: Failed reading verification hash, encrypted file is corrupted!");
                                return;
                            }

                            if (originalHashBits.SequenceEqual(decryptedHash))
                            {
                                Console.Out.WriteLine("Successfully decrypted '{0}'", outputFileName);
                            }
                            else
                            {
                                Console.Out.WriteLine("Decryption FAIL");
                            }
                        }
                    }
            }
        }
Esempio n. 21
0
	byte[] IHashAlgorithm.GetRunningHash ()
	{
		var copy = new SHA512Managed (this);
		copy.TransformFinalBlock (empty, 0, 0);
		return copy.Hash;
	}