/// <summary> /// 压缩2 /// </summary> /// <param name="str"></param> /// <returns></returns> public static byte[] DeflateByte(byte[] str) { if (str == null) { return null; } //这里要添加库Ionic using (var output = new MemoryStream()) { using ( var compressor = new Ionic.Zlib.DeflateStream( output, Ionic.Zlib.CompressionMode.Compress, Ionic.Zlib.CompressionLevel.BestSpeed)) { compressor.Write(str, 0, str.Length); } return output.ToArray(); } //当然如果使用GZIP压缩的话,只需要将 //new Ionic.Zlib.DeflateStream( 改为 //new Ionic.Zlib.GZipStream(,然后 //actContext.Response.Content.Headers.Add("Content-encoding", "deflate");改为 //actContext.Response.Content.Headers.Add("Content-encoding", "gzip"); //就可以了,经本人测试, //Deflate压缩要比GZIP压缩后的代码要小,所以推荐使用Deflate压缩 }
/// <summary> /// Gets the response stream with HTTP decompression. /// </summary> /// <param name="response">The response.</param> /// <returns></returns> public static Stream GetResponseStreamWithHttpDecompression(this WebResponse response) { var stream = response.GetResponseStream(); var encoding = response.Headers["Content-Encoding"]; if (encoding != null && encoding.Contains("gzip")) stream = new Ionic.Zlib.GZipStream(stream, Ionic.Zlib.CompressionMode.Decompress); else if (encoding != null && encoding.Contains("deflate")) stream = new Ionic.Zlib.DeflateStream(stream, Ionic.Zlib.CompressionMode.Decompress); return stream; }
public static byte[] CompressDeflate(byte[] bytes) { using (MemoryStream ms = new MemoryStream()) { using (Ionic.Zlib.DeflateStream zip = new Ionic.Zlib.DeflateStream(ms, Ionic.Zlib.CompressionMode.Compress, true)) { zip.Write(bytes, 0, bytes.Length); } return ms.ToArray(); } }
public static byte[] CompressDeflate(string ResponseData, Encoding e) { Byte[] bytes = e.GetBytes(ResponseData); using (MemoryStream ms = new MemoryStream()) { using (Ionic.Zlib.DeflateStream zip = new Ionic.Zlib.DeflateStream(ms, Ionic.Zlib.CompressionMode.Compress, true)) { zip.Write(bytes, 0, bytes.Length); } return ms.ToArray(); } }
public static byte[] DeflateByte(byte[] str) { if (str == null) { return null; } using (var output = new MemoryStream()) { using (var compressor = new Ionic.Zlib.DeflateStream(output, Ionic.Zlib.CompressionMode.Compress, Ionic.Zlib.CompressionLevel.BestSpeed)) { compressor.Write(str, 0, str.Length); } return output.ToArray(); } }
public static async Task<byte[]> CompressionByteAsync(byte[] str, CompressionType compressionType) { if (str == null) { return null; } using (var output = new MemoryStream()) { switch (compressionType) { case CompressionType.Deflate: using ( var compressor = new Ionic.Zlib.DeflateStream( output, Ionic.Zlib.CompressionMode.Compress, Ionic.Zlib.CompressionLevel.BestSpeed)) { await compressor.WriteAsync(str, 0, str.Length); //compressor.Write(str, 0, str.Length); } break; case CompressionType.GZip: using ( var compressor = new Ionic.Zlib.GZipStream( output, Ionic.Zlib.CompressionMode.Compress, Ionic.Zlib.CompressionLevel.BestSpeed)) { await compressor.WriteAsync(str, 0, str.Length); //compressor.Write(str, 0, str.Length); } break; case CompressionType.Zlib: using ( var compressor = new Ionic.Zlib.ZlibStream( output, Ionic.Zlib.CompressionMode.Compress, Ionic.Zlib.CompressionLevel.BestSpeed)) { await compressor.WriteAsync(str, 0, str.Length); //compressor.Write(str, 0, str.Length); } break; } return output.ToArray(); } }
public static byte[] DecompressDeflate(Stream input) { using (Ionic.Zlib.DeflateStream decompressor = new Ionic.Zlib.DeflateStream(input, Ionic.Zlib.CompressionMode.Decompress)) { int read = 0; var buffer = new byte[BUFFER_SIZE]; using (MemoryStream output = new MemoryStream()) { while ((read = decompressor.Read(buffer, 0, buffer.Length)) > 0) { output.Write(buffer, 0, read); } return output.ToArray(); } } }
public static byte[] DeflateByte(byte[] str) { if (str == null) { return(null); } using (var output = new MemoryStream()) { using ( var compressor = new Ionic.Zlib.DeflateStream( output, Ionic.Zlib.CompressionMode.Compress, Ionic.Zlib.CompressionLevel.BestSpeed)) { compressor.Write(str, 0, str.Length); } return(output.ToArray()); } }
/// <summary> /// Compress bytes using zlib compression /// </summary> /// <param name="decompressedBytes"></param> /// <param name="compressedBytes"></param> /// <returns></returns> public static byte[] CompressZLib(byte[] decompressedBytes, out int compressedBytes) { var msDecompressed = new MemoryStream(decompressedBytes); // We must skip the first two bytes // See http://george.chiramattel.com/blog/2007/09/deflatestream-block-length-does-not-match.html // EAT the zlib headers, the rest is a normal 'deflate'd stream //msDecompressed.ReadByte(); //msDecompressed.ReadByte(); //var msInflated = new MemoryStream((int)(msCompressed.Length * 2)); //var newBytes = new byte[msCompressed.Length * 2]; var newBytes = new byte[decompressedBytes.Length]; // TODO: Add the zlib headers to the data.... // TODO: Also need the Adler32 Checksum at the end... var deflate2 = new Ionic.Zlib.DeflateStream(msDecompressed, Ionic.Zlib.CompressionMode.Compress); deflate2.Read(newBytes, 0, decompressedBytes.Length); // The last 32 bits (4 bytes) are supposed to be an Adler-32 checksum. Might need to remove them as well. using (var deflater = new DeflateStream(msDecompressed, CompressionMode.Compress)) { compressedBytes = deflater.Read(newBytes, 0, decompressedBytes.Length) + 2; //while (inflater.CanRead) //{ // var readBytes = new byte[4095]; // // Should be able to change to just this. // var bytesRead = inflater.Read(readBytes, 0, readBytes.Length); // if (bytesRead != 0) // { // msInflated.Write(readBytes, 0, bytesRead); // } //} } //newBytes = new byte[msInflated.Length]; //msInflated.Read(newBytes, 0, (int)msInflated.Length); return(newBytes); }
public static void CompressByte(byte[] sourceByte, out byte[] dataByte) { dataByte = null; Ionic.Zlib.DeflateStream compressByte = null; try{ using (MemoryStream ms = new MemoryStream()) { using (compressByte = new Ionic.Zlib.DeflateStream(ms, Ionic.Zlib.CompressionMode.Compress, true)) { compressByte.Write(sourceByte, 0, sourceByte.Length); } dataByte = ms.ToArray(); } }catch (ApplicationException ex) { Console.WriteLine("compress byte is exception !!"); }finally{ if (compressByte != null) { compressByte.Close(); } } }
public static byte[] DecryptData(ref byte[] data, string password, RijndaelManaged aes) { int len = 0; byte[] buffer = new byte[aes.BlockSize / 8]; byte[] salt = new byte[aes.KeySize / 8]; byte[] iv = new byte[aes.BlockSize / 8]; byte[] decryptedData; using (MemoryStream inms = new MemoryStream(data)) { inms.Read(salt, 0, salt.Length); inms.Read(iv, 0, iv.Length); aes.IV = iv; Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(password, salt, 1000); aes.Key = deriveBytes.GetBytes(salt.Length); //Decryption interface. using (ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV)) using (CryptoStream cse = new CryptoStream(inms, decryptor, CryptoStreamMode.Read)) using (MemoryStream outms = new MemoryStream()) { //using (DeflateStream ds = new DeflateStream(cse, CompressionMode.Decompress, false)) using (Ionic.Zlib.DeflateStream ds = new Ionic.Zlib.DeflateStream(cse, Ionic.Zlib.CompressionMode.Decompress)) { while ((len = ds.Read(buffer, 0, buffer.Length)) > 0) { outms.Write(buffer, 0, len); } } decryptedData = outms.ToArray(); } return(decryptedData); } }
private Stream MaybeApplyCompression(Stream s, long streamLength) { if (_CompressionMethod == 0x08 && CompressionLevel != Ionic.Zlib.CompressionLevel.None) { #if !NETCF // ParallelDeflateThreshold == 0 means ALWAYS use parallel deflate // ParallelDeflateThreshold == -1L means NEVER use parallel deflate // Other values specify the actual threshold. if (_container.ParallelDeflateThreshold == 0L || (streamLength > _container.ParallelDeflateThreshold && _container.ParallelDeflateThreshold > 0L)) { // This is sort of hacky. // // It's expensive to create a ParallelDeflateOutputStream, because // of the large memory buffers. But the class is unlike most Stream // classes in that it can be re-used, so the caller can compress // multiple files with it, one file at a time. The key is to call // Reset() on it, in between uses. // // The ParallelDeflateOutputStream is attached to the container // itself - there is just one for the entire ZipFile or // ZipOutputStream. So it gets created once, per save, and then // re-used many times. // // This approach will break when we go to a "parallel save" // approach, where multiple entries within the zip file are being // compressed and saved at the same time. But for now it's ok. // // instantiate the ParallelDeflateOutputStream if (_container.ParallelDeflater == null) { _container.ParallelDeflater = new Ionic.Zlib.ParallelDeflateOutputStream(s, CompressionLevel, _container.Strategy, true); // can set the codec buffer size only before the first call to Write(). if (_container.CodecBufferSize > 0) _container.ParallelDeflater.BufferSize = _container.CodecBufferSize; if (_container.ParallelDeflateMaxBufferPairs > 0) _container.ParallelDeflater.MaxBufferPairs = _container.ParallelDeflateMaxBufferPairs; } // reset it with the new stream Ionic.Zlib.ParallelDeflateOutputStream o1 = _container.ParallelDeflater; o1.Reset(s); return o1; } #endif var o = new Ionic.Zlib.DeflateStream(s, Ionic.Zlib.CompressionMode.Compress, CompressionLevel, true); if (_container.CodecBufferSize > 0) o.BufferSize = _container.CodecBufferSize; o.Strategy = _container.Strategy; return o; } #if BZIP if (_CompressionMethod == 0x0c) { #if !NETCF if (_container.ParallelDeflateThreshold == 0L || (streamLength > _container.ParallelDeflateThreshold && _container.ParallelDeflateThreshold > 0L)) { var o1 = new Ionic.BZip2.ParallelBZip2OutputStream(s, true); return o1; } #endif var o = new Ionic.BZip2.BZip2OutputStream(s, true); return o; } #endif return s; }
/// <summary> /// The encrypted file by AES (exactly Rijndael) to the original file or folder by user's password. /// ユーザーが設定したパスワードによって、AES(正確にはRijndael)によって暗号化されたファイルを /// 元のファイル、またはフォルダーに復号して戻す。 /// </summary> /// <param name="FilePath">File path or directory path is encrypted</param> /// <param name="OutFileDir">The directory of outputing encryption file.</param> /// <param name="Password">Encription password string</param> /// <returns>bool true: Success, false: Failed</returns> public bool Decrypt( object sender, DoWorkEventArgs e, string FilePath, string OutDirPath, string Password, byte[] PasswordBinary, Action<int, string> dialog) { BackgroundWorker worker = sender as BackgroundWorker; worker.WorkerSupportsCancellation = true; //----------------------------------- // Header data is starting. // Progress event handler ArrayList MessageList = new ArrayList(); MessageList.Add(READY_FOR_DECRYPT); MessageList.Add(Path.GetFileName(FilePath)); worker.ReportProgress(0, MessageList); int len = 0; byte[] byteArray; List<string> FileList = new List<string>(); Dictionary<int, FileListData> dic = new Dictionary<int, FileListData>(); if (_TokenStr.Trim() == "_AttacheCaseData") { // Atc data } else if (_TokenStr.Trim() == "_Atc_Broken_Data") { // Atc file is broken e.Result = new FileDecryptReturnVal(ATC_BROKEN_DATA, FilePath); return (false); } else { // not AttacheCase data e.Result = new FileDecryptReturnVal(NOT_ATC_DATA, FilePath); return(false); } Rfc2898DeriveBytes deriveBytes; if (PasswordBinary == null) { deriveBytes = new Rfc2898DeriveBytes(Password, _salt, 1000); } else { deriveBytes = new Rfc2898DeriveBytes(PasswordBinary, _salt, 1000); } byte[] key = deriveBytes.GetBytes(32); byte[] iv = deriveBytes.GetBytes(32); using (FileStream fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { if (fs.Length < 32) { // not AttacheCase data e.Result = new FileDecryptReturnVal(NOT_ATC_DATA, FilePath); return (false); } else { if (_ExeOutSize > 0) { // self-executable file fs.Seek(_ExeOutSize + 36, SeekOrigin.Begin); } else { fs.Seek(36, SeekOrigin.Begin); } } try { // The Header of MemoryStream is encrypted using (Rijndael aes = new RijndaelManaged()) { aes.BlockSize = 256; // BlockSize = 32 bytes aes.KeySize = 256; // KeySize = 32 bytes aes.Mode = CipherMode.CBC; // CBC mode aes.Padding = PaddingMode.Zeros; // Padding mode is "ZEROS". aes.Key = key; aes.IV = iv; // Decryption interface. ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV); using (CryptoStream cse = new CryptoStream(fs, decryptor, CryptoStreamMode.Read)) { using (MemoryStream ms = new MemoryStream()) { byteArray = new byte[_AtcHeaderSize]; len = cse.Read(byteArray, 0, _AtcHeaderSize); ms.Write(byteArray, 0, _AtcHeaderSize); #if (DEBUG) //string AppDirPath = Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath); string DesktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); string TempFilePath = Path.Combine(DesktopPath, "decrypt_header.txt"); using (StreamWriter sw = new StreamWriter(TempFilePath, false, Encoding.UTF8)) { sw.Write(Encoding.UTF8.GetString(byteArray)); } #endif // Check Password Token if (Encoding.UTF8.GetString(byteArray).IndexOf(AtC_ENCRYPTED_TOKEN) > -1) { // Decryption is succeeded. } else { // Token is not match ( Password is not correct ) e.Result = new FileDecryptReturnVal(PASSWORD_TOKEN_NOT_FOUND, FilePath); return (false); } ms.Position = 0; var sr = new StreamReader(ms, Encoding.UTF8); string line; while ((line = sr.ReadLine()) != null) { if (Regex.IsMatch(line, @"^[0-9]+:")) { FileList.Add(line); } } }//end using (MemoryStream ms = new MemoryStream()) }//end using (CryptoStream cse = new CryptoStream(fs, decryptor, CryptoStreamMode.Read)); }//end using (Rijndael aes = new RijndaelManaged()); } catch { e.Result = new FileDecryptReturnVal(ERROR_UNEXPECTED, ""); return (false); } }//end using (FileStream fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read)); //---------------------------------------------------------------------- // Make a list array of the information for each file //---------------------------------------------------------------------- _TotalFileSize = 0; string ParentFolder = ""; bool fDirectoryTraversal = false; string InvalidFilePath = ""; FileList.ForEach(delegate (string OutputLine) { int LastWriteDate, CreateDate; double LastWriteTime, CreateTime; DateTime LastWriteDateTime = DateTime.Parse("0001/01/01"); DateTime CreationDateTime = DateTime.Parse("0001/01/01"); FileListData fd = new FileListData(); string[] OutputFileData = OutputLine.Split('\t'); //----------------------------------- // File number // int FileNum; // e.g.) // 0:sample.txt[\t]49657[\t]32[\t]736194[\t]39585.875[\t]736194[\t]30186.782[\t]5f43aa1fed05350f34c2fabb7ed938457b2497f2b54a50415b51882f333b8ae1 string[] FilePathSplits = OutputFileData[0].Split(':'); if (Int32.TryParse(FilePathSplits[0], out FileNum) == false) { FileNum = -1; } //----------------------------------- // ディレクトリ・トラバーサル対策 // Directory traversal countermeasures if (OutputFileData[0].IndexOf(@"..\") >= 0) { fDirectoryTraversal = true; InvalidFilePath = OutputFileData[0]; } //----------------------------------- // Parent folder is not created. // if (_fNoParentFolder == true) { if (FileNum == 0) { if(FilePathSplits.Length > 2) // ルートディレクトリ(ex. 0:G:\Test.txt) { ParentFolder = FilePathSplits[2]; } else { ParentFolder = FilePathSplits[1]; } } else { if (FilePathSplits.Length > 2) // ルートディレクトリ { StringBuilder sb = new StringBuilder(FilePathSplits[2]); len = ParentFolder.Length; FilePathSplits[2] = sb.Replace(ParentFolder, "", 0, len).ToString(); } else { StringBuilder sb = new StringBuilder(FilePathSplits[1]); len = ParentFolder.Length; FilePathSplits[1] = sb.Replace(ParentFolder, "", 0, len).ToString(); } } } //----------------------------------- // File path // string OutFilePath = ""; if (_fSalvageIntoSameDirectory == true) // Salvage mode? { OutFilePath = Path.Combine(OutDirPath, Path.GetFileName(FilePathSplits[1])); } else { if(FilePathSplits.Length > 2) { OutFilePath = Path.Combine(OutDirPath, FilePathSplits[2]); } else { OutFilePath = Path.Combine(OutDirPath, FilePathSplits[1]); } } fd.FilePath = OutFilePath; //----------------------------------- // File size if (Int64.TryParse(OutputFileData[1], out fd.FileSize) == false) { fd.FileSize = -1; } else { _TotalFileSize += fd.FileSize; } //----------------------------------- // File attribute if (Int32.TryParse(OutputFileData[2], out fd.FileAttribute) == false) { fd.FileAttribute = -1; } /* * TTimeStamp = record * Time: Integer; { Number of milliseconds since midnight } * Date: Integer; { One plus number of days since 1/1/0001 } * end; */ //----------------------------------- // Last update timestamp if (_fSameTimeStamp == false && Int32.TryParse(OutputFileData[3], out LastWriteDate) == true) { LastWriteDateTime = LastWriteDateTime.AddDays(LastWriteDate); // Add days } else { LastWriteDateTime = DateTime.Now; } if (_fSameTimeStamp == false && Double.TryParse(OutputFileData[4], out LastWriteTime) == true) { LastWriteDateTime = LastWriteDateTime.AddSeconds(LastWriteTime); // Add seconds } else { LastWriteDateTime = DateTime.Now; } fd.LastWriteDateTime = LastWriteDateTime; //----------------------------------- // Create datetime if (_fSameTimeStamp == false && Int32.TryParse(OutputFileData[5], out CreateDate) == true) { CreationDateTime = CreationDateTime.AddDays(CreateDate); } else { CreationDateTime = DateTime.Now; } if (_fSameTimeStamp == false && Double.TryParse(OutputFileData[6], out CreateTime) == true) { CreationDateTime = CreationDateTime.AddSeconds(CreateTime); } else { CreationDateTime = DateTime.Now; } fd.CreationDateTime = CreationDateTime; //----------------------------------- // SHA-256 hash if (OutputFileData.Length > 7) { fd.Hash = OutputFileData[7]; } //----------------------------------- // Insert to 'Key-Value' type array data. dic.Add(FileNum, fd); }); // Directory traversal countermeasures if (fDirectoryTraversal == true) { e.Result = new FileDecryptReturnVal(INVALID_FILE_PATH, InvalidFilePath); return(false); } //---------------------------------------------------------------------- // Check the disk space //---------------------------------------------------------------------- string RootDriveLetter = Path.GetPathRoot(OutDirPath).Substring(0, 1); if (RootDriveLetter == "\\") { // Network } else { DriveInfo drive = new DriveInfo(RootDriveLetter); DriveType driveType = drive.DriveType; switch (driveType) { case DriveType.CDRom: case DriveType.NoRootDirectory: case DriveType.Unknown: break; case DriveType.Fixed: // Local Drive case DriveType.Network: // Mapped Drive case DriveType.Ram: // Ram Drive case DriveType.Removable: // Usually a USB Drive // The drive is not available, or not enough free space. if (drive.IsReady == false || drive.AvailableFreeSpace < _TotalFileSize) { e.Result = new FileDecryptReturnVal(NO_DISK_SPACE, drive.ToString(), _TotalFileSize, drive.AvailableFreeSpace); return (false); } break; } } //----------------------------------- // Decrypt file main data. //----------------------------------- try { using (FileStream fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { //----------------------------------- // Adjust the header data in 32 bytes int mod = _AtcHeaderSize % 32; if (_fExecutableType == true) { fs.Seek(_ExeOutSize + 36 + _AtcHeaderSize + 32 - mod, SeekOrigin.Begin); } else { fs.Seek(36 + _AtcHeaderSize + 32 - mod, SeekOrigin.Begin); } //----------------------------------- // Decyption using (Rijndael aes = new RijndaelManaged()) { aes.BlockSize = 256; // BlockSize = 32bytes aes.KeySize = 256; // KeySize = 32bytes aes.Mode = CipherMode.CBC; // CBC mode aes.Padding = PaddingMode.Zeros; // Padding mode aes.Key = key; aes.IV = iv; #if (DEBUG) //System.Windows.Forms.MessageBox.Show("dic.Count: " + dic.Count); #endif //Decryption interface. ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV); using (CryptoStream cse = new CryptoStream(fs, decryptor, CryptoStreamMode.Read)) { using (Ionic.Zlib.DeflateStream ds = new Ionic.Zlib.DeflateStream(cse, Ionic.Zlib.CompressionMode.Decompress)) { /* public struct FileListData { public string FilePath; public Int64 FileSize; public int FileAttribute; public DateTime LastWriteDateTime; public DateTime CreationDateTime; public string Sha256String; } */ FileStream outfs = null; Int64 FileSize = 0; int FileIndex = 0; bool fSkip = false; if (_fNoParentFolder == true) { if (dic[0].FilePath.EndsWith("\\") == true) { FileIndex = 1; // Ignore parent folder. } } //---------------------------------------------------------------------- byteArray = new byte[BUFFER_SIZE]; //while ((len = ds.Read(byteArray, 0, BUFFER_SIZE)) > 0) while(true) { if (_AppVersion < 3013) { len = cse.Read(byteArray, 0, BUFFER_SIZE); } else { len = ds.Read(byteArray, 0, BUFFER_SIZE); } // 末尾の0バイトファイル、またはフォルダ生成対策 if (len == 0) len = 1; int buffer_size = len; while (len > 0) { //---------------------------------------------------------------------- // 書き込み中のファイルまたはフォルダが無い場合は作る // Create them if there is no writing file or folder. //---------------------------------------------------------------------- if (outfs == null) { //----------------------------------- // Create file or dirctories. if (dic.ContainsKey(FileIndex) == false) { if (FileIndex > dic.Count - 1) { e.Result = new FileDecryptReturnVal(DECRYPT_SUCCEEDED); return (true); } else { e.Result = new FileDecryptReturnVal(FILE_INDEX_NOT_FOUND, FileIndex); return (false); } } else { //----------------------------------- // Create directory //----------------------------------- if (dic[FileIndex].FilePath.EndsWith("\\") == true) { string path = Path.Combine(OutDirPath, dic[FileIndex].FilePath); DirectoryInfo di = new DirectoryInfo(path); // File already exists. if (Directory.Exists(path) == true) { // Temporary option for overwriting // private const int USER_CANCELED = -1; // private const int OVERWRITE = 1; // private const int OVERWRITE_ALL = 2; // private const int KEEP_NEWER = 3; // private const int KEEP_NEWER_ALL = 4; // private const int SKIP = 5; // private const int SKIP_ALL = 6; if (_TempOverWriteOption == OVERWRITE_ALL) { // Overwrite ( New create ) } else if (_TempOverWriteOption == SKIP_ALL) { fSkip = true; } else if (_TempOverWriteOption == KEEP_NEWER_ALL) { if (di.LastWriteTime > dic[FileIndex].LastWriteDateTime) { fSkip = true; // old directory } } else { // Show dialog of comfirming to overwrite. dialog(0, path); // Cancel if (_TempOverWriteOption == USER_CANCELED) { e.Result = new FileDecryptReturnVal(USER_CANCELED); return (false); } else if (_TempOverWriteOption == OVERWRITE || _TempOverWriteOption == OVERWRITE_ALL) { // Overwrite ( New create ) } // Skip, or Skip All else if (_TempOverWriteOption == SKIP_ALL) { fSkip = true; e.Result = new FileDecryptReturnVal(DECRYPT_SUCCEEDED); return (true); } else if (_TempOverWriteOption == SKIP) { fSkip = true; } else if (_TempOverWriteOption == KEEP_NEWER || _TempOverWriteOption == KEEP_NEWER_ALL) { // New file? if (di.LastWriteTime > dic[FileIndex].LastWriteDateTime) { fSkip = true; } } } if ( fSkip == false) { //隠し属性を削除する di.Attributes &= ~FileAttributes.Hidden; //読み取り専用を削除 di.Attributes &= ~FileAttributes.ReadOnly; } //すべての属性を解除 //File.SetAttributes(path, FileAttributes.Normal); } // end if ( Directory.Exists ) Directory.CreateDirectory(dic[FileIndex].FilePath); _OutputFileList.Add(dic[FileIndex].FilePath); FileSize = 0; FileIndex++; if (FileIndex > dic.Count - 1) { e.Result = new FileDecryptReturnVal(DECRYPT_SUCCEEDED); return (true); } continue; } //----------------------------------- // Create file //----------------------------------- else { string path = Path.Combine(OutDirPath, dic[FileIndex].FilePath); FileInfo fi = new FileInfo(path); // File already exists. if (File.Exists(path) == true) { // Salvage Data Mode if (_fSalvageIntoSameDirectory == true) { int SerialNum = 0; while (File.Exists(path) == true) { path = getFileNameWithSerialNumber(path, SerialNum); SerialNum++; } } else { // Temporary option for overwriting // private const int USER_CANCELED = -1; // private const int OVERWRITE = 1; // private const int OVERWRITE_ALL = 2; // private const int KEEP_NEWER = 3; // private const int KEEP_NEWER_ALL = 4; // private const int SKIP = 5; // private const int SKIP_ALL = 6; if (_TempOverWriteOption == OVERWRITE_ALL) { // Overwrite ( New create ) } else if (_TempOverWriteOption == SKIP_ALL) { fSkip = true; } else if (_TempOverWriteOption == KEEP_NEWER_ALL) { if (fi.LastWriteTime > dic[FileIndex].LastWriteDateTime) { fSkip = true; } } else { // Show dialog of comfirming to overwrite. dialog(0, path); // Cancel if (_TempOverWriteOption == USER_CANCELED) { e.Result = new FileDecryptReturnVal(USER_CANCELED); return (false); } else if (_TempOverWriteOption == OVERWRITE || _TempOverWriteOption == OVERWRITE_ALL) { // Overwrite ( New create ) } // Skip, or Skip All else if (_TempOverWriteOption == SKIP || _TempOverWriteOption == SKIP_ALL) { fSkip = true; } else if (_TempOverWriteOption == KEEP_NEWER || _TempOverWriteOption == KEEP_NEWER_ALL) { // New file? if (fi.LastWriteTime > dic[FileIndex].LastWriteDateTime) { fSkip = true; // old directory } } } if (fSkip == false) { //隠し属性を削除する //fi.Attributes &= ~FileAttributes.Hidden; //読み取り専用を削除 //fi.Attributes &= ~FileAttributes.ReadOnly; //すべての属性を解除 File.SetAttributes(path, FileAttributes.Normal); } } }// end if ( File.Exists ); // Salvage data mode // サルベージ・モード if (_fSalvageToCreateParentFolderOneByOne == true) { // Decrypt one by one while creating the parent folder. Directory.CreateDirectory(Path.GetDirectoryName(path)); } if ( fSkip == true) { // Not create file } else { outfs = new FileStream(path, FileMode.Create, FileAccess.Write); } _OutputFileList.Add(path); FileSize = 0; } } }// end if (outfs == null); //---------------------------------------------------------------------- // Write data //---------------------------------------------------------------------- if (FileSize + len < (Int64)dic[FileIndex].FileSize) { if (outfs != null || fSkip == true) { // まだまだ書き込める // can write more if (fSkip == false) { outfs.Write(byteArray, buffer_size - len, len); } FileSize += len; _TotalSize += len; len = 0; } } else { // ファイルの境界を超えて読み込んでいる // Reading beyond file boundaries int rest = (int)(dic[FileIndex].FileSize - FileSize); if (fSkip == false) { // 書き込み完了 // Write completed outfs.Write(byteArray, buffer_size - len, rest); } _TotalSize += rest; len -= rest; if (outfs != null) { // 生成したファイルを閉じる // File close outfs.Close(); outfs = null; } //---------------------------------------------------------------------- // ファイル属性の復元 // Restore file attributes if (fSkip == false) { FileInfo fi = new FileInfo(dic[FileIndex].FilePath); // タイムスタンプの復元 // Restore the timestamp of a file fi.CreationTime = (DateTime)dic[FileIndex].CreationDateTime; fi.LastWriteTime = (DateTime)dic[FileIndex].LastWriteDateTime; // ファイル属性の復元 // Restore file attribute. fi.Attributes = (FileAttributes)dic[FileIndex].FileAttribute; // ハッシュ値のチェック // Check the hash of a file string hash = GetSha256HashFromFile(dic[FileIndex].FilePath); if (hash != dic[FileIndex].Hash.ToString()) { e.Result = new FileDecryptReturnVal(NOT_CORRECT_HASH_VALUE, dic[FileIndex].FilePath); return (false); } } FileSize = 0; FileIndex++; fSkip = false; if (FileIndex > dic.Count - 1) { e.Result = new FileDecryptReturnVal(DECRYPT_SUCCEEDED); return (true); } } //---------------------------------------------------------------------- //進捗の表示 string MessageText = ""; if (_TotalNumberOfFiles > 1) { MessageText = FilePath + " ( " + _NumberOfFiles.ToString() + "/" + _TotalNumberOfFiles.ToString() + " files" + " )"; } else { MessageText = FilePath; } MessageList = new ArrayList(); MessageList.Add(DECRYPTING); MessageList.Add(MessageText); float percent = ((float)_TotalSize / _TotalFileSize); worker.ReportProgress((int)(percent * 10000), MessageList); // User cancel if (worker.CancellationPending == true) { if (outfs != null) { outfs.Close(); outfs = null; } e.Cancel = true; return (false); } }// end while(len > 0); }// end while ((len = ds.Read(byteArray, 0, BUFFER_SIZE)) > 0); }// end using (DeflateStream ds = new DeflateStream(cse, CompressionMode.Decompress)); }// end using (CryptoStream cse = new CryptoStream(fs, decryptor, CryptoStreamMode.Read)); }// end using (Rijndael aes = new RijndaelManaged()); }// end using (FileStream fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read)); } catch (Exception ex) { #if (DEBUG) System.Windows.Forms.MessageBox.Show("Exception!"); #endif System.Windows.Forms.MessageBox.Show(ex.Message); e.Result = new FileDecryptReturnVal(ERROR_UNEXPECTED); return (false); } e.Result = new FileDecryptReturnVal(DECRYPT_SUCCEEDED); return (true); }
public DeflateHttpContent(Stream stream) { m_stream = new Ionic.Zlib.DeflateStream(stream, Ionic.Zlib.CompressionMode.Decompress); }
/// <summary> /// Multiple files or directories is encrypted by AES (exactly Rijndael) to use password string. /// 複数のファイル、またはディレクトリをAES(正確にはRijndael)を使って指定のパスワードで暗号化する /// </summary> /// <param name="FilePath">File path or directory path is encrypted</param> /// <param name="OutFilePath">Output encryption file name</param> /// <param name="Password">Encription password string</param> /// <returns>Encryption success(true) or failed(false)</returns> public Tuple<bool, int> Encrypt( object sender, DoWorkEventArgs e, string[] FilePaths, string OutFilePath, string Password, byte[] PasswordBinary, string NewArchiveName) { byte[] bufferPassword; byte[] bufferKey = new byte[32]; _AtcFilePath = OutFilePath; BackgroundWorker worker = sender as BackgroundWorker; //----------------------------------- // Header data is starting. // Progress event handler ArrayList MessageList = new ArrayList(); MessageList.Add(READY_FOR_ENCRYPT); MessageList.Add(Path.GetFileName(OutFilePath)); worker.ReportProgress(0, MessageList); _FileList = new List<string>(); byte[] byteArray = null; using (FileStream outfs = new FileStream(OutFilePath, FileMode.Create, FileAccess.Write)) { // 自己実行形式ファイル(Self-executable file) if (_fExecutable == true) { ExeOutFileSize = rawData.Length; outfs.Write(rawData, 0, (int)ExeOutFileSize); } _StartPos = outfs.Seek(0, SeekOrigin.End); byteArray = new byte[16]; // Plain text header byteArray = BitConverter.GetBytes(DATA_SUB_VERSION); outfs.Write(byteArray, 0, 1); byteArray = null; byteArray = BitConverter.GetBytes(RESERVED_DATA); outfs.Write(byteArray, 0, 1); byteArray = null; byteArray = BitConverter.GetBytes(charMissTypeLimits); outfs.Write(byteArray, 0, 1); byteArray = null; byteArray = BitConverter.GetBytes(fBrocken); outfs.Write(byteArray, 0, 1); byteArray = null; byteArray =Encoding.ASCII.GetBytes(STRING_TOKEN_NORMAL); outfs.Write(byteArray, 0, 16); byteArray = null; byteArray = BitConverter.GetBytes(DATA_FILE_VERSION); outfs.Write(byteArray, 0, 4); byteArray = null; byteArray = BitConverter.GetBytes(TYPE_ALGORISM); outfs.Write(byteArray, 0, 4); // Reserve cipher text header size after encrypting. byteArray = null; byteArray = BitConverter.GetBytes(_AtcHeaderSize); outfs.Write(byteArray, 0, 4); // Cipher text header. using (MemoryStream ms = new MemoryStream()) { byteArray =Encoding.ASCII.GetBytes("Passcode:AttacheCase\n"); ms.Write(byteArray, 0, byteArray.Length); DateTime dt = DateTime.Now; byteArray = Encoding.ASCII.GetBytes("LastDateTime:" + dt.ToString("yyyy/MM/dd HH:mm:ss\n")); ms.Write(byteArray, 0, byteArray.Length); int FileNumber = 0; string ParentPath; ArrayList FileInfoList = new ArrayList(); //---------------------------------------------------------------------- // Put together files in one ( Save as the name ). // 複数ファイルを一つにまとめる(ファイルに名前をつけて保存) if (NewArchiveName != "") { // Now time DateTime dtNow = new DateTime(); FileInfoList.Add("Fn_0:" + // File number NewArchiveName + "\\\t" + // File name "0" + "\t" + // File size "16" + "\t" + // File attribute dtNow.Date.Subtract(new DateTime(1, 1, 1)).TotalDays + "\t" + // Last write date dtNow.TimeOfDay.TotalSeconds + "\t" + // Last write time dtNow.Date.Subtract(new DateTime(1, 1, 1)).TotalDays + "\t" + // Creation date dtNow.TimeOfDay.TotalSeconds); // Creation time FileNumber++; } //---------------------------------------------------------------------- // When encrypt multiple files // 複数のファイルを暗号化する場合 foreach (string FilePath in FilePaths) { ParentPath = Path.GetDirectoryName(FilePath) + "\\"; if ((worker.CancellationPending == true)) { e.Cancel = true; return Tuple.Create(false, USER_CANCELED); } //---------------------------------------------------------------------- // 暗号化リストを生成(ファイル) // Create file to encrypt list ( File ) //---------------------------------------------------------------------- if (File.Exists(FilePath) == true) { ArrayList Item = GetFileInfo(ParentPath, FilePath); FileInfoList.Add("Fn_" + FileNumber.ToString() + ":" + // File number //Item[0] + "\t" + // TypeFlag ( Directory: 0, file: 1 ) //Item[1] + "\t" + // Absolute file path Item[2] + "\t" + // Relative file path Item[3].ToString() + "\t" + // File size Item[4].ToString() + "\t" + // File attribute Item[5].ToString() + "\t" + // Last write date Item[6].ToString() + "\t" + // Last write time Item[7].ToString() + "\t" + // Creation date Item[8].ToString()); // Creation time // files only if (Convert.ToInt32(Item[0]) == 1) { // Files list for encryption _FileList.Add(Item[1].ToString()); // Absolute file path // Total file size _TotalFileSize += Convert.ToInt64(Item[3]); } FileNumber++; } //---------------------------------------------------------------------- // 暗号化リストを生成(ディレクトリ) // Create file to encrypt list ( Directory ) //---------------------------------------------------------------------- else { // Directory _FileList.Add(FilePath); // Absolute file path foreach (ArrayList Item in GetFileList(ParentPath, FilePath)) { if ((worker.CancellationPending == true)) { e.Cancel = true; return Tuple.Create(false, USER_CANCELED); } if (NewArchiveName != "") { Item[2] = NewArchiveName + "\\" + Item[2]; } FileInfoList.Add("Fn_" + FileNumber.ToString() + ":" + // File number //Item[0] + "\t" + // TypeFlag ( Directory: 0, file: 1 ) //Item[1] + "\t" + // Absolute file path Item[2] + "\t" + // Relative file path Item[3].ToString() + "\t" + // File size Item[4].ToString() + "\t" + // File attribute Item[5].ToString() + "\t" + // Last write date Item[6].ToString() + "\t" + // Last write time Item[7].ToString() + "\t" + // Creation date Item[8].ToString()); // Creation time if (Convert.ToInt32(Item[0]) == 1) { // files only // Files list for encryption _FileList.Add(Item[1].ToString()); // Absolute file path // Total file size _TotalFileSize += Convert.ToInt64(Item[3]); } else { // Directory _FileList.Add(Item[1].ToString()); // Absolute file path } FileNumber++; }// end foreach (ArrayList Item in GetFilesList(ParentPath, FilePath)); } }// end foreach (string FilePath in FilePaths); //---------------------------------------------------------------------- // Check the disk space //---------------------------------------------------------------------- string RootDriveLetter = Path.GetPathRoot(OutFilePath).Substring(0, 1); if (RootDriveLetter == "\\") { // Network } else { DriveInfo drive = new DriveInfo(RootDriveLetter); DriveType driveType = drive.DriveType; switch (driveType) { case DriveType.CDRom: case DriveType.NoRootDirectory: case DriveType.Unknown: break; case DriveType.Fixed: // Local Drive case DriveType.Network: // Mapped Drive case DriveType.Ram: // Ram Drive case DriveType.Removable: // Usually a USB Drive // The drive is not available, or not enough free space. if (drive.IsReady == false || drive.AvailableFreeSpace < _TotalFileSize) { e.Result = NO_DISK_SPACE; // not available free space return Tuple.Create(false, NO_DISK_SPACE); } break; } } //---------------------------------------------------------------------- // Create header data string[] FileInfoText = (string[])FileInfoList.ToArray(typeof(string)); // Shift-JIS ( Japanese ) byteArray = Encoding.GetEncoding(932).GetBytes(string.Join("\n", FileInfoText)); ms.Write(byteArray, 0, byteArray.Length); Console.WriteLine(FileInfoText); // UTF-8 byteArray = Encoding.UTF8.GetBytes("\n"+string.Join("\n", FileInfoText).Replace("Fn_", "U_")); ms.Write(byteArray, 0, byteArray.Length); Console.WriteLine(FileInfoText); #if (DEBUG) //Output text file of header contents for debug. Int64 NowPosition = ms.Position; ms.Position = 0; //Save to Desktop folder. string DesktopPath = System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); string HeaderTextFilePath = Path.Combine(DesktopPath, "encrypt_header.txt"); FileStream fsDebug = new FileStream(HeaderTextFilePath, FileMode.Create, FileAccess.Write); ms.WriteTo(fsDebug); fsDebug.Close(); ms.Position = NowPosition; #endif // The Header of MemoryStream is encrypted using (Rijndael aes = new RijndaelManaged()) { aes.BlockSize = 256; // BlockSize = 16bytes aes.KeySize = 256; // KeySize = 16bytes aes.Mode = CipherMode.CBC; // CBC mode //aes.Padding = PaddingMode.Zeros; // Padding mode is "None". // Password if (PasswordBinary != null) { // Binary bufferPassword = PasswordBinary; } else { // Text bufferPassword = Encoding.UTF8.GetBytes(Password); //byte[] bufferPassword = Encoding.GetEncoding(932).GetBytes(Password); // Shift-JIS } // Password is 256 bit, so truncated up to 32 bytes or fill up the data size. // パスワードは256 bitなので、32バイトまで切り詰めるか、あるいはそのサイズまで埋める処理 for (int i = 0; i < bufferKey.Length; i++) { if (i < bufferPassword.Length) { // Cut down to 32 bytes characters. bufferKey[i] = bufferPassword[i]; } else { bufferKey[i] = 0; // Zero filled } } aes.Key = bufferKey; // Initilization Vector aes.GenerateIV(); outfs.Write(aes.IV, 0, 32); ms.Position = 0; //Encryption interface. ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); using (CryptoStream cse = new CryptoStream(outfs, encryptor, CryptoStreamMode.Write)) { //---------------------------------------------------------------------- // ヘッダーの暗号化 //---------------------------------------------------------------------- int len = 0; _AtcHeaderSize = 0; // exclude IV of header buffer = new byte[BUFFER_SIZE]; while ((len = ms.Read(buffer, 0, BUFFER_SIZE)) > 0) { cse.Write(buffer, 0, len); _AtcHeaderSize += len; } } }// end using (Rijndael aes = new RijndaelManaged()); }// end using (MemoryStream ms = new MemoryStream()); }// end using (FileStream outfs = new FileStream(OutFilePath, FileMode.Create, FileAccess.Write)); //---------------------------------------------------------------------- // 本体データの暗号化 //---------------------------------------------------------------------- using (FileStream outfs = new FileStream(OutFilePath, FileMode.OpenOrCreate, FileAccess.Write)) { byteArray = new byte[4]; // Back to current positon of 'encrypted file size' if (_fExecutable == true) { outfs.Seek(ExeOutFileSize + 28, SeekOrigin.Begin); // self executable file } else { outfs.Seek(28, SeekOrigin.Begin); } byteArray = BitConverter.GetBytes(_AtcHeaderSize); outfs.Write(byteArray, 0, 4); // Out file stream postion move to end outfs.Seek(0, SeekOrigin.End); // The Header of MemoryStream is encrypted using (Rijndael aes = new RijndaelManaged()) { aes.BlockSize = 256; // BlockSize = 16bytes aes.KeySize = 256; // KeySize = 16bytes aes.Mode = CipherMode.CBC; // CBC mode //aes.Padding = PaddingMode.PKCS7; // Padding mode is "PKCS7". // Password is 256 bit, so truncated up to 32 bytes or fill up the data size. for (int i = 0; i < bufferKey.Length; i++) { if (i < bufferPassword.Length) { //Cut down to 32bytes characters. bufferKey[i] = bufferPassword[i]; } else { bufferKey[i] = 0; } } aes.Key = bufferKey; // Initilization Vector byte[] iv = new byte[32]; RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); rng.GetNonZeroBytes(iv); aes.IV = iv; outfs.Write(iv, 0, 32); // Encryption interface. ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); using (CryptoStream cse = new CryptoStream(outfs, encryptor, CryptoStreamMode.Write)) { // zlib 2bytes header cse.WriteByte(0x78); // cse.WriteByte(0x01); //No Compression/low cse.WriteByte(0x9C); //Default Compression //cse.WriteByte(0xDA); //Best Compression Ionic.Zlib.CompressionLevel flv = Ionic.Zlib.CompressionLevel.Default; switch (AppSettings.Instance.CompressRate) { case 0: flv = Ionic.Zlib.CompressionLevel.Level0; break; case 1: flv = Ionic.Zlib.CompressionLevel.Level1; break; case 2: flv = Ionic.Zlib.CompressionLevel.Level2; break; case 3: flv = Ionic.Zlib.CompressionLevel.Level3; break; case 4: flv = Ionic.Zlib.CompressionLevel.Level4; break; case 5: flv = Ionic.Zlib.CompressionLevel.Level5; break; case 6: flv = Ionic.Zlib.CompressionLevel.Level6; break; case 7: flv = Ionic.Zlib.CompressionLevel.Level7; break; case 8: flv = Ionic.Zlib.CompressionLevel.Level8; break; case 9: flv = Ionic.Zlib.CompressionLevel.Level9; break; } using ( Ionic.Zlib.DeflateStream ds = new Ionic.Zlib.DeflateStream(cse, Ionic.Zlib.CompressionMode.Compress, flv)) { int len = 0; foreach (string path in _FileList) { // Only file is encrypted if (File.Exists(path) == true) { buffer = new byte[BUFFER_SIZE]; using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) { len = 0; while ((len = fs.Read(buffer, 0, BUFFER_SIZE)) > 0) { ds.Write(buffer, 0, len); _TotalSize += len; string MessageText = ""; if (_TotalNumberOfFiles > 1) { MessageText = path + " ( " + _NumberOfFiles.ToString() + " files/ " + _TotalNumberOfFiles.ToString() + " folders )"; } else { MessageText = path; } MessageList = new ArrayList(); MessageList.Add(DECRYPTING); MessageList.Add(MessageText); float percent = ((float)_TotalSize / _TotalFileSize); worker.ReportProgress((int)(percent * 10000), MessageList); if (worker.CancellationPending == true) { e.Cancel = true; return Tuple.Create(false, USER_CANCELED); } } } } // end if (File.Exists(path) == true); } // end foreach (string path in _FileList); /* Random r = new Random(); byteArray = new byte[BUFFER_SIZE]; r.NextBytes(byteArray); ds.Write(buffer, 0, BUFFER_SIZE); */ } // end using ( Ionic.Zlib.DeflateStream ds); } // end using (CryptoStream cse); } // end using (Rijndael aes = new RijndaelManaged()); } // end using (FileStream outfs = new FileStream(OutFilePath, FileMode.Create, FileAccess.Write)); // Self-executable file if (fExecutable == true) { using (FileStream outfs = new FileStream(OutFilePath, FileMode.Open, FileAccess.Write)) { Int64 DataSize = outfs.Seek(0, SeekOrigin.End); DataSize = DataSize - _StartPos; byteArray = BitConverter.GetBytes(DataSize); outfs.Write(byteArray, 0, sizeof(Int64)); } } // Set the timestamp of encryption file to original files or directories if (_fKeepTimeStamp == true) { DateTime dtCreate = File.GetCreationTime((string)AppSettings.Instance.FileList[0]); DateTime dtUpdate = File.GetLastWriteTime((string)AppSettings.Instance.FileList[0]); DateTime dtAccess = File.GetLastAccessTime((string)AppSettings.Instance.FileList[0]); File.SetCreationTime(OutFilePath, dtCreate); File.SetLastWriteTime(OutFilePath, dtUpdate); File.SetLastAccessTime(OutFilePath, dtAccess); } //Encryption succeed. e.Result = ENCRYPT_SUCCEEDED; return Tuple.Create(true, ENCRYPT_SUCCEEDED); }
private Stream MaybeApplyCompression(Stream s, long streamLength) { if (_CompressionMethod == 0x08 && CompressionLevel != Ionic.Zlib.CompressionLevel.None) { var o = new Ionic.Zlib.DeflateStream(s, Ionic.Zlib.CompressionMode.Compress, CompressionLevel, true); if (_container.CodecBufferSize > 0) o.BufferSize = _container.CodecBufferSize; o.Strategy = _container.Strategy; return o; } #if BZIP if (_CompressionMethod == 0x0c) { #if !NETCF if (_container.ParallelDeflateThreshold == 0L || (streamLength > _container.ParallelDeflateThreshold && _container.ParallelDeflateThreshold > 0L)) { var o1 = new Ionic.BZip2.ParallelBZip2OutputStream(s, true); return o1; } #endif var o = new Ionic.BZip2.BZip2OutputStream(s, true); return o; } #endif return s; }
/// <summary> /// Multiple files or directories is encrypted by AES (exactly Rijndael) to use password string. /// 複数のファイル、またはディレクトリをAES(正確にはRijndael)を使って指定のパスワードで暗号化する /// </summary> /// <param name="FilePath">File path or directory path is encrypted</param> /// <param name="OutFilePath">Output encryption file name</param> /// <param name="Password">Encription password string</param> /// <returns>Encryption success(true) or failed(false)</returns> public Tuple<bool, int> Encrypt( object sender, DoWorkEventArgs e, string[] FilePaths, string OutFilePath, string Password, byte[] PasswordBinary, string NewArchiveName) { _AtcFilePath = OutFilePath; BackgroundWorker worker = sender as BackgroundWorker; // The timestamp of original file DateTime dtCreate = File.GetCreationTime(FilePaths[0]); DateTime dtUpdate = File.GetLastWriteTime(FilePaths[0]); DateTime dtAccess = File.GetLastAccessTime(FilePaths[0]); // Create Header data. ArrayList MessageList = new ArrayList(); MessageList.Add(READY_FOR_ENCRYPT); MessageList.Add(Path.GetFileName(OutFilePath)); worker.ReportProgress(0, MessageList); _FileList = new List<string>(); byte[] byteArray = null; // Salt Rfc2898DeriveBytes deriveBytes; if(PasswordBinary == null) { // String Password deriveBytes = new Rfc2898DeriveBytes(Password, 8, 1000); } else { // Binary Password byte[] random_salt = new byte[8]; RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); rng.GetBytes(random_salt); deriveBytes = new Rfc2898DeriveBytes(PasswordBinary, random_salt, 1000); } byte[] salt = deriveBytes.Salt; byte[] key = deriveBytes.GetBytes(32); byte[] iv = deriveBytes.GetBytes(32); using (FileStream outfs = new FileStream(OutFilePath, FileMode.Create, FileAccess.Write)) { // 自己実行形式ファイル(Self-executable file) if (_fExecutable == true) { ExeOutFileSize = rawData.Length; outfs.Write(rawData, 0, (int)ExeOutFileSize); } _StartPos = outfs.Seek(0, SeekOrigin.End); // Application version Version ver = ApplicationInfo.Version; short vernum = Int16.Parse(ver.ToString().Replace(".", "")); byteArray = BitConverter.GetBytes(vernum); outfs.Write(byteArray, 0, 2); // Input password limit byteArray = BitConverter.GetBytes(_MissTypeLimits); outfs.Write(byteArray, 0, 1); // Exceed the password input limit, destroy the file? byteArray = BitConverter.GetBytes(fBrocken); outfs.Write(byteArray, 0, 1); // Token that this is the AttacheCase file byteArray = Encoding.ASCII.GetBytes(STRING_TOKEN_NORMAL); outfs.Write(byteArray, 0, 16); // File sub version byteArray = BitConverter.GetBytes(DATA_FILE_VERSION); outfs.Write(byteArray, 0, 4); // The size of encrypted Atc header size ( reserved ) byteArray = BitConverter.GetBytes((int)0); outfs.Write(byteArray, 0, 4); // Salt outfs.Write(salt, 0, 8); // Cipher text header. using (MemoryStream ms = new MemoryStream()) { byteArray = Encoding.ASCII.GetBytes(AtC_ENCRYPTED_TOKEN + "\n"); ms.Write(byteArray, 0, byteArray.Length); int FileNumber = 0; string ParentPath; ArrayList FileInfoList = new ArrayList(); //---------------------------------------------------------------------- // Put together files in one ( Save as the name ). // 複数ファイルを一つにまとめる(ファイルに名前をつけて保存) if (NewArchiveName != "") { // Now time DateTime dtNow = new DateTime(); FileInfoList.Add("0:" + // File number NewArchiveName + "\\\t" + // File name "0" + "\t" + // File size "16" + "\t" + // File attribute dtNow.Date.Subtract(new DateTime(1, 1, 1)).TotalDays + "\t" + // Last write date dtNow.TimeOfDay.TotalSeconds + "\t" + // Last write time dtNow.Date.Subtract(new DateTime(1, 1, 1)).TotalDays + "\t" + // Creation date dtNow.TimeOfDay.TotalSeconds); // Creation time FileNumber++; } //---------------------------------------------------------------------- // When encrypt multiple files // 複数のファイルを暗号化する場合 foreach (string FilePath in FilePaths) { ParentPath = Path.GetDirectoryName(FilePath); if(ParentPath.EndsWith("\\") == false) // In case of 'C:\\' root direcroy. { ParentPath = ParentPath + "\\"; } if ((worker.CancellationPending == true)) { e.Cancel = true; return Tuple.Create(false, USER_CANCELED); } //---------------------------------------------------------------------- // 暗号化リストを生成(ファイル) // Create file to encrypt list ( File ) //---------------------------------------------------------------------- if (File.Exists(FilePath) == true) { ArrayList Item = GetFileInfo(ParentPath, FilePath); FileInfoList.Add(FileNumber.ToString() + ":" + // File number //Item[0] + "\t" + // TypeFlag ( Directory: 0, file: 1 ) //Item[1] + "\t" + // Absolute file path Item[2] + "\t" + // Relative file path Item[3].ToString() + "\t" + // File size Item[4].ToString() + "\t" + // File attribute Item[5].ToString() + "\t" + // Last write date Item[6].ToString() + "\t" + // Last write time Item[7].ToString() + "\t" + // Creation date Item[8].ToString() + "\t" + // Creation time Item[9].ToString()); // SHA-256 Hash string // files only if (Convert.ToInt32(Item[0]) == 1) { // Files list for encryption _FileList.Add(Item[1].ToString()); // Absolute file path // Total file size _TotalFileSize += Convert.ToInt64(Item[3]); } FileNumber++; } //---------------------------------------------------------------------- // 暗号化リストを生成(ディレクトリ) // Create file to encrypt list ( Directory ) //---------------------------------------------------------------------- else { // Directory _FileList.Add(FilePath); // Absolute file path foreach (ArrayList Item in GetFileList(ParentPath, FilePath)) { if ((worker.CancellationPending == true)) { e.Cancel = true; return Tuple.Create(false, USER_CANCELED); } if (NewArchiveName != "") { Item[2] = NewArchiveName + "\\" + Item[2]; } if ((int)Item[0] == 0) { // Directory FileInfoList.Add(FileNumber.ToString() + ":" + // File number Item[2] + "\t" + // Relative file path Item[3].ToString() + "\t" + // File size Item[4].ToString() + "\t" + // File attribute Item[5].ToString() + "\t" + // Last write date Item[6].ToString() + "\t" + // Last write time Item[7].ToString() + "\t" + // Creation date Item[8].ToString()); // Creation time } else { // File FileInfoList.Add(FileNumber.ToString() + ":" + // File number Item[2] + "\t" + // Relative file path Item[3].ToString() + "\t" + // File size Item[4].ToString() + "\t" + // File attribute Item[5].ToString() + "\t" + // Last write date Item[6].ToString() + "\t" + // Last write time Item[7].ToString() + "\t" + // Creation date Item[8].ToString() + "\t" + // Creation time Item[9].ToString()); // SHA-256 hash } if (Convert.ToInt32(Item[0]) == 1) { // files only // Files list for encryption _FileList.Add(Item[1].ToString()); // Absolute file path // Total file size _TotalFileSize += Convert.ToInt64(Item[3]); } else { // Directory _FileList.Add(Item[1].ToString()); // Absolute file path } FileNumber++; }// end foreach (ArrayList Item in GetFilesList(ParentPath, FilePath)); }// if (File.Exists(FilePath) == true); }// end foreach (string FilePath in FilePaths); //---------------------------------------------------------------------- // Check the disk space //---------------------------------------------------------------------- string RootDriveLetter = Path.GetPathRoot(OutFilePath).Substring(0, 1); if (RootDriveLetter == "\\") { // Network } else { DriveInfo drive = new DriveInfo(RootDriveLetter); DriveType driveType = drive.DriveType; switch (driveType) { case DriveType.CDRom: case DriveType.NoRootDirectory: case DriveType.Unknown: break; case DriveType.Fixed: // Local Drive case DriveType.Network: // Mapped Drive case DriveType.Ram: // Ram Drive case DriveType.Removable: // Usually a USB Drive // The drive is not available, or not enough free space. if (drive.IsReady == false || drive.AvailableFreeSpace < _TotalFileSize) { e.Result = NO_DISK_SPACE; // not available free space return Tuple.Create(false, NO_DISK_SPACE); } break; } } //---------------------------------------------------------------------- // Create header data string[] FileInfoText = (string[])FileInfoList.ToArray(typeof(string)); byteArray = Encoding.UTF8.GetBytes(string.Join("\n", FileInfoText)); ms.Write(byteArray, 0, byteArray.Length); #if (DEBUG) //Output text file of header contents for debug. Int64 NowPosition = ms.Position; ms.Position = 0; //Save to Desktop folder. string AppDirPath = Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath); string HeaderTextFilePath = Path.Combine(AppDirPath, "encrypt_header.txt"); using (FileStream fsDebug = new FileStream(HeaderTextFilePath, FileMode.Create, FileAccess.Write)) { ms.WriteTo(fsDebug); ms.Position = NowPosition; } #endif // The Header of MemoryStream is encrypted using (Rijndael aes = new RijndaelManaged()) { aes.BlockSize = 256; // BlockSize = 16bytes aes.KeySize = 256; // KeySize = 16bytes aes.Mode = CipherMode.CBC; // CBC mode //aes.Padding = PaddingMode.Zeros; // Padding mode is "None". aes.Key = key; aes.IV = iv; ms.Position = 0; //Encryption interface. ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); using (CryptoStream cse = new CryptoStream(outfs, encryptor, CryptoStreamMode.Write)) { //---------------------------------------------------------------------- // ヘッダーの暗号化 //---------------------------------------------------------------------- int len = 0; _AtcHeaderSize = 0; // exclude IV of header buffer = new byte[BUFFER_SIZE]; while ((len = ms.Read(buffer, 0, BUFFER_SIZE)) > 0) { cse.Write(buffer, 0, len); _AtcHeaderSize += len; } } }// end using (Rijndael aes = new RijndaelManaged()); }// end using (MemoryStream ms = new MemoryStream()); }// end using (FileStream outfs = new FileStream(OutFilePath, FileMode.Create, FileAccess.Write)); //---------------------------------------------------------------------- // 本体データの暗号化 //---------------------------------------------------------------------- using (FileStream outfs = new FileStream(OutFilePath, FileMode.OpenOrCreate, FileAccess.Write)) { try { byteArray = new byte[4]; // Back to current positon of 'encrypted file size' if (_fExecutable == true) { outfs.Seek(ExeOutFileSize + 24, SeekOrigin.Begin); // self executable file } else { outfs.Seek(24, SeekOrigin.Begin); } byteArray = BitConverter.GetBytes(_AtcHeaderSize); outfs.Write(byteArray, 0, 4); // Out file stream postion move to end outfs.Seek(0, SeekOrigin.End); // The Header of MemoryStream is encrypted using (Rijndael aes = new RijndaelManaged()) { aes.BlockSize = 256; // BlockSize = 16bytes aes.KeySize = 256; // KeySize = 16bytes aes.Mode = CipherMode.CBC; // CBC mode aes.Padding = PaddingMode.Zeros; // Padding mode aes.Key = key; aes.IV = iv; // Encryption interface. ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); using (CryptoStream cse = new CryptoStream(outfs, encryptor, CryptoStreamMode.Write)) { Ionic.Zlib.CompressionLevel flv = Ionic.Zlib.CompressionLevel.Default; switch (AppSettings.Instance.CompressRate) { case 0: flv = Ionic.Zlib.CompressionLevel.Level0; break; case 1: flv = Ionic.Zlib.CompressionLevel.Level1; break; case 2: flv = Ionic.Zlib.CompressionLevel.Level2; break; case 3: flv = Ionic.Zlib.CompressionLevel.Level3; break; case 4: flv = Ionic.Zlib.CompressionLevel.Level4; break; case 5: flv = Ionic.Zlib.CompressionLevel.Level5; break; case 6: flv = Ionic.Zlib.CompressionLevel.Level6; break; case 7: flv = Ionic.Zlib.CompressionLevel.Level7; break; case 8: flv = Ionic.Zlib.CompressionLevel.Level8; break; case 9: flv = Ionic.Zlib.CompressionLevel.Level9; break; } using (Ionic.Zlib.DeflateStream ds = new Ionic.Zlib.DeflateStream(cse, Ionic.Zlib.CompressionMode.Compress, flv)) { int len = 0; foreach (string path in _FileList) { // Only file is encrypted if (File.Exists(path) == true) { try { buffer = new byte[BUFFER_SIZE]; using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { len = 0; while ((len = fs.Read(buffer, 0, BUFFER_SIZE)) > 0) { ds.Write(buffer, 0, len); _TotalSize += len; string MessageText = ""; if (_TotalNumberOfFiles > 1) { MessageText = path + " ( " + _NumberOfFiles.ToString() + " / " + _TotalNumberOfFiles.ToString() + " files )"; } else { MessageText = path; } float percent = ((float)_TotalSize / _TotalFileSize); MessageList = new ArrayList(); MessageList.Add(ENCRYPTING); MessageList.Add(MessageText); worker.ReportProgress((int)(percent * 10000), MessageList); if (worker.CancellationPending == true) { fs.Dispose(); e.Cancel = true; return Tuple.Create(false, USER_CANCELED); } } } } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message.ToString()); e.Result = ERROR_UNEXPECTED; return Tuple.Create(false, ERROR_UNEXPECTED); } } // end if (File.Exists(path) == true); } // end foreach (string path in _FileList); /* for (int i = 0; i < 10; i++) { Random r = new Random(); byteArray = new byte[BUFFER_SIZE]; r.NextBytes(byteArray); cse.Write(buffer, 0, BUFFER_SIZE); } */ } // end using ( Ionic.Zlib.DeflateStream ds); } // end using (CryptoStream cse); } // end using (Rijndael aes = new RijndaelManaged()); } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message.ToString()); e.Result = ERROR_UNEXPECTED; return Tuple.Create(false, ERROR_UNEXPECTED); } } // end using (FileStream outfs = new FileStream(OutFilePath, FileMode.Create, FileAccess.Write)); // Set the timestamp of encryption file to original files or directories if (_fKeepTimeStamp == true) { File.SetCreationTime(OutFilePath, dtCreate); File.SetLastWriteTime(OutFilePath, dtUpdate); File.SetLastAccessTime(OutFilePath, dtAccess); } else { dtUpdate = DateTime.Now; File.SetLastWriteTime(OutFilePath, dtUpdate); } //Encryption succeed. e.Result = ENCRYPT_SUCCEEDED; return Tuple.Create(true, ENCRYPT_SUCCEEDED); }
public bool Encrypt( object sender, DoWorkEventArgs e, string[] FilePaths, string OutFilePath, string Password, byte[] PasswordBinary, string NewArchiveName) { #if (DEBUG) Logger lg = new Logger(); lg.Info("-----------------------------------"); lg.Info(OutFilePath); lg.Info("Encryotion satrt."); lg.StopWatchStart(); #endif _AtcFilePath = OutFilePath; BackgroundWorker worker = sender as BackgroundWorker; // The timestamp of original file DateTime dtCreate = File.GetCreationTime(FilePaths[0]); DateTime dtUpdate = File.GetLastWriteTime(FilePaths[0]); DateTime dtAccess = File.GetLastAccessTime(FilePaths[0]); // Create Header data. ArrayList MessageList = new ArrayList { READY_FOR_ENCRYPT, Path.GetFileName(_AtcFilePath) }; worker.ReportProgress(0, MessageList); // Stopwatch for measuring time and adjusting the progress bar display Stopwatch swEncrypt = new Stopwatch(); Stopwatch swProgress = new Stopwatch(); swEncrypt.Start(); swProgress.Start(); float percent = 0; _FileList = new List <string>(); byte[] byteArray = null; // Salt Rfc2898DeriveBytes deriveBytes; if (PasswordBinary == null) { // String Password deriveBytes = new Rfc2898DeriveBytes(Password, 8, 1000); } else { // Binary Password byte[] random_salt = new byte[8]; RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); rng.GetBytes(random_salt); deriveBytes = new Rfc2898DeriveBytes(PasswordBinary, random_salt, 1000); } byte[] salt = deriveBytes.Salt; byte[] key = deriveBytes.GetBytes(32); byte[] iv = deriveBytes.GetBytes(32); try { using (FileStream outfs = new FileStream(_AtcFilePath, FileMode.Create, FileAccess.Write)) { // 自己実行形式ファイル(Self-executable file) if (_fExecutable == true) { // Read from ExeOut3.cs ExeOutFileSize = rawData.Length; outfs.Write(rawData, 0, (int)ExeOutFileSize); } _StartPos = outfs.Seek(0, SeekOrigin.End); // Application version Version ver = ApplicationInfo.Version; short vernum = Int16.Parse(ver.ToString().Replace(".", "")); byteArray = BitConverter.GetBytes(vernum); outfs.Write(byteArray, 0, 2); // Input password limit byteArray = BitConverter.GetBytes(_MissTypeLimits); outfs.Write(byteArray, 0, 1); // Exceed the password input limit, destroy the file? byteArray = BitConverter.GetBytes(fBrocken); outfs.Write(byteArray, 0, 1); // Token that this is the AttacheCase file byteArray = Encoding.ASCII.GetBytes(STRING_TOKEN_NORMAL); outfs.Write(byteArray, 0, 16); // File sub version byteArray = BitConverter.GetBytes(DATA_FILE_VERSION); outfs.Write(byteArray, 0, 4); // The size of encrypted Atc header size ( reserved ) byteArray = BitConverter.GetBytes((int)0); outfs.Write(byteArray, 0, 4); // Salt outfs.Write(salt, 0, 8); // Cipher text header. using (MemoryStream ms = new MemoryStream()) { byteArray = Encoding.ASCII.GetBytes(AtC_ENCRYPTED_TOKEN + "\n"); ms.Write(byteArray, 0, byteArray.Length); int FileNumber = 0; string ParentPath; ArrayList FileInfoList = new ArrayList(); //---------------------------------------------------------------------- // Put together files in one ( Save as the name ). // 複数ファイルを一つにまとめる(ファイルに名前をつけて保存) if (NewArchiveName != "") { NewArchiveName = NewArchiveName + "\\"; // Now time DateTime dtNow = new DateTime(); FileInfoList.Add("0:" + // File number NewArchiveName + "\t" + // File name "0" + "\t" + // File size "16" + "\t" + // File attribute dtNow.Date.Subtract(new DateTime(1, 1, 1)).TotalDays + "\t" + // Last write date dtNow.TimeOfDay.TotalSeconds + "\t" + // Last write time dtNow.Date.Subtract(new DateTime(1, 1, 1)).TotalDays + "\t" + // Creation date dtNow.TimeOfDay.TotalSeconds + "\t" + // Creation time "" + "\t" + // ver.3.2.3.0 ~ DateTime.UtcNow.ToString("yyyy/MM/dd HH:mm:ss") + "\t" + DateTime.UtcNow.ToString("yyyy/MM/dd HH:mm:ss")); FileNumber++; } //---------------------------------------------------------------------- // When encrypt multiple files // 複数のファイルを暗号化する場合 foreach (string FilePath in FilePaths) { ParentPath = Path.GetDirectoryName(FilePath); if (ParentPath.EndsWith("\\") == false) // In case of 'C:\\' root direcroy. { ParentPath = ParentPath + "\\"; } if ((worker.CancellationPending == true)) { e.Cancel = true; return(false); } //---------------------------------------------------------------------- // 暗号化リストを生成(ファイル) // Create file to encrypt list ( File ) //---------------------------------------------------------------------- if (File.Exists(FilePath) == true) { ArrayList Item = GetFileInfo(ParentPath, FilePath); FileInfoList.Add(FileNumber.ToString() + ":" + // File number //Item[0] + "\t" + // TypeFlag ( Directory: 0, file: 1 ) //Item[1] + "\t" + // Absolute file path NewArchiveName + Item[2] + "\t" + // Relative file path Item[3].ToString() + "\t" + // File size Item[4].ToString() + "\t" + // File attribute Item[5].ToString() + "\t" + // Last write date Item[6].ToString() + "\t" + // Last write time Item[7].ToString() + "\t" + // Creation date Item[8].ToString() + "\t" + // Creation time Item[9].ToString() + "\t" + // SHA-256 Hash string // ver.3.2.3.0 ~ Item[10].ToString() + "\t" + // Last write date time(UTC) Item[11].ToString()); // Creation date time(UTC) // files only if (Convert.ToInt32(Item[0]) == 1) { // Files list for encryption _FileList.Add(Item[1].ToString()); // Absolute file path // Total file size _TotalFileSize += Convert.ToInt64(Item[3]); } FileNumber++; } //---------------------------------------------------------------------- // 暗号化リストを生成(ディレクトリ) // Create file to encrypt list ( Directory ) //---------------------------------------------------------------------- else { // Directory _FileList.Add(FilePath); // Absolute file path foreach (ArrayList Item in GetFileList(ParentPath, FilePath)) { if ((worker.CancellationPending == true)) { e.Cancel = true; return(false); } if (NewArchiveName != "") { Item[2] = NewArchiveName + "\\" + Item[2]; } if ((int)Item[0] == 0) { // Directory FileInfoList.Add(FileNumber.ToString() + ":" + // File number NewArchiveName + Item[2] + "\t" + // Relative file path Item[3].ToString() + "\t" + // File size Item[4].ToString() + "\t" + // File attribute Item[5].ToString() + "\t" + // Last write date Item[6].ToString() + "\t" + // Last write time Item[7].ToString() + "\t" + // Creation date Item[8].ToString() + "\t" + // Creation time "" + "\t" + // ver.3.2.3.0 ~ Item[10].ToString() + "\t" + // Last write date time(UTC) Item[11].ToString()); // Creation date date time(UTC) } else { // File FileInfoList.Add(FileNumber.ToString() + ":" + // File number NewArchiveName + Item[2] + "\t" + // Relative file path Item[3].ToString() + "\t" + // File size Item[4].ToString() + "\t" + // File attribute Item[5].ToString() + "\t" + // Last write date Item[6].ToString() + "\t" + // Last write time Item[7].ToString() + "\t" + // Creation date Item[8].ToString() + "\t" + // Creation time Item[9].ToString() + "\t" + // SHA-256 hash // ver.3.2.3.0 ~ Item[10].ToString() + "\t" + // Last write date time(UTC) Item[11].ToString()); // Creation date date time(UTC) } if (Convert.ToInt32(Item[0]) == 1) { // files only // Files list for encryption _FileList.Add(Item[1].ToString()); // Absolute file path // Total file size _TotalFileSize += Convert.ToInt64(Item[3]); } else { // Directory _FileList.Add(Item[1].ToString()); // Absolute file path } FileNumber++; } // end foreach (ArrayList Item in GetFilesList(ParentPath, FilePath)); } // if (File.Exists(FilePath) == true); } // end foreach (string FilePath in FilePaths); //---------------------------------------------------------------------- // Check the disk space //---------------------------------------------------------------------- string RootDriveLetter = Path.GetPathRoot(_AtcFilePath).Substring(0, 1); if (RootDriveLetter == "\\") { // Network } else { DriveInfo drive = new DriveInfo(RootDriveLetter); DriveType driveType = drive.DriveType; switch (driveType) { case DriveType.CDRom: case DriveType.NoRootDirectory: case DriveType.Unknown: break; case DriveType.Fixed: // Local Drive case DriveType.Network: // Mapped Drive case DriveType.Ram: // Ram Drive case DriveType.Removable: // Usually a USB Drive // The drive is not available, or not enough free space. if (drive.IsReady == false || drive.AvailableFreeSpace < _TotalFileSize) { // not available free space _ReturnCode = NO_DISK_SPACE; _DriveName = drive.ToString(); //_TotalFileSize = _TotalFileSize; _AvailableFreeSpace = drive.AvailableFreeSpace; return(false); } break; } } //---------------------------------------------------------------------- // Create header data string[] FileInfoText = (string[])FileInfoList.ToArray(typeof(string)); #if (DEBUG) string DesktopPath = System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); string FileListTextPath = Path.Combine(DesktopPath, "_header_text.txt"); var FileListText = String.Join("\n", FileInfoText); System.IO.File.WriteAllText(FileListTextPath, FileListText, System.Text.Encoding.UTF8); #endif byteArray = Encoding.UTF8.GetBytes(string.Join("\n", FileInfoText)); ms.Write(byteArray, 0, byteArray.Length); // The Header of MemoryStream is encrypted using (Rijndael aes = new RijndaelManaged()) { aes.BlockSize = 256; // BlockSize = 16bytes aes.KeySize = 256; // KeySize = 16bytes aes.Mode = CipherMode.CBC; // CBC mode //aes.Padding = PaddingMode.Zeros; // Padding mode is "None". aes.Key = key; aes.IV = iv; ms.Position = 0; //Encryption interface. ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); using (CryptoStream cse = new CryptoStream(outfs, encryptor, CryptoStreamMode.Write)) { //---------------------------------------------------------------------- // ヘッダーの暗号化 //---------------------------------------------------------------------- int len = 0; _AtcHeaderSize = 0; // exclude IV of header buffer = new byte[BUFFER_SIZE]; while ((len = ms.Read(buffer, 0, BUFFER_SIZE)) > 0) { cse.Write(buffer, 0, len); _AtcHeaderSize += len; } } } // end using (Rijndael aes = new RijndaelManaged()); } // end using (MemoryStream ms = new MemoryStream()); } // end using (FileStream outfs = new FileStream(_AtcFilePath, FileMode.Create, FileAccess.Write)); //---------------------------------------------------------------------- // 本体データの暗号化 //---------------------------------------------------------------------- using (FileStream outfs = new FileStream(_AtcFilePath, FileMode.OpenOrCreate, FileAccess.Write)) { byteArray = new byte[4]; // Back to current positon of 'encrypted file size' if (_fExecutable == true) { outfs.Seek(ExeOutFileSize + 24, SeekOrigin.Begin); // self executable file } else { outfs.Seek(24, SeekOrigin.Begin); } byteArray = BitConverter.GetBytes(_AtcHeaderSize); outfs.Write(byteArray, 0, 4); // Out file stream postion move to end outfs.Seek(0, SeekOrigin.End); // The Header of MemoryStream is encrypted using (Rijndael aes = new RijndaelManaged()) { aes.BlockSize = 256; // BlockSize = 16bytes aes.KeySize = 256; // KeySize = 16bytes aes.Mode = CipherMode.CBC; // CBC mode aes.Padding = PaddingMode.Zeros; // Padding mode aes.Key = key; aes.IV = iv; // Encryption interface. ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); using (CryptoStream cse = new CryptoStream(outfs, encryptor, CryptoStreamMode.Write)) { Ionic.Zlib.CompressionLevel flv = Ionic.Zlib.CompressionLevel.Default; switch (AppSettings.Instance.CompressRate) { case 0: flv = Ionic.Zlib.CompressionLevel.Level0; break; case 1: flv = Ionic.Zlib.CompressionLevel.Level1; break; case 2: flv = Ionic.Zlib.CompressionLevel.Level2; break; case 3: flv = Ionic.Zlib.CompressionLevel.Level3; break; case 4: flv = Ionic.Zlib.CompressionLevel.Level4; break; case 5: flv = Ionic.Zlib.CompressionLevel.Level5; break; case 6: flv = Ionic.Zlib.CompressionLevel.Level6; break; case 7: flv = Ionic.Zlib.CompressionLevel.Level7; break; case 8: flv = Ionic.Zlib.CompressionLevel.Level8; break; case 9: flv = Ionic.Zlib.CompressionLevel.Level9; break; } using (Ionic.Zlib.DeflateStream ds = new Ionic.Zlib.DeflateStream(cse, Ionic.Zlib.CompressionMode.Compress, flv)) { int len = 0; foreach (string path in _FileList) { // Only file is encrypted if (File.Exists(path) == true) { buffer = new byte[BUFFER_SIZE]; using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { len = 0; while ((len = fs.Read(buffer, 0, BUFFER_SIZE)) > 0) { ds.Write(buffer, 0, len); _TotalSize += len; string MessageText = ""; if (_TotalNumberOfFiles > 1) { MessageText = path + " ( " + _NumberOfFiles.ToString() + " / " + _TotalNumberOfFiles.ToString() + " files )"; } else { MessageText = path; } MessageList = new ArrayList(); MessageList.Add(ENCRYPTING); MessageList.Add(MessageText); // プログレスバーの更新間隔を100msに調整 if (swProgress.ElapsedMilliseconds > 100) { percent = ((float)_TotalSize / _TotalFileSize); worker.ReportProgress((int)(percent * 10000), MessageList); swProgress.Restart(); } if (worker.CancellationPending == true) { fs.Dispose(); e.Cancel = true; return(false); } } } } // end if (File.Exists(path) == true); } // end foreach (string path in _FileList); /* * for (int i = 0; i < 10; i++) * { * Random r = new Random(); * byteArray = new byte[BUFFER_SIZE]; * r.NextBytes(byteArray); * cse.Write(buffer, 0, BUFFER_SIZE); * } */ } // end using ( Ionic.Zlib.DeflateStream ds); } // end using (CryptoStream cse); } // end using (Rijndael aes = new RijndaelManaged()); } // end using (FileStream outfs = new FileStream(_AtcFilePath, FileMode.Create, FileAccess.Write)); // Set the timestamp of encryption file to original files or directories if (_fKeepTimeStamp == true) { File.SetCreationTime(_AtcFilePath, dtCreate); File.SetLastWriteTime(_AtcFilePath, dtUpdate); File.SetLastAccessTime(_AtcFilePath, dtAccess); } else { dtUpdate = DateTime.Now; File.SetLastWriteTime(_AtcFilePath, dtUpdate); } //Encryption succeed. _ReturnCode = ENCRYPT_SUCCEEDED; return(true); } catch (UnauthorizedAccessException) { //オペレーティング システムが I/O エラーまたは特定の種類のセキュリティエラーのためにアクセスを拒否する場合、スローされる例外 //The exception that is thrown when the operating system denies access //because of an I/O error or a specific type of security error. _ReturnCode = OS_DENIES_ACCESS; _ErrorFilePath = _AtcFilePath; return(false); } catch (DirectoryNotFoundException ex) { //ファイルまたはディレクトリの一部が見つからない場合にスローされる例外 //The exception that is thrown when part of a file or directory cannot be found _ReturnCode = DIRECTORY_NOT_FOUND; _ErrorMessage = ex.Message; return(false); } catch (DriveNotFoundException ex) { //使用できないドライブまたは共有にアクセスしようとするとスローされる例外 //The exception that is thrown when trying to access a drive or share that is not available _ReturnCode = DRIVE_NOT_FOUND; _ErrorMessage = ex.Message; return(false); } catch (FileLoadException ex) { //マネージド アセンブリが見つかったが、読み込むことができない場合にスローされる例外 //The exception that is thrown when a managed assembly is found but cannot be loaded _ReturnCode = FILE_NOT_LOADED; _ErrorFilePath = ex.FileName; return(false); } catch (FileNotFoundException ex) { //ディスク上に存在しないファイルにアクセスしようとして失敗したときにスローされる例外 //The exception that is thrown when an attempt to access a file that does not exist on disk fails _ReturnCode = FILE_NOT_FOUND; _ErrorFilePath = ex.FileName; return(false); } catch (PathTooLongException) { //パス名または完全修飾ファイル名がシステム定義の最大長を超えている場合にスローされる例外 //The exception that is thrown when a path or fully qualified file name is longer than the system-defined maximum length _ReturnCode = PATH_TOO_LONG; return(false); } catch (IOException ex) { //I/Oエラーが発生したときにスローされる例外。現在の例外を説明するメッセージを取得します。 //The exception that is thrown when an I/O error occurs. Gets a message that describes the current exception. _ReturnCode = IO_EXCEPTION; _ErrorMessage = ex.Message; return(false); } catch (Exception ex) { _ReturnCode = ERROR_UNEXPECTED; _ErrorMessage = ex.Message; return(false); } finally { #if (DEBUG) lg.StopWatchStop(); lg.Info("encryption finished!"); #endif swEncrypt.Stop(); swProgress.Stop(); // 計測時間 TimeSpan ts = swEncrypt.Elapsed; _EncryptionTimeString = Convert.ToString(ts.Hours) + "h" + Convert.ToString(ts.Minutes) + "m" + Convert.ToString(ts.Seconds) + "s" + Convert.ToString(ts.Milliseconds) + "ms"; } } // encrypt();
/// <summary> /// Multiple files or directories is encrypted by AES (exactly Rijndael) to use password string. /// 複数のファイル、またはディレクトリをAES(正確にはRijndael)を使って指定のパスワードで暗号化する /// </summary> /// <param name="FilePath">File path or directory path is encrypted</param> /// <param name="OutFilePath">Output encryption file name</param> /// <param name="Password">Encription password string</param> /// <returns>Encryption success(true) or failed(false)</returns> public Tuple <bool, int> Encrypt( object sender, DoWorkEventArgs e, string[] FilePaths, string OutFilePath, string Password, byte[] PasswordBinary, string NewArchiveName) { byte[] bufferPassword; byte[] bufferKey = new byte[32]; _AtcFilePath = OutFilePath; BackgroundWorker worker = sender as BackgroundWorker; //----------------------------------- // Header data is starting. // Progress event handler ArrayList MessageList = new ArrayList(); MessageList.Add(READY_FOR_ENCRYPT); MessageList.Add(Path.GetFileName(OutFilePath)); worker.ReportProgress(0, MessageList); _FileList = new List <string>(); byte[] byteArray = null; using (FileStream outfs = new FileStream(OutFilePath, FileMode.Create, FileAccess.Write)) { // 自己実行形式ファイル(Self-executable file) if (_fExecutable == true) { ExeOutFileSize = rawData.Length; outfs.Write(rawData, 0, (int)ExeOutFileSize); } _StartPos = outfs.Seek(0, SeekOrigin.End); byteArray = new byte[16]; // Plain text header byteArray = BitConverter.GetBytes(DATA_SUB_VERSION); outfs.Write(byteArray, 0, 1); byteArray = null; byteArray = BitConverter.GetBytes(RESERVED_DATA); outfs.Write(byteArray, 0, 1); byteArray = null; byteArray = BitConverter.GetBytes(charMissTypeLimits); outfs.Write(byteArray, 0, 1); byteArray = null; byteArray = BitConverter.GetBytes(fBrocken); outfs.Write(byteArray, 0, 1); byteArray = null; byteArray = Encoding.ASCII.GetBytes(STRING_TOKEN_NORMAL); outfs.Write(byteArray, 0, 16); byteArray = null; byteArray = BitConverter.GetBytes(DATA_FILE_VERSION); outfs.Write(byteArray, 0, 4); byteArray = null; byteArray = BitConverter.GetBytes(TYPE_ALGORISM); outfs.Write(byteArray, 0, 4); // Reserve cipher text header size after encrypting. byteArray = null; byteArray = BitConverter.GetBytes(_AtcHeaderSize); outfs.Write(byteArray, 0, 4); // Cipher text header. using (MemoryStream ms = new MemoryStream()) { byteArray = Encoding.ASCII.GetBytes("Passcode:AttacheCase\n"); ms.Write(byteArray, 0, byteArray.Length); DateTime dt = DateTime.Now; byteArray = Encoding.ASCII.GetBytes("LastDateTime:" + dt.ToString("yyyy/MM/dd HH:mm:ss\n")); ms.Write(byteArray, 0, byteArray.Length); int FileNumber = 0; string ParentPath; ArrayList FileInfoList = new ArrayList(); //---------------------------------------------------------------------- // Put together files in one ( Save as the name ). // 複数ファイルを一つにまとめる(ファイルに名前をつけて保存) if (NewArchiveName != "") { // Now time DateTime dtNow = new DateTime(); FileInfoList.Add("Fn_0:" + // File number NewArchiveName + "\\\t" + // File name "0" + "\t" + // File size "16" + "\t" + // File attribute dtNow.Date.Subtract(new DateTime(1, 1, 1)).TotalDays + "\t" + // Last write date dtNow.TimeOfDay.TotalSeconds + "\t" + // Last write time dtNow.Date.Subtract(new DateTime(1, 1, 1)).TotalDays + "\t" + // Creation date dtNow.TimeOfDay.TotalSeconds); // Creation time FileNumber++; } //---------------------------------------------------------------------- // When encrypt multiple files // 複数のファイルを暗号化する場合 foreach (string FilePath in FilePaths) { ParentPath = Path.GetDirectoryName(FilePath) + "\\"; if ((worker.CancellationPending == true)) { e.Cancel = true; return(Tuple.Create(false, USER_CANCELED)); } //---------------------------------------------------------------------- // 暗号化リストを生成(ファイル) // Create file to encrypt list ( File ) //---------------------------------------------------------------------- if (File.Exists(FilePath) == true) { ArrayList Item = GetFileInfo(ParentPath, FilePath); FileInfoList.Add("Fn_" + FileNumber.ToString() + ":" + // File number //Item[0] + "\t" + // TypeFlag ( Directory: 0, file: 1 ) //Item[1] + "\t" + // Absolute file path Item[2] + "\t" + // Relative file path Item[3].ToString() + "\t" + // File size Item[4].ToString() + "\t" + // File attribute Item[5].ToString() + "\t" + // Last write date Item[6].ToString() + "\t" + // Last write time Item[7].ToString() + "\t" + // Creation date Item[8].ToString()); // Creation time // files only if (Convert.ToInt32(Item[0]) == 1) { // Files list for encryption _FileList.Add(Item[1].ToString()); // Absolute file path // Total file size _TotalFileSize += Convert.ToInt64(Item[3]); } FileNumber++; } //---------------------------------------------------------------------- // 暗号化リストを生成(ディレクトリ) // Create file to encrypt list ( Directory ) //---------------------------------------------------------------------- else { // Directory _FileList.Add(FilePath); // Absolute file path foreach (ArrayList Item in GetFileList(ParentPath, FilePath)) { if ((worker.CancellationPending == true)) { e.Cancel = true; return(Tuple.Create(false, USER_CANCELED)); } if (NewArchiveName != "") { Item[2] = NewArchiveName + "\\" + Item[2]; } FileInfoList.Add("Fn_" + FileNumber.ToString() + ":" + // File number //Item[0] + "\t" + // TypeFlag ( Directory: 0, file: 1 ) //Item[1] + "\t" + // Absolute file path Item[2] + "\t" + // Relative file path Item[3].ToString() + "\t" + // File size Item[4].ToString() + "\t" + // File attribute Item[5].ToString() + "\t" + // Last write date Item[6].ToString() + "\t" + // Last write time Item[7].ToString() + "\t" + // Creation date Item[8].ToString()); // Creation time if (Convert.ToInt32(Item[0]) == 1) { // files only // Files list for encryption _FileList.Add(Item[1].ToString()); // Absolute file path // Total file size _TotalFileSize += Convert.ToInt64(Item[3]); } else { // Directory _FileList.Add(Item[1].ToString()); // Absolute file path } FileNumber++; } // end foreach (ArrayList Item in GetFilesList(ParentPath, FilePath)); } } // end foreach (string FilePath in FilePaths); //---------------------------------------------------------------------- // Check the disk space //---------------------------------------------------------------------- string RootDriveLetter = Path.GetPathRoot(OutFilePath).Substring(0, 1); if (RootDriveLetter == "\\") { // Network } else { DriveInfo drive = new DriveInfo(RootDriveLetter); DriveType driveType = drive.DriveType; switch (driveType) { case DriveType.CDRom: case DriveType.NoRootDirectory: case DriveType.Unknown: break; case DriveType.Fixed: // Local Drive case DriveType.Network: // Mapped Drive case DriveType.Ram: // Ram Drive case DriveType.Removable: // Usually a USB Drive // The drive is not available, or not enough free space. if (drive.IsReady == false || drive.AvailableFreeSpace < _TotalFileSize) { e.Result = NO_DISK_SPACE; // not available free space return(Tuple.Create(false, NO_DISK_SPACE)); } break; } } //---------------------------------------------------------------------- // Create header data string[] FileInfoText = (string[])FileInfoList.ToArray(typeof(string)); // Shift-JIS ( Japanese ) byteArray = Encoding.GetEncoding(932).GetBytes(string.Join("\n", FileInfoText)); ms.Write(byteArray, 0, byteArray.Length); Console.WriteLine(FileInfoText); // UTF-8 byteArray = Encoding.UTF8.GetBytes("\n" + string.Join("\n", FileInfoText).Replace("Fn_", "U_")); ms.Write(byteArray, 0, byteArray.Length); Console.WriteLine(FileInfoText); #if (DEBUG) //Output text file of header contents for debug. Int64 NowPosition = ms.Position; ms.Position = 0; //Save to Desktop folder. string DesktopPath = System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); string HeaderTextFilePath = Path.Combine(DesktopPath, "encrypt_header.txt"); FileStream fsDebug = new FileStream(HeaderTextFilePath, FileMode.Create, FileAccess.Write); ms.WriteTo(fsDebug); fsDebug.Close(); ms.Position = NowPosition; #endif // The Header of MemoryStream is encrypted using (Rijndael aes = new RijndaelManaged()) { aes.BlockSize = 256; // BlockSize = 16bytes aes.KeySize = 256; // KeySize = 16bytes aes.Mode = CipherMode.CBC; // CBC mode //aes.Padding = PaddingMode.Zeros; // Padding mode is "None". // Password if (PasswordBinary != null) { // Binary bufferPassword = PasswordBinary; } else { // Text bufferPassword = Encoding.UTF8.GetBytes(Password); //byte[] bufferPassword = Encoding.GetEncoding(932).GetBytes(Password); // Shift-JIS } // Password is 256 bit, so truncated up to 32 bytes or fill up the data size. // パスワードは256 bitなので、32バイトまで切り詰めるか、あるいはそのサイズまで埋める処理 for (int i = 0; i < bufferKey.Length; i++) { if (i < bufferPassword.Length) { // Cut down to 32 bytes characters. bufferKey[i] = bufferPassword[i]; } else { bufferKey[i] = 0; // Zero filled } } aes.Key = bufferKey; // Initilization Vector aes.GenerateIV(); outfs.Write(aes.IV, 0, 32); ms.Position = 0; //Encryption interface. ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); using (CryptoStream cse = new CryptoStream(outfs, encryptor, CryptoStreamMode.Write)) { //---------------------------------------------------------------------- // ヘッダーの暗号化 //---------------------------------------------------------------------- int len = 0; _AtcHeaderSize = 0; // exclude IV of header buffer = new byte[BUFFER_SIZE]; while ((len = ms.Read(buffer, 0, BUFFER_SIZE)) > 0) { cse.Write(buffer, 0, len); _AtcHeaderSize += len; } } } // end using (Rijndael aes = new RijndaelManaged()); } // end using (MemoryStream ms = new MemoryStream()); } // end using (FileStream outfs = new FileStream(OutFilePath, FileMode.Create, FileAccess.Write)); //---------------------------------------------------------------------- // 本体データの暗号化 //---------------------------------------------------------------------- using (FileStream outfs = new FileStream(OutFilePath, FileMode.OpenOrCreate, FileAccess.Write)) { byteArray = new byte[4]; // Back to current positon of 'encrypted file size' if (_fExecutable == true) { outfs.Seek(ExeOutFileSize + 28, SeekOrigin.Begin); // self executable file } else { outfs.Seek(28, SeekOrigin.Begin); } byteArray = BitConverter.GetBytes(_AtcHeaderSize); outfs.Write(byteArray, 0, 4); // Out file stream postion move to end outfs.Seek(0, SeekOrigin.End); // The Header of MemoryStream is encrypted using (Rijndael aes = new RijndaelManaged()) { aes.BlockSize = 256; // BlockSize = 16bytes aes.KeySize = 256; // KeySize = 16bytes aes.Mode = CipherMode.CBC; // CBC mode //aes.Padding = PaddingMode.PKCS7; // Padding mode is "PKCS7". // Password is 256 bit, so truncated up to 32 bytes or fill up the data size. for (int i = 0; i < bufferKey.Length; i++) { if (i < bufferPassword.Length) { //Cut down to 32bytes characters. bufferKey[i] = bufferPassword[i]; } else { bufferKey[i] = 0; } } aes.Key = bufferKey; // Initilization Vector byte[] iv = new byte[32]; RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); rng.GetNonZeroBytes(iv); aes.IV = iv; outfs.Write(iv, 0, 32); // Encryption interface. ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); using (CryptoStream cse = new CryptoStream(outfs, encryptor, CryptoStreamMode.Write)) { // zlib 2bytes header cse.WriteByte(0x78); // cse.WriteByte(0x01); //No Compression/low cse.WriteByte(0x9C); //Default Compression //cse.WriteByte(0xDA); //Best Compression Ionic.Zlib.CompressionLevel flv = Ionic.Zlib.CompressionLevel.Default; switch (AppSettings.Instance.CompressRate) { case 0: flv = Ionic.Zlib.CompressionLevel.Level0; break; case 1: flv = Ionic.Zlib.CompressionLevel.Level1; break; case 2: flv = Ionic.Zlib.CompressionLevel.Level2; break; case 3: flv = Ionic.Zlib.CompressionLevel.Level3; break; case 4: flv = Ionic.Zlib.CompressionLevel.Level4; break; case 5: flv = Ionic.Zlib.CompressionLevel.Level5; break; case 6: flv = Ionic.Zlib.CompressionLevel.Level6; break; case 7: flv = Ionic.Zlib.CompressionLevel.Level7; break; case 8: flv = Ionic.Zlib.CompressionLevel.Level8; break; case 9: flv = Ionic.Zlib.CompressionLevel.Level9; break; } using (Ionic.Zlib.DeflateStream ds = new Ionic.Zlib.DeflateStream(cse, Ionic.Zlib.CompressionMode.Compress, flv)) { int len = 0; foreach (string path in _FileList) { // Only file is encrypted if (File.Exists(path) == true) { buffer = new byte[BUFFER_SIZE]; using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) { len = 0; while ((len = fs.Read(buffer, 0, BUFFER_SIZE)) > 0) { ds.Write(buffer, 0, len); _TotalSize += len; string MessageText = ""; if (_TotalNumberOfFiles > 1) { MessageText = path + " ( " + _NumberOfFiles.ToString() + " files/ " + _TotalNumberOfFiles.ToString() + " folders )"; } else { MessageText = path; } MessageList = new ArrayList(); MessageList.Add(DECRYPTING); MessageList.Add(MessageText); float percent = ((float)_TotalSize / _TotalFileSize); worker.ReportProgress((int)(percent * 10000), MessageList); if (worker.CancellationPending == true) { e.Cancel = true; return(Tuple.Create(false, USER_CANCELED)); } } } } // end if (File.Exists(path) == true); } // end foreach (string path in _FileList); /* * Random r = new Random(); * byteArray = new byte[BUFFER_SIZE]; * r.NextBytes(byteArray); * ds.Write(buffer, 0, BUFFER_SIZE); */ } // end using ( Ionic.Zlib.DeflateStream ds); } // end using (CryptoStream cse); } // end using (Rijndael aes = new RijndaelManaged()); } // end using (FileStream outfs = new FileStream(OutFilePath, FileMode.Create, FileAccess.Write)); // Self-executable file if (fExecutable == true) { using (FileStream outfs = new FileStream(OutFilePath, FileMode.Open, FileAccess.Write)) { Int64 DataSize = outfs.Seek(0, SeekOrigin.End); DataSize = DataSize - _StartPos; byteArray = BitConverter.GetBytes(DataSize); outfs.Write(byteArray, 0, sizeof(Int64)); } } // Set the timestamp of encryption file to original files or directories if (_fKeepTimeStamp == true) { DateTime dtCreate = File.GetCreationTime((string)AppSettings.Instance.FileList[0]); DateTime dtUpdate = File.GetLastWriteTime((string)AppSettings.Instance.FileList[0]); DateTime dtAccess = File.GetLastAccessTime((string)AppSettings.Instance.FileList[0]); File.SetCreationTime(OutFilePath, dtCreate); File.SetLastWriteTime(OutFilePath, dtUpdate); File.SetLastAccessTime(OutFilePath, dtAccess); } //Encryption succeed. e.Result = ENCRYPT_SUCCEEDED; return(Tuple.Create(true, ENCRYPT_SUCCEEDED)); } // encrypt();
/// <summary> /// Multiple files or directories is encrypted by AES (exactly Rijndael) to use password string. /// 複数のファイル、またはディレクトリをAES(正確にはRijndael)を使って指定のパスワードで暗号化する /// </summary> /// <param name="FilePath">File path or directory path is encrypted</param> /// <param name="OutFilePath">Output encryption file name</param> /// <param name="Password">Encription password string</param> /// <returns>Encryption success(true) or failed(false)</returns> public Tuple <bool, int> Encrypt( object sender, DoWorkEventArgs e, string[] FilePaths, string OutFilePath, string Password, byte[] PasswordBinary, string NewArchiveName) { _AtcFilePath = OutFilePath; BackgroundWorker worker = sender as BackgroundWorker; // The timestamp of original file DateTime dtCreate = File.GetCreationTime(FilePaths[0]); DateTime dtUpdate = File.GetLastWriteTime(FilePaths[0]); DateTime dtAccess = File.GetLastAccessTime(FilePaths[0]); // Create Header data. ArrayList MessageList = new ArrayList(); MessageList.Add(READY_FOR_ENCRYPT); MessageList.Add(Path.GetFileName(OutFilePath)); worker.ReportProgress(0, MessageList); _FileList = new List <string>(); byte[] byteArray = null; // Salt Rfc2898DeriveBytes deriveBytes; if (PasswordBinary == null) { // String Password deriveBytes = new Rfc2898DeriveBytes(Password, 8, 1000); } else { // Binary Password byte[] random_salt = new byte[8]; RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); rng.GetBytes(random_salt); deriveBytes = new Rfc2898DeriveBytes(PasswordBinary, random_salt, 1000); } byte[] salt = deriveBytes.Salt; byte[] key = deriveBytes.GetBytes(32); byte[] iv = deriveBytes.GetBytes(32); using (FileStream outfs = new FileStream(OutFilePath, FileMode.Create, FileAccess.Write)) { // 自己実行形式ファイル(Self-executable file) if (_fExecutable == true) { ExeOutFileSize = rawData.Length; outfs.Write(rawData, 0, (int)ExeOutFileSize); } _StartPos = outfs.Seek(0, SeekOrigin.End); // Application version Version ver = ApplicationInfo.Version; short vernum = Int16.Parse(ver.ToString().Replace(".", "")); byteArray = BitConverter.GetBytes(vernum); outfs.Write(byteArray, 0, 2); // Input password limit byteArray = BitConverter.GetBytes(_MissTypeLimits); outfs.Write(byteArray, 0, 1); // Exceed the password input limit, destroy the file? byteArray = BitConverter.GetBytes(fBrocken); outfs.Write(byteArray, 0, 1); // Token that this is the AttacheCase file byteArray = Encoding.ASCII.GetBytes(STRING_TOKEN_NORMAL); outfs.Write(byteArray, 0, 16); // File sub version byteArray = BitConverter.GetBytes(DATA_FILE_VERSION); outfs.Write(byteArray, 0, 4); // The size of encrypted Atc header size ( reserved ) byteArray = BitConverter.GetBytes((int)0); outfs.Write(byteArray, 0, 4); // Salt outfs.Write(salt, 0, 8); // Cipher text header. using (MemoryStream ms = new MemoryStream()) { byteArray = Encoding.ASCII.GetBytes(AtC_ENCRYPTED_TOKEN + "\n"); ms.Write(byteArray, 0, byteArray.Length); int FileNumber = 0; string ParentPath; ArrayList FileInfoList = new ArrayList(); //---------------------------------------------------------------------- // Put together files in one ( Save as the name ). // 複数ファイルを一つにまとめる(ファイルに名前をつけて保存) if (NewArchiveName != "") { // Now time DateTime dtNow = new DateTime(); FileInfoList.Add("0:" + // File number NewArchiveName + "\\\t" + // File name "0" + "\t" + // File size "16" + "\t" + // File attribute dtNow.Date.Subtract(new DateTime(1, 1, 1)).TotalDays + "\t" + // Last write date dtNow.TimeOfDay.TotalSeconds + "\t" + // Last write time dtNow.Date.Subtract(new DateTime(1, 1, 1)).TotalDays + "\t" + // Creation date dtNow.TimeOfDay.TotalSeconds); // Creation time FileNumber++; } //---------------------------------------------------------------------- // When encrypt multiple files // 複数のファイルを暗号化する場合 foreach (string FilePath in FilePaths) { ParentPath = Path.GetDirectoryName(FilePath); if (ParentPath.EndsWith("\\") == false) // In case of 'C:\\' root direcroy. { ParentPath = ParentPath + "\\"; } if ((worker.CancellationPending == true)) { e.Cancel = true; return(Tuple.Create(false, USER_CANCELED)); } //---------------------------------------------------------------------- // 暗号化リストを生成(ファイル) // Create file to encrypt list ( File ) //---------------------------------------------------------------------- if (File.Exists(FilePath) == true) { ArrayList Item = GetFileInfo(ParentPath, FilePath); FileInfoList.Add(FileNumber.ToString() + ":" + // File number //Item[0] + "\t" + // TypeFlag ( Directory: 0, file: 1 ) //Item[1] + "\t" + // Absolute file path Item[2] + "\t" + // Relative file path Item[3].ToString() + "\t" + // File size Item[4].ToString() + "\t" + // File attribute Item[5].ToString() + "\t" + // Last write date Item[6].ToString() + "\t" + // Last write time Item[7].ToString() + "\t" + // Creation date Item[8].ToString() + "\t" + // Creation time Item[9].ToString()); // SHA-256 Hash string // files only if (Convert.ToInt32(Item[0]) == 1) { // Files list for encryption _FileList.Add(Item[1].ToString()); // Absolute file path // Total file size _TotalFileSize += Convert.ToInt64(Item[3]); } FileNumber++; } //---------------------------------------------------------------------- // 暗号化リストを生成(ディレクトリ) // Create file to encrypt list ( Directory ) //---------------------------------------------------------------------- else { // Directory _FileList.Add(FilePath); // Absolute file path foreach (ArrayList Item in GetFileList(ParentPath, FilePath)) { if ((worker.CancellationPending == true)) { e.Cancel = true; return(Tuple.Create(false, USER_CANCELED)); } if (NewArchiveName != "") { Item[2] = NewArchiveName + "\\" + Item[2]; } if ((int)Item[0] == 0) { // Directory FileInfoList.Add(FileNumber.ToString() + ":" + // File number Item[2] + "\t" + // Relative file path Item[3].ToString() + "\t" + // File size Item[4].ToString() + "\t" + // File attribute Item[5].ToString() + "\t" + // Last write date Item[6].ToString() + "\t" + // Last write time Item[7].ToString() + "\t" + // Creation date Item[8].ToString()); // Creation time } else { // File FileInfoList.Add(FileNumber.ToString() + ":" + // File number Item[2] + "\t" + // Relative file path Item[3].ToString() + "\t" + // File size Item[4].ToString() + "\t" + // File attribute Item[5].ToString() + "\t" + // Last write date Item[6].ToString() + "\t" + // Last write time Item[7].ToString() + "\t" + // Creation date Item[8].ToString() + "\t" + // Creation time Item[9].ToString()); // SHA-256 hash } if (Convert.ToInt32(Item[0]) == 1) { // files only // Files list for encryption _FileList.Add(Item[1].ToString()); // Absolute file path // Total file size _TotalFileSize += Convert.ToInt64(Item[3]); } else { // Directory _FileList.Add(Item[1].ToString()); // Absolute file path } FileNumber++; } // end foreach (ArrayList Item in GetFilesList(ParentPath, FilePath)); } // if (File.Exists(FilePath) == true); } // end foreach (string FilePath in FilePaths); //---------------------------------------------------------------------- // Check the disk space //---------------------------------------------------------------------- string RootDriveLetter = Path.GetPathRoot(OutFilePath).Substring(0, 1); if (RootDriveLetter == "\\") { // Network } else { DriveInfo drive = new DriveInfo(RootDriveLetter); DriveType driveType = drive.DriveType; switch (driveType) { case DriveType.CDRom: case DriveType.NoRootDirectory: case DriveType.Unknown: break; case DriveType.Fixed: // Local Drive case DriveType.Network: // Mapped Drive case DriveType.Ram: // Ram Drive case DriveType.Removable: // Usually a USB Drive // The drive is not available, or not enough free space. if (drive.IsReady == false || drive.AvailableFreeSpace < _TotalFileSize) { e.Result = NO_DISK_SPACE; // not available free space return(Tuple.Create(false, NO_DISK_SPACE)); } break; } } //---------------------------------------------------------------------- // Create header data string[] FileInfoText = (string[])FileInfoList.ToArray(typeof(string)); byteArray = Encoding.UTF8.GetBytes(string.Join("\n", FileInfoText)); ms.Write(byteArray, 0, byteArray.Length); #if (DEBUG) //Output text file of header contents for debug. Int64 NowPosition = ms.Position; ms.Position = 0; //Save to Desktop folder. string AppDirPath = Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath); string HeaderTextFilePath = Path.Combine(AppDirPath, "encrypt_header.txt"); using (FileStream fsDebug = new FileStream(HeaderTextFilePath, FileMode.Create, FileAccess.Write)) { ms.WriteTo(fsDebug); ms.Position = NowPosition; } #endif // The Header of MemoryStream is encrypted using (Rijndael aes = new RijndaelManaged()) { aes.BlockSize = 256; // BlockSize = 16bytes aes.KeySize = 256; // KeySize = 16bytes aes.Mode = CipherMode.CBC; // CBC mode //aes.Padding = PaddingMode.Zeros; // Padding mode is "None". aes.Key = key; aes.IV = iv; ms.Position = 0; //Encryption interface. ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); using (CryptoStream cse = new CryptoStream(outfs, encryptor, CryptoStreamMode.Write)) { //---------------------------------------------------------------------- // ヘッダーの暗号化 //---------------------------------------------------------------------- int len = 0; _AtcHeaderSize = 0; // exclude IV of header buffer = new byte[BUFFER_SIZE]; while ((len = ms.Read(buffer, 0, BUFFER_SIZE)) > 0) { cse.Write(buffer, 0, len); _AtcHeaderSize += len; } } } // end using (Rijndael aes = new RijndaelManaged()); } // end using (MemoryStream ms = new MemoryStream()); } // end using (FileStream outfs = new FileStream(OutFilePath, FileMode.Create, FileAccess.Write)); //---------------------------------------------------------------------- // 本体データの暗号化 //---------------------------------------------------------------------- using (FileStream outfs = new FileStream(OutFilePath, FileMode.OpenOrCreate, FileAccess.Write)) { try { byteArray = new byte[4]; // Back to current positon of 'encrypted file size' if (_fExecutable == true) { outfs.Seek(ExeOutFileSize + 24, SeekOrigin.Begin); // self executable file } else { outfs.Seek(24, SeekOrigin.Begin); } byteArray = BitConverter.GetBytes(_AtcHeaderSize); outfs.Write(byteArray, 0, 4); // Out file stream postion move to end outfs.Seek(0, SeekOrigin.End); // The Header of MemoryStream is encrypted using (Rijndael aes = new RijndaelManaged()) { aes.BlockSize = 256; // BlockSize = 16bytes aes.KeySize = 256; // KeySize = 16bytes aes.Mode = CipherMode.CBC; // CBC mode aes.Padding = PaddingMode.Zeros; // Padding mode aes.Key = key; aes.IV = iv; // Encryption interface. ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); using (CryptoStream cse = new CryptoStream(outfs, encryptor, CryptoStreamMode.Write)) { Ionic.Zlib.CompressionLevel flv = Ionic.Zlib.CompressionLevel.Default; switch (AppSettings.Instance.CompressRate) { case 0: flv = Ionic.Zlib.CompressionLevel.Level0; break; case 1: flv = Ionic.Zlib.CompressionLevel.Level1; break; case 2: flv = Ionic.Zlib.CompressionLevel.Level2; break; case 3: flv = Ionic.Zlib.CompressionLevel.Level3; break; case 4: flv = Ionic.Zlib.CompressionLevel.Level4; break; case 5: flv = Ionic.Zlib.CompressionLevel.Level5; break; case 6: flv = Ionic.Zlib.CompressionLevel.Level6; break; case 7: flv = Ionic.Zlib.CompressionLevel.Level7; break; case 8: flv = Ionic.Zlib.CompressionLevel.Level8; break; case 9: flv = Ionic.Zlib.CompressionLevel.Level9; break; } using (Ionic.Zlib.DeflateStream ds = new Ionic.Zlib.DeflateStream(cse, Ionic.Zlib.CompressionMode.Compress, flv)) { int len = 0; foreach (string path in _FileList) { // Only file is encrypted if (File.Exists(path) == true) { try { buffer = new byte[BUFFER_SIZE]; using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { len = 0; while ((len = fs.Read(buffer, 0, BUFFER_SIZE)) > 0) { ds.Write(buffer, 0, len); _TotalSize += len; string MessageText = ""; if (_TotalNumberOfFiles > 1) { MessageText = path + " ( " + _NumberOfFiles.ToString() + " / " + _TotalNumberOfFiles.ToString() + " files )"; } else { MessageText = path; } float percent = ((float)_TotalSize / _TotalFileSize); MessageList = new ArrayList(); MessageList.Add(ENCRYPTING); MessageList.Add(MessageText); worker.ReportProgress((int)(percent * 10000), MessageList); if (worker.CancellationPending == true) { fs.Dispose(); e.Cancel = true; return(Tuple.Create(false, USER_CANCELED)); } } } } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message.ToString()); e.Result = ERROR_UNEXPECTED; return(Tuple.Create(false, ERROR_UNEXPECTED)); } } // end if (File.Exists(path) == true); } // end foreach (string path in _FileList); /* * for (int i = 0; i < 10; i++) * { * Random r = new Random(); * byteArray = new byte[BUFFER_SIZE]; * r.NextBytes(byteArray); * cse.Write(buffer, 0, BUFFER_SIZE); * } */ } // end using ( Ionic.Zlib.DeflateStream ds); } // end using (CryptoStream cse); } // end using (Rijndael aes = new RijndaelManaged()); } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message.ToString()); e.Result = ERROR_UNEXPECTED; return(Tuple.Create(false, ERROR_UNEXPECTED)); } } // end using (FileStream outfs = new FileStream(OutFilePath, FileMode.Create, FileAccess.Write)); // Set the timestamp of encryption file to original files or directories if (_fKeepTimeStamp == true) { File.SetCreationTime(OutFilePath, dtCreate); File.SetLastWriteTime(OutFilePath, dtUpdate); File.SetLastAccessTime(OutFilePath, dtAccess); } else { dtUpdate = DateTime.Now; File.SetLastWriteTime(OutFilePath, dtUpdate); } //Encryption succeed. e.Result = ENCRYPT_SUCCEEDED; return(Tuple.Create(true, ENCRYPT_SUCCEEDED)); } // encrypt();