Beispiel #1
0
        public unsafe void Decrypt(Stream input, Stream output)
        {
            if (input == null) throw new ArgumentNullException("input");
            if (output == null) throw new ArgumentNullException("output");

            /*
             * All versions of the scrypt format will start with "scrypt" and
             * have at least 7 bytes of header.
             */
            if (input.Length < 7)
            {
                throw new NoValidScryptBlockException("File really too small");
            }

            var header = new byte[96];
            input.ReadExactly(header, 0, header.Length);

            var marker = header.Take(scryptBytes.Length).ToArray();
            if (!marker.SequenceEqual(scryptBytes))
            {
                throw new NoValidScryptBlockException("No file marker");
            }

            /* Check the format. */
            if (header[6] != 0)
            {
                throw new UnrecognizedFormatVersionException();
            }

            /* We must have at least 128 bytes. */
            if (input.Length < 128)
            {
                throw new NoValidScryptBlockException("File too small");
            }

            var dk = new byte[DERIVED_KEY_SIZE];

            // ReSharper disable once UnusedVariable
            // pDk is useless but C# can't pin without creating a pointer
            fixed (byte* pDk = &dk[0])
            {
                /* Parse the header and generate derived keys. */
                ParseAndCheckHeader(header, dk);

                /* Decrypt data. */
                using (var aesCtr = new ScryptAesCtr(dk.Take(32).ToArray(), 0))
                {
                    aesCtr.EncryptOrDectrypt(input, output);
                }

                /* Verify signature. */
                var hmacKey = new byte[32];
                Array.Copy(dk, 32, hmacKey, 0, 32);
                var hmacSha256 = new HMACSHA256(hmacKey);
                var inputWithoutSignature = new SubsetStream(input, 0, input.Length - 32);
                inputWithoutSignature.Position = 0;
                var computedHmac = hmacSha256.ComputeHash(inputWithoutSignature);
                input.Position = input.Length - 32;
                var hmacInFile = new byte[32];
                input.ReadExactly(hmacInFile, 0, 32);
                if (!hmacInFile.SequenceEqual(computedHmac))
                {
                    throw new NoValidScryptBlockException("Signature don't verify");
                }

                /* Zero sensitive data. */
                for (int i = 0; i < dk.Length; i++)
                {
                    dk[i] = 0;
                }
            }

            /* Success! */
        }
Beispiel #2
0
        public unsafe void Encrypt(Stream input, Stream output)
        {
            if (input == null) throw new ArgumentNullException("input");
            if (output == null) throw new ArgumentNullException("output");

            var dk = new byte[DERIVED_KEY_SIZE];

            // ReSharper disable once UnusedVariable
            // pDk is useless but C# can't pin without creating a pointer
            fixed (byte* pDk = &dk[0])
            {
                /* Generate the header and derived key. */
                byte[] header;
                CreateHeader(out header, dk);

                /* Copy header into output buffer. */
                output.Write(header, 0, header.Length);

                /* Encrypt data. */
                var aesCtr = new ScryptAesCtr(dk.Take(32).ToArray(), 0);
                aesCtr.EncryptOrDectrypt(input, output);

                /* Add signature. */
                var hmacKey = new byte[32];
                Array.Copy(dk, 32, hmacKey, 0, 32);

                var hmacSha256 = new HMACSHA256(hmacKey);
                output.Position = 0;
                var headerHmac = hmacSha256.ComputeHash(output);
                output.Write(headerHmac, 0, 32);

                /* Zero sensitive data. */
                for (int i = 0; i < dk.Length; i++)
                {
                    dk[i] = 0;
                }
            }
        }