private static bool VerifyDsaSignature(EncryptedFile file, BinaryReader reader, RSAParameters key)
        {
            var hasher = Helpers.GetHasherFromCode(file.HasherCode);

            reader.BaseStream.Position = 0;

            byte[] header = reader.ReadBytes(file.HeaderLength);
            var    contentHashAggregate = hasher.ComputeHash(header);

            byte[] additionalData = reader.ReadBytes(16);
            contentHashAggregate = hasher.ComputeHash(contentHashAggregate.Concat(hasher.ComputeHash(additionalData)).ToArray());

            for (int i = 0; i < file.NumberOfBlocks; i++)
            {
                byte[] blockSizeArray = reader.ReadBytes(4);
                int    blockSize      = BitConverter.ToInt32(blockSizeArray, 0);
                byte[] block          = reader.ReadBytes(blockSize);
                contentHashAggregate = hasher.ComputeHash(contentHashAggregate.Concat(hasher.ComputeHash(blockSizeArray.Concat(block).ToArray())).ToArray());
            }

            int rsaLength = BitConverter.ToInt32(reader.ReadBytes(4), 0);

            byte[] rsaSignature = reader.ReadBytes(rsaLength);

            return(new RsaMachine(key).CheckSignature(contentHashAggregate, hasher, rsaSignature));
        }
        /// <summary>
        /// This method will parse the <see cref="Stream"/> of the encrypted file.
        /// </summary>
        /// <param name="stream">The <see cref="Stream"/> of the encrypted file.</param>
        /// <returns><see cref="EncryptedFile"/> populated with all the header information required for decryption.</returns>
        public static EncryptedFile Parse(Stream stream)
        {
            BinaryReader  reader = new BinaryReader(stream);
            EncryptedFile file   = new EncryptedFile(reader.BaseStream);

            reader.BaseStream.Position = 0;

            if (!reader.ReadBytes(6).SequenceEqual(Helpers.MagicBytes))
            {
                throw new InvalidFileException();
            }

            file.CryptorCode = Encoding.ASCII.GetString(reader.ReadBytes(Helpers.CryptorCodenameSize));
            if (!file.CryptorCode.Equals(AesMachine.Signature) && !file.CryptorCode.Equals(TDesMachine.Signature) && !file.CryptorCode.Equals(TwofishMachine.Signature))
            {
                throw new UnknownCryptorCodeException(file.CryptorCode);
            }

            file.HasherCode = Encoding.ASCII.GetString(reader.ReadBytes(Helpers.HasherCodenameSize));
            if (!Helpers.IsHasherCodeValid(file.HasherCode))
            {
                throw new UnknownHasherCodeException(file.HasherCode);
            }

            int cryptedKeyLength = BitConverter.ToInt32(reader.ReadBytes(4), 0);

            file.EncryptedKey = reader.ReadBytes(cryptedKeyLength);

            int extLength = BitConverter.ToInt32(reader.ReadBytes(4), 0);

            file.FormatExtension = Encoding.ASCII.GetString(reader.ReadBytes(extLength));

            file.NumberOfBlocks = BitConverter.ToInt64(reader.ReadBytes(8), 0);

            reader.BaseStream.Position += 16;
            for (int i = 0; i < file.NumberOfBlocks + 1; i++)
            {
                int blockSize = BitConverter.ToInt32(reader.ReadBytes(4), 0);
                reader.BaseStream.Position += blockSize;
            }

            if (!(reader.BaseStream.Position == reader.BaseStream.Length))
            {
                throw new InvalidFileException();
            }

            return(file);
        }
Exemple #3
0
        /// <summary>
        /// Decrypts a file.
        /// </summary>
        /// <param name="input"><see cref="EncryptedFile"/> that will be decrypted.</param>
        /// <param name="output">Output <see cref="Stream"/> where the decrypted file will be written.</param>
        /// <param name="reportProgress">Action that is used to report progress of decryption in percentages.</param>
        public void Decrypt(EncryptedFile input, Stream output, Action <int> reportProgress = null)
        {
            BinaryReader reader = new BinaryReader(input.BaseStream);

            reader.BaseStream.Position = input.HeaderLength;
            output.Position            = 0;
            BinaryWriter outputWriter = new BinaryWriter(output);

            byte[] decryptedAlgKey = new RsaMachine(this.Key).Decrypt(input.EncryptedKey);
            reportProgress?.Invoke(35);

            IMachine decryptor = null;

            if (input.CryptorCode == AesMachine.Signature)
            {
                decryptor = new AesMachine(decryptedAlgKey, reader.ReadBytes(16));
            }
            else if (input.CryptorCode == TDesMachine.Signature)
            {
                decryptor = new TDesMachine(decryptedAlgKey, reader.ReadBytes(16));
            }
            else if (input.CryptorCode == TwofishMachine.Signature)
            {
                decryptor = new TwofishMachine(decryptedAlgKey, reader.ReadBytes(16));
            }

            for (int i = 0; i < input.NumberOfBlocks; i++)
            {
                int    currentBlockSize = BitConverter.ToInt32(reader.ReadBytes(4), 0);
                byte[] block            = reader.ReadBytes(currentBlockSize);
                outputWriter.Write(decryptor.Decrypt(block));
                reportProgress?.Invoke((int)(((float)i / (float)input.NumberOfBlocks) * 1000.00));
            }

            reportProgress?.Invoke(1000);
        }
        /// <summary>
        /// This method will verify the signature of the encrypted file.
        /// </summary>
        /// <param name="file">The <see cref="EncryptedFile"/> whose signature will be verified.</param>
        /// <param name="param">Public key of the sender.</param>
        /// <returns>Boolean indicating if the signature is valid.</returns>
        public static bool VerifySignature(EncryptedFile file, RSAParameters param)
        {
            BinaryReader reader = new BinaryReader(file.BaseStream);

            return(VerifyDsaSignature(file, reader, param));
        }