public void TestTwofishFileDecryption() { byte[] data = new byte[10000]; new Random().NextBytes(data); // fill random data using (var senderRsa = new RSACryptoServiceProvider()) { var senderPrivateKey = senderRsa.ExportParameters(true); using (var receiverRsa = new RSACryptoServiceProvider()) { var receiverPrivateKey = receiverRsa.ExportParameters(true); var receiverPublicKey = receiverRsa.ExportParameters(false); CryptCombo combo = new CryptCombo(MD5.Create(), new TwofishMachine()); MemoryStream cryptedFileStream = new MemoryStream(); OriginalFile originFile = new OriginalFile(new MemoryStream(data), ".java"); FileCryptor cryptor = new FileCryptor(senderPrivateKey, receiverPublicKey); cryptor.Encrypt(originFile, cryptedFileStream, combo); MemoryStream decryptedStream = new MemoryStream(); EncryptedFile newCryptedFile = EncryptedFileChecker.Parse(cryptedFileStream); FileDecryptor decryptor = new FileDecryptor(receiverPrivateKey); decryptor.Decrypt(newCryptedFile, decryptedStream); Assert.IsTrue(decryptedStream.ToArray().SequenceEqual(data)); } } }
/// <summary> /// Encrypts a file using a combination of an encryption and a hash algorithm. /// </summary> /// <param name="input"><see cref="OriginalFile"/> to be encrypted.</param> /// <param name="output">Output <see cref="Stream"/> where the encrypted file will be written.</param> /// <param name="algs">Combination of an encryption and a hash algorithm.</param> /// <param name="reportProgress">Action used to report progress somewhere.</param> public void Encrypt(OriginalFile input, Stream output, CryptCombo algs, Action <int> reportProgress = null) { BinaryWriter writer = new BinaryWriter(output); // to write to output BinaryReader reader = new BinaryReader(input.FileContent); writer.Seek(0, SeekOrigin.Begin); // write to beginning, this will override if there is something there reader.BaseStream.Position = 0; // read from beginning long numberOfBlocks = input.FileContent.Length / algs.Machine.BlockSize; if (numberOfBlocks * algs.Machine.BlockSize < input.FileContent.Length) { numberOfBlocks++; } var algKey = algs.Machine.Key; var cryptedkey = new RsaMachine(this.ReceiverPublicKey).Encrypt(algKey); byte[] header = new byte[] { }; header = header // we concat here instead of writing directly so we can calculate hash .Concat(Helpers.MagicBytes) .Concat(Encoding.ASCII.GetBytes(algs.Machine.GetSignatureString())) .Concat(Encoding.ASCII.GetBytes(Helpers.GetCodeFromHasher(algs.Hasher))) .Concat(BitConverter.GetBytes(cryptedkey.Length)) .Concat(cryptedkey) .Concat(BitConverter.GetBytes(input.Extension.Length)) .Concat(Encoding.ASCII.GetBytes(input.Extension)) .Concat(BitConverter.GetBytes(numberOfBlocks)) .ToArray(); var contentHashAggregate = algs.Hasher.ComputeHash(header); writer.Write(header); reportProgress?.Invoke(25); byte[] additionalData = algs.Machine.AdditionalData; if (additionalData != null) { contentHashAggregate = algs.Hasher.ComputeHash(contentHashAggregate.Concat(algs.Hasher.ComputeHash(additionalData)).ToArray()); writer.Write(additionalData); } reportProgress?.Invoke(30); for (int i = 0; i < numberOfBlocks; i++) { byte[] buffer = reader.ReadBytes(algs.Machine.BlockSize); byte[] encryptedBlock = algs.Machine.Encrypt(buffer); byte[] encSize = BitConverter.GetBytes(encryptedBlock.Length); byte[] blockToWrite = encSize.Concat(encryptedBlock).ToArray(); contentHashAggregate = algs.Hasher.ComputeHash(contentHashAggregate.Concat(algs.Hasher.ComputeHash(blockToWrite)).ToArray()); writer.Write(blockToWrite); int progress = (int)(((float)i / (float)numberOfBlocks) * 1000.00); reportProgress?.Invoke(progress < 980 ? progress : 980); } byte[] rsaSignature = new RsaMachine(this.SenderPrivateKey).Sign(contentHashAggregate, algs.Hasher); reportProgress?.Invoke(990); writer.Write(rsaSignature.Length); writer.Write(rsaSignature); reportProgress?.Invoke(1000); }
public Encryptor(User receiverUsername, UserInformation currentUser, CryptCombo combo) { this.receiver = receiverUsername; this.currentUser = currentUser; this.combo = combo; }