예제 #1
0
 internal string   convertPassword(string password, AppConst.MPE_Flag flag)
 {
     if (flag.HasFlag(AppConst.MPE_Flag.isRemoveSpace))
     {
         password = Util.toRemoveInnerSpaces(password);
     }
     if (flag.HasFlag(AppConst.MPE_Flag.isIgnoreCase))
     {
         password = Util.toUpperCase(password);
     }
     if (flag.HasFlag(AppConst.MPE_Flag.isIgnoreZenHan))
     {
         password = Util.toZenkaku(password);
     }
     if (flag.HasFlag(AppConst.MPE_Flag.isIgnoreHiraKata))
     {
         password = Util.toHiragana(password);
     }
     return(password);
 }
예제 #2
0
        /**
         * First zip the file and then encrypt it.
         * (J) 最初にファイルをzip圧縮し、その後に暗号化する。
         *
         * encTargetList : Files or directories for encryption.
         * hints : question's hint
         * passwordLists : password List for hint.
         * nRequiredPasswords :  number of passwords are required for decryption.
         * flag : Encryption flag
         * outputFS : output file stream.
         */
        internal static void Encrypt(
            List <string> encTargetList,
            string[] hints,
            List <string>[] passwordLists,
            int nRequiredPasswords,
            AppConst.MPE_Flag flag,
            FileStream outputFS,
            IProgress <string> progress = null)
        {
            var tmpFileCompress = System.IO.Path.GetRandomFileName();   // temporary file name for zip file.

            try
            {
                progress?.Report("(1/4) creating archive.");
                // zip
                CompressionLevel compressionLevel = flag.HasFlag(AppConst.MPE_Flag.isNoCompress) ? CompressionLevel.NoCompression : CompressionLevel.Optimal;
                using (FileStream zipFS = File.Create(tmpFileCompress))
                {
                    using (ZipArchive archive = new ZipArchive(zipFS, ZipArchiveMode.Create))
                    {
                        foreach (var item in encTargetList)
                        {
                            string rootPathFile = item.ToString();
                            if (File.Exists(rootPathFile))
                            {   // Add the file as it is.
                                //(J) ファイルはそのまま追加
                                archive.CreateEntryFromFile(rootPathFile, System.IO.Path.GetFileName(rootPathFile), compressionLevel);
                            }
                            else if (Directory.Exists(rootPathFile))
                            {   // Add directory recursively
                                //(J) ディレクトリは再帰的に追加
                                string   parentPath = System.IO.Directory.GetParent(rootPathFile).ToString();
                                string[] pathFiles  = Directory.GetFileSystemEntries(rootPathFile, "*", System.IO.SearchOption.AllDirectories);
                                if (pathFiles.Length == 0)
                                {   // Empty directory added only entry.
                                    //(J) 空ディレクトリはエントリのみ追加
                                    archive.CreateEntry(System.IO.Path.GetFullPath(rootPathFile).Substring(parentPath.Length + 1) + "/");
                                }
                                foreach (var pathFile in pathFiles)
                                {
                                    string entryPath = pathFile.Substring(parentPath.Length + 1);   // Archive the specified directory as root. (J)指定したディレクトリをルートとしてアーカイブ
                                    if (File.Exists(pathFile))
                                    {
                                        archive.CreateEntryFromFile(pathFile, entryPath, compressionLevel);
                                    }
                                    else if (Directory.Exists(pathFile))
                                    {
                                        archive.CreateEntry(entryPath + "/");
                                    }
                                }
                            }
                        }
                    }
                }

                // File is not properly terminated without Dispose().
                // Dispose() archive, zipFS will also be closed(), so open it again.
                //(J) 一旦 archive を Dispose() しないと正しくファイルが終端化されない。
                //(J) archive を Dispose() すると zipFS も Close()されてしまうため、開きなおす。

                progress?.Report("(2/4) encrypting archive.");
                var tmpFileEncrypted = System.IO.Path.GetRandomFileName();  // temporary file name for encrypted file.
                try
                {
                    // encryption
                    RNGCryptoServiceProvider r = new RNGCryptoServiceProvider();
                    byte[] dataKey             = new byte[Crypto.AES_KEY_SIZE_BYTE]; // Encryption key for data.
                    r.GetBytes(dataKey);

                    using (FileStream zipFS = File.Open(tmpFileCompress, FileMode.Open))
                    {
                        using (FileStream encryptedFS = File.Create(tmpFileEncrypted))
                        {
                            Crypto.encryptStream(zipFS, encryptedFS, dataKey);
                        }
                    }
                    // Since it became unnecessary, try to delete here
                    //(J) 不要になったのでここで削除を試みる
                    File.Delete(tmpFileCompress);

                    using (FileStream encryptedFS = File.Open(tmpFileEncrypted, FileMode.Open))
                    {
                        Encrypt_2(encryptedFS, hints, passwordLists, nRequiredPasswords, flag, r, dataKey, outputFS, progress);
                    }
                    progress?.Report("(4/4) finished.");
                }
                finally
                {
                    File.Delete(tmpFileEncrypted);
                }
            }
            finally
            {
                File.Delete(tmpFileCompress);
            }
        }
