internal void closeDecMpeFile() { if (_decMpeFileInfo != null) { DecryptBtn.IsEnabled = false; DecQuestionListPanel.Children.RemoveRange(1, DecQuestionListPanel.Children.Count - 1); _decMpeFileInfo._encryptedFS.Close(); _decMpeFileInfo = null; } }
internal void openDecMpeFile(bool isShowMessage) { if (File.Exists(DecEncryptedFileTxt.Text) == false) { return; } var currentCursor = this.Cursor; this.Cursor = Cursors.Wait; string message; var decMPEfileInfo = MPECore.readHeader(DecEncryptedFileTxt.Text); if (decMPEfileInfo._errorDetailMessage != "") { if (isShowMessage) { message = ResourceService.Current.getMessage("MsgETargetNotMPE") + decMPEfileInfo._errorDetailMessage; // The specified file is not a Multiple Passwords Encrypted file.\r\n\r\nDetailed information: MessageBox.Show(message, "Error", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK); } goto EXIT; } int nQuestions = decMPEfileInfo._nQuestions; int nRequiredPasswords = decMPEfileInfo._nRequiredPasswords; // create UI _decPasswordTxts = new TextBox[nQuestions]; setFlag(decMPEfileInfo._flag); DecryptBtn.IsEnabled = true; DecNumRequiredPasswordsCmb.Items.Clear(); DecNumRequiredPasswordsCmb.Items.Add(nRequiredPasswords); DecNumRequiredPasswordsCmb.SelectedIndex = 0; for (int i = 0; i < nQuestions; ++i) { var question = decMPEfileInfo._decQuestions[i]; var border = new Border(); border.BorderThickness = TH_BOADER; border.BorderBrush = Brushes.Gray; border.Margin = TH_MARGIN_T5_R5; var scrollViewer = new ScrollViewer(); scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto; scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled; scrollViewer.Padding = TH_PADDING_5; border.Child = scrollViewer; var questionStackPanel = new StackPanel(); questionStackPanel.Orientation = Orientation.Vertical; scrollViewer.Content = questionStackPanel; var hintStackPanel = new StackPanel(); hintStackPanel.Orientation = Orientation.Horizontal; questionStackPanel.Children.Add(hintStackPanel); var hintLabel = new Label(); hintLabel.Content = "Hint" + (i + 1) + ":"; hintLabel.Width = HEADER_WIDTH; hintStackPanel.Children.Add(hintLabel); var hintTextBox = new TextBox(); hintTextBox.MinWidth = HINT_WIDTH; hintTextBox.IsEnabled = false; hintStackPanel.Children.Add(hintTextBox); hintTextBox.Text = question.hint; var questionRemoveButton = new Button(); questionRemoveButton.Content = "X"; questionRemoveButton.Width = HINT_REMOVE_BUTTON_WIDTH; questionRemoveButton.Margin = TH_MARGIN_L10; questionRemoveButton.IsEnabled = false; hintStackPanel.Children.Add(questionRemoveButton); var passwordStackPanel = new StackPanel(); passwordStackPanel.Orientation = Orientation.Horizontal; passwordStackPanel.Margin = TH_MARGIN_T5; questionStackPanel.Children.Add(passwordStackPanel); var passwordLabel = new Label(); passwordLabel.Content = "Password:"******"" && isShowMessage) { message = ResourceService.Current.getMessage("MsgWMPEInvalidFormat") + decMPEfileInfo._warningDetailMessage; // The specified file may not be decrypted properly.\r\n\r\nDetailed information: MessageBox.Show(message, "Warning", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK); } _decMpeFileInfo = decMPEfileInfo; EXIT: this.Cursor = currentCursor; }
internal static bool Decrypt( DecMPEFileInfo decMpeFileInfo, string[] passwords, string outputDir, IProgress <string> progress = null) { int nQuestions = decMpeFileInfo._nQuestions; int nRequiredPasswords = decMpeFileInfo._nRequiredPasswords; int nDecryptedQuestionKeys = 0; // Number of QuestionKeys that could be decoded. (J)複号できたQuestionKeyの数 int[] questionKeyIndexes = new int[nRequiredPasswords]; // Index of QuestionKeys that could be decoded. (J)複号できたQuestionKeyのIndex byte[] questionKeys = new byte[nRequiredPasswords * Crypto.AES_KEY_SIZE_BYTE]; // Combined Question Key (for decrypt dataKey) // check password for (int i = 0; i < nQuestions && nDecryptedQuestionKeys < nRequiredPasswords; ++i) { var passwordTxt = passwords[i]; if (passwordTxt == "") { continue; } var question = decMpeFileInfo._decQuestions[i]; byte[] password = Encoding.UTF8.GetBytes(passwordTxt); for (int j = 0; j < question.nPasswords; ++j) { var result = Crypto.decryptByte(question.encryptedQuestionKeys, j * Crypto.AES_KEY_SIZE_BYTE_WITH_PADDING, Crypto.AES_KEY_SIZE_BYTE_WITH_PADDING, password, Crypto.createSalt(i, j)); if (result != null) { if (result.Length != Crypto.AES_KEY_SIZE_BYTE) { // assertion throw new Exception("broken file"); } // store question key Buffer.BlockCopy(result, 0, questionKeys, nDecryptedQuestionKeys * Crypto.AES_KEY_SIZE_BYTE, Crypto.AES_KEY_SIZE_BYTE); questionKeyIndexes[nDecryptedQuestionKeys] = i; nDecryptedQuestionKeys += 1; break; } } } if (nDecryptedQuestionKeys < nRequiredPasswords) { return(false); // fail. number of passwords is not enough. } // decrypt data byte[] dataKey = null; int[][] combinaitons = Combination.enumerateCombination(nQuestions, nRequiredPasswords); for (int i = 0; i < combinaitons.Length; ++i) { if (combinaitons[i].SequenceEqual(questionKeyIndexes)) { dataKey = Crypto.decryptByte(decMpeFileInfo._encryptedDataKeys, i * Crypto.AES_KEY_SIZE_BYTE_WITH_PADDING, Crypto.AES_KEY_SIZE_BYTE_WITH_PADDING, questionKeys); break; } } if (dataKey == null) { throw new Exception("broken file"); } progress?.Report("(1/3) decripting archive."); // OK var tmpFileCompress = System.IO.Path.GetRandomFileName(); try { using (FileStream zipFS = new FileStream(tmpFileCompress, FileMode.Create)) { decMpeFileInfo._encryptedFS.Position = decMpeFileInfo._dataStartPosition; Crypto.decryptStream(decMpeFileInfo._encryptedFS, zipFS, dataKey); } // ZipFile.ExtractToDirectory can not read files unless Close() is done on zipFS //(J) zipFS を Close() しないと ZipFile.ExtractToDirectory はファイルを読み込めない try { progress?.Report("(2/3) creating output file(s)."); System.IO.Compression.ZipFile.ExtractToDirectory(tmpFileCompress, outputDir); } catch (Exception ex) { throw ex; } } finally { File.Delete(tmpFileCompress); } progress?.Report("(3/3) finished."); return(true); // succeed }
internal static DecMPEFileInfo readHeader(string encryptedFileName) { // Anaryze MPE File. //(J) MPEファイル解析 string errorDetailMessage = ""; string warningDetailMessage = ""; var encryptedFS = new FileStream(encryptedFileName, FileMode.Open); byte[] buf = new byte[AppConst.MPE_HEADER_SIZE]; int readByte = encryptedFS.Read(buf, 0, AppConst.MPE_HEADER_SIZE); if (readByte < AppConst.MPE_HEADER_SIZE) { errorDetailMessage = "File size is too small."; goto ERROR; } var reader = new MPEHeaderReader(buf); string headerConst = reader.ReadString(3); if (headerConst != AppConst.MPE_HEADER_CONST) { errorDetailMessage = "MPE Header constant is incorrect."; goto ERROR; } string warningDetail = ""; string archiveVersion = reader.ReadString(3); if (archiveVersion != AppConst.MPE_FORMAT_VERSION) { warningDetail += "archive format version:" + archiveVersion + " preferred:000\r\n"; } string encoderVersion = reader.ReadString(3); if (encoderVersion != AppConst.MPE_ENCODER_VERSION) { warningDetail += "encoder version:" + encoderVersion + " preferred:000\r\n"; } int questionHeaderLen = reader.ReadInt(); byte[] questionHeaderCRC = reader.ReadBytes(4); long dataLen = reader.ReadLong(); byte[] dataCRC = reader.ReadBytes(4); if (AppConst.MPE_HEADER_SIZE + questionHeaderLen + dataLen != encryptedFS.Length) { errorDetailMessage = "File size is incorrect."; goto ERROR; } // question header byte[] questionHeaderBuf = new byte[questionHeaderLen]; encryptedFS.Read(questionHeaderBuf, 0, questionHeaderLen); byte[] questionHeaderCRCVerify; using (CRC crcProvider = new CRC(CRCpolynomial.CRC32_C)) { questionHeaderCRCVerify = crcProvider.ComputeHash(questionHeaderBuf); } if (questionHeaderCRC.SequenceEqual(questionHeaderCRCVerify) == false) { warningDetail += "question header CRC32 unmatched.\r\n"; } // TODO:別スレッドで検算 long dataStartPosition = encryptedFS.Position; byte[] dataCRCVerify; using (CRC crcProvider = new CRC(CRCpolynomial.CRC32_C)) { dataCRCVerify = crcProvider.ComputeHash(encryptedFS); } if (dataCRC.SequenceEqual(dataCRCVerify) == false) { warningDetail += "data CRC32 unmatched.\r\n"; } byte flag; int nQuestions; int nRequiredPasswords; int nPasswordCombinations; byte[] encryptedDataKeys; DecQuestion[] questions; try { // parse question header reader = new MPEHeaderReader(questionHeaderBuf); flag = reader.ReadByte(); nQuestions = reader.ReadInt(); nRequiredPasswords = reader.ReadInt(); nPasswordCombinations = reader.ReadInt(); // assertion: nQuestions C nRequiredPasswords == nPasswordCombinations encryptedDataKeys = reader.ReadBytes(nPasswordCombinations * Crypto.AES_KEY_SIZE_BYTE_WITH_PADDING); questions = new DecQuestion[nQuestions]; for (int i = 0; i < nQuestions; ++i) { var question = new DecQuestion(); int hintLen = reader.ReadInt(); question.hint = reader.ReadString(hintLen); question.nPasswords = reader.ReadInt(); question.encryptedQuestionKeys = reader.ReadBytes(question.nPasswords * Crypto.AES_KEY_SIZE_BYTE_WITH_PADDING); questions[i] = question; } if (reader.Position != questionHeaderBuf.Length) { errorDetailMessage = "MPE Header is incorrect."; goto ERROR; } } catch (IndexOutOfRangeException) { errorDetailMessage = "MPE Header is incorrect."; goto ERROR; } var decMpeFileInfo = new DecMPEFileInfo(); decMpeFileInfo._encryptedFS = encryptedFS; decMpeFileInfo._dataStartPosition = dataStartPosition; decMpeFileInfo._flag = flag; decMpeFileInfo._nQuestions = nQuestions; decMpeFileInfo._nRequiredPasswords = nRequiredPasswords; decMpeFileInfo._encryptedDataKeys = encryptedDataKeys; decMpeFileInfo._decQuestions = questions; decMpeFileInfo._errorDetailMessage = errorDetailMessage; decMpeFileInfo._warningDetailMessage = warningDetailMessage; return(decMpeFileInfo); ERROR: encryptedFS.Close(); decMpeFileInfo = new DecMPEFileInfo(); decMpeFileInfo._warningDetailMessage = warningDetailMessage; decMpeFileInfo._errorDetailMessage = errorDetailMessage; return(decMpeFileInfo); }