예제 #3
0
        // Encrypt
        private async void EncryptButton_Click(object sender, RoutedEventArgs e)
        {
            DisableUIs();

            // input file check
            string message;

            if (EncFileNameLb.Items.Count == 0)
            {
                message = ResourceService.Current.getMessage("MsgETargetNotSpecified"); // Encryption target file is not specified.
                MessageBox.Show(message, "Error", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK);
                goto EXIT;
            }
            if (EncOutputFileTxt.Text.Trim() == "")
            {
                message = ResourceService.Current.getMessage("MsgEOutputNotSpecified"); // Output file is not specified.
                MessageBox.Show(message, "Error", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK);
                goto EXIT;
            }


            var fileList         = new List <string>();
            var dirList          = new List <string>();
            var notExistFileList = new List <string>();
            var encTargetList    = new List <string>();

            foreach (var item in EncFileNameLb.Items)
            {
                string pathFile = item.ToString();
                if (File.Exists(pathFile))
                {
                    fileList.Add(System.IO.Path.GetFileName(pathFile));
                    encTargetList.Add(pathFile);
                }
                else if (Directory.Exists(pathFile))
                {
                    var dir = new DirectoryInfo(pathFile);
                    dirList.Add(dir.Name);
                    encTargetList.Add(pathFile);
                }
                else
                {
                    notExistFileList.Add(pathFile);
                }
            }
            if (fileList.Count != fileList.Distinct().Count() || dirList.Count != dirList.Distinct().Count())
            {
                message = ResourceService.Current.getMessage("MsgETargetDuplicated"); // Encryption is impossible due to duplicate file name or folder name.
                MessageBox.Show(message, "Error", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK);
                goto EXIT;
            }
            if (notExistFileList.Count > 0)
            {
                message = ResourceService.Current.getMessage("MsgWFileNotExisted"); // The following file does not exist.
                foreach (var s in notExistFileList)
                {
                    message += "\r\n\t" + s;
                }
                if (EncFileNameLb.Items.Count == notExistFileList.Count)
                {
                    message += "\r\n\r\n" + ResourceService.Current.getMessage("MsgETargetNotExisted"); // There is no file to encrypt.
                    MessageBox.Show(message, "Error", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK);
                    goto EXIT;
                }
                else
                {
                    message += "\r\n\r\n" + ResourceService.Current.getMessage("MsgCEncryptOnlyExistFile"); // Encrypt with existing files only?
                    if (MessageBox.Show(message, "Confirmation", MessageBoxButton.YesNo, MessageBoxImage.Exclamation, MessageBoxResult.No) == MessageBoxResult.No)
                    {
                        goto EXIT;
                    }
                }
            }

            // input password check
            int nQuestions         = _encQuestionList.Count;
            int nRequiredPasswords = int.Parse(EncNumRequiredPasswordsCmb.Text);

            if ((bool)EncTrimChk.IsChecked)
            {
                foreach (var question in _encQuestionList)
                {
                    foreach (var passwordText in question._passwordStackPanel.Children.OfType <TextBox>())
                    {
                        passwordText.Text = passwordText.Text.Trim();
                    }
                }
            }

            string[]        hintList       = new string[nQuestions];
            List <string>[] passwordList   = new List <string> [nQuestions];
            int             nDummyQuestion = 0;

            for (int i = 0; i < _encQuestionList.Count; ++i)
            {
                var question = _encQuestionList[i];

                hintList[i]     = question._hintTextBox.Text;
                passwordList[i] = new List <string>();

                foreach (var passwordText in question._passwordStackPanel.Children.OfType <TextBox>())
                {
                    if (passwordText.Text != "")
                    {
                        passwordList[i].Add(passwordText.Text);
                    }
                }
                if (passwordList[i].Count == 0)
                {
                    nDummyQuestion += 1;
                }
            }

            if (nDummyQuestion > 0)
            {
                message = ResourceService.Current.getMessage("MsgWDummyQuestion"); // A Question without a password is a dummy Question.
                if (nQuestions - nDummyQuestion < nRequiredPasswords)
                {
                    message += "\r\n" + ResourceService.Current.getMessage("MsgWUndecrytableArchive"); // Because it is less than the number of passwords required for decryption, an archive that can not be decrypted is created.
                }
                MessageBox.Show(message, "Warning", MessageBoxButton.OK, MessageBoxImage.Exclamation, MessageBoxResult.OK);
            }

            if (File.Exists(EncOutputFileTxt.Text))
            {
                message = ResourceService.Current.getMessage("MsgCOverwriteOutputFile"); // The output file exists. Do you want to overwrite?
                if (MessageBox.Show(message, "Confirmation", MessageBoxButton.YesNo, MessageBoxImage.Exclamation, MessageBoxResult.No) == MessageBoxResult.No)
                {
                    goto EXIT;
                }
            }

            FileStream outputFS;

            try
            {
                outputFS = File.Create(EncOutputFileTxt.Text);
            }
            catch (Exception ex)
            {
                message = ResourceService.Current.getMessage("MsgEFailCreateFile") + ex.Message; // Failed to create the output file.\r\n\r\nDetailed information:
                MessageBox.Show(message, "Error", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK);
                goto EXIT;
            }

            message = ResourceService.Current.getMessage("MsgCStartEncryption"); // Start encryption.
            if (MessageBox.Show(message, "Confirmation", MessageBoxButton.OKCancel, MessageBoxImage.Question, MessageBoxResult.Cancel) == MessageBoxResult.Cancel)
            {
                outputFS.Close();
                goto EXIT;
            }


            AppConst.MPE_Flag flag = createFlag();
            foreach (var list in passwordList)
            {
                for (int i = 0; i < list.Count; ++i)
                {
                    list[i] = convertPassword(list[i], flag);
                }
            }

            var currentCursor = this.Cursor;

            try
            {
                this.Cursor = Cursors.Wait;
                var p = new Progress <string>(ShowProgress);
                await Task.Run(() => { MPECore.Encrypt(encTargetList, hintList, passwordList, nRequiredPasswords, flag, outputFS, p); });
            }
            catch (Exception ex)
            {
                message = ResourceService.Current.getMessage("MsgEFailEncryption") + ex.Message; // Encryption failed.\r\n\r\nDetailed information:
                MessageBox.Show(message, "Error", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK);
                goto EXIT;
            }
            finally
            {
                outputFS.Close();
                this.Cursor = currentCursor;
            }
            message = ResourceService.Current.getMessage("MsgIEndEncryption"); // Encryption is complete.
            MessageBox.Show(message, "Succeed", MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK);

EXIT:
            EnableUIs();
        }
예제 #4
0
        /**
         * encryption
         */
        internal static void Encrypt_2(
            FileStream encryptedFS,
            string[] hintList,
            List <string>[] passwordList,
            int nRequiredPasswords,
            AppConst.MPE_Flag flag,
            RNGCryptoServiceProvider r,
            byte[] dataKey,
            FileStream outputFS,
            IProgress <string> progress = null)
        {
            // generate questionKeys, encryptedQuestionKeys
            int nQuestions = hintList.Length;

            byte[][]   questionKeys          = new byte[nQuestions][];
            byte[][][] encryptedQuestionKeys = new byte[nQuestions][][];
            for (int i = 0; i < nQuestions; ++i)
            {
                questionKeys[i] = new byte[Crypto.AES_KEY_SIZE_BYTE];   // Encryption key for dataKey
                r.GetBytes(questionKeys[i]);

                // encrypt questionKey
                // Based on the number of passwords, assign the location of the password to encrypt questionKeys. In order to hide the number of passwords, dummy indexes are also included.
                // For example, when three passwords are set in the Question being processed, the following values ​​are randomly set in passwordEncryptIndexes.
                // passwordEncryptIndexes = {1, -1, 0, 2, -1}
                // In this case, encryptedQuestionKeys is [question 0] encrypted questionKey with password 1, [1]: dummy, [2]: questionKey encrypted with password 0, [3]: questionKey encrypted with password 2 , [4]: ​​Dummy is stored.
                //(J) パスワードの個数をもとに、questionKeysを暗号化するパスワードの位置を割り当てる。パスワード個数を隠蔽するため、ダミーのインデクスも含まれる。
                //(J) たとえば、処理中の Question にパスワードが3つ設定されている場合に、passwordEncryptIndexes には以下のような値をランダムに設定する。
                //(J) passwordEncryptIndexes = {1, -1, 0, 2, -1}
                //(J) この場合はencryptedQuestionKeys は、[0]:パスワード1で暗号化されたquestionKey, [1]:ダミー, [2]:パスワード0で暗号化されたquestionKey, [3]:パスワード2で暗号化されたquestionKey, [4]:ダミー が格納される。
                int[] passwordEncryptIndexes = alllocPasswordEncryptIndexes(passwordList[i].Count);
                encryptedQuestionKeys[i] = new byte[passwordEncryptIndexes.Length][];
                for (int j = 0; j < passwordEncryptIndexes.Length; ++j)
                {
                    if (passwordEncryptIndexes[j] >= 0)
                    {   // real password
                        String password      = passwordList[i][passwordEncryptIndexes[j]];
                        byte[] passwordBytes = Encoding.UTF8.GetBytes(password);

                        encryptedQuestionKeys[i][j] = Crypto.encryptByte(questionKeys[i], passwordBytes, Crypto.createSalt(i, j));
                        if (encryptedQuestionKeys[i][j].Length != Crypto.AES_KEY_SIZE_BYTE_WITH_PADDING)
                        {                                        // assertion
                            throw new Exception("system error"); //!
                        }
                    }
                    else
                    {   // dummy key
                        byte[] dummyKey = new byte[Crypto.AES_KEY_SIZE_BYTE_WITH_PADDING];
                        r.GetBytes(dummyKey);
                        encryptedQuestionKeys[i][j] = dummyKey;
                    }
                }
            }

            // generate encryptedDataKey
            int[][]  combinaiton         = Combination.enumerateCombination(nQuestions, nRequiredPasswords);
            byte[]   combinedQuestionKey = new byte[nRequiredPasswords * Crypto.AES_KEY_SIZE_BYTE];
            byte[][] encryptedDataKey    = new byte[combinaiton.Length][];
            for (int i = 0; i < combinaiton.Length; ++i)
            {
                // Create a password for dataKey from multiple question keys.
                //(J) 複数のquestion key から dataKey 用のパスワードを作成する
                for (int j = 0; j < combinaiton[i].Length; ++j)
                {
                    int qkIdx = combinaiton[i][j];
                    Buffer.BlockCopy(questionKeys[qkIdx], 0, combinedQuestionKey, j * Crypto.AES_KEY_SIZE_BYTE, Crypto.AES_KEY_SIZE_BYTE);
                }

                encryptedDataKey[i] = Crypto.encryptByte(dataKey, combinedQuestionKey);
                if (encryptedDataKey[i].Length != Crypto.AES_KEY_SIZE_BYTE_WITH_PADDING)
                {                                        // assertion
                    throw new Exception("system error"); //!
                }
            }

            progress?.Report("(3/4) creating output file.");
            // create question Header (for MPE File)
            using (var questionHeaderMS = new MemoryStream())
            {
                byte[] bytes;
                //	flag				1
                questionHeaderMS.WriteByte((byte)flag);
                //	nQuestions			4
                bytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(nQuestions));
                questionHeaderMS.Write(bytes, 0, bytes.Length);
                //	nRequiredPasswords		4
                bytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(nRequiredPasswords));
                questionHeaderMS.Write(bytes, 0, bytes.Length);
                //	nPasswordCombinations	4
                bytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(encryptedDataKey.Length));
                questionHeaderMS.Write(bytes, 0, bytes.Length);
                //	encryptedDataKeys	n  * 48
                for (int i = 0; i < encryptedDataKey.Length; ++i)
                {
                    questionHeaderMS.Write(encryptedDataKey[i], 0, encryptedDataKey[i].Length);
                }

                //	Question			n
                for (int i = 0; i < nQuestions; ++i)
                {
                    // hint string len      4
                    byte[] hintStrBytes = Encoding.UTF8.GetBytes(hintList[i]);
                    bytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(hintStrBytes.Length));
                    questionHeaderMS.Write(bytes, 0, bytes.Length);
                    // hint string          n
                    questionHeaderMS.Write(hintStrBytes, 0, hintStrBytes.Length);
                    // nPasswords            4
                    bytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(encryptedQuestionKeys[i].Length));
                    questionHeaderMS.Write(bytes, 0, bytes.Length);
                    // encryptedQuestionKeys n * 48
                    for (int j = 0; j < encryptedQuestionKeys[i].Length; ++j)
                    {
                        questionHeaderMS.Write(encryptedQuestionKeys[i][j], 0, encryptedQuestionKeys[i][j].Length);
                    }
                }

                Encrypt_3(questionHeaderMS, encryptedFS, outputFS);
            }
        }