タイトルでも記載があるとおり私はC#でのXOR暗号化の処理をPHPで実装しようとしております。
・条件
・C#でXOR暗号化したbinファイルとPHPでXOR暗号化したbinファイルが同じ内容であること。
・暗号化に使用するkeyは同じもの
https://code.i-harness.com/ja/q/dfe68f
上記のサイトを参考にして、以下のように実装いたしました。
PHP
1<?php 2 暗号化のカギ 3 $key = pack("cnv*", 0xB5, 0x1A, 0x3, 0xF3, 0x7F, 0x42, 0xD3); 4 try{ 5 foreach(glob('/home/sql/{*.sql}',GLOB_BRACE) as $file){ 6 if(is_file($file) && strpos($file,'Seal') === false){ 7 $lines = file($file); 8 $filename = basename($file,'.sql'); 9 バイナリに書き込み 10 if(file_exists("/home/sql/binfile/{$filename}.bin")) { 11 特になし 12 }else{ 13 touch("/home/sql/binfile/{$filename}.bin"); 14 } 15 16 $fp = fopen("/home/sql/en/binfile/{$filename}.bin", 'wb'); 17 一行ずつXOR暗号化していき書き込んでいく 18 foreach ($lines as $line) { 19 $xor_string = xor_encrypt($line,$key); 20 fwrite($fp, $xor_string); 21 } 22 fclose($fp); 23 } 24 } 25 26 }catch (Exception $e) { 27 echo "エラー:" . $e->getMessage(); 28 } 29 30 XOR暗号化 31 function xor_encrypt($string, $key) { 32 for($i = 0; $i < strlen($string); $i++) { 33 $string[$i] = ($string[$i] ^ $key[$i % strlen($key)]); 34 } 35 return $string; 36 } 37 38?
C#でのXOR暗号化のソースは以下の物になります。
C#
1using System; 2using System.Collections.Generic; 3using System.IO; 4using System.Linq; 5using System.Text; 6using System.Threading.Tasks; 7using System.Windows.Forms; 8 9namespace updatebinfile 10{ 11 class Program 12 { 13 static string SQLPath = "/home/sql/"; 14 static string binPath = "/home/sql/binfile/"; 15 static private byte[] Byte_Key = { 0xB5, 0x1A, 0x3, 0xF3, 0x7F, 0x42, 0xD3 }; 16 static int offset = 0; 17 static void Main(string[] args) 18 { 19 String[] FileName = Directory.GetFiles(SQLPath); 20 foreach(String file in FileName) 21 { 22 if (!file.Contains(".txt")) 23 { 24 String UpdateFile = Encrypt(file); 25 if(File.Exists(binPath + Path.GetFileName(UpdateFile))) 26 { 27 File.Delete(binPath + Path.GetFileName(UpdateFile)); 28 } 29 File.Move(UpdateFile, binPath + Path.GetFileName(UpdateFile)); 30 } 31 } 32 } 33 34 static private void CreateBinFile(String FileName) 35 { 36 37 38 } 39 40 static private String Encrypt(String FileName) 41 { 42 String file = System.String.Empty; 43 offset = 0; 44 //拡張子を判定 45 { 46 String[] split = FileName.Split('.'); 47 String extension = "." + split[split.Length - 1]; 48 file = ReplaceLast(FileName, extension, ".bin"); 49 } 50 51 //読み込み開始 52 { 53 List<String> list = new List<String>(); 54 55 using (System.IO.StreamReader cReader = new System.IO.StreamReader(FileName, new System.Text.UTF8Encoding(false))) 56 { 57 58 while (!cReader.EndOfStream) 59 { 60 list.Add(cReader.ReadLine()); 61 } 62 } 63 64 { 65 //既に出力先に同名のファイルがある場合は削除しておく 66 System.IO.FileInfo cFileInfo = new System.IO.FileInfo(file); 67 // ファイルを削除する 68 cFileInfo.Delete(); 69 } 70 71 using (System.IO.BinaryWriter write = new BinaryWriter(File.OpenWrite(file), new System.Text.UTF8Encoding(false))) 72 { 73 foreach (String str in list) 74 { 75 write.Write(XOR_EnCrypt(str)); 76 write.Write(XOR_EnCrypt("\n")); 77 } 78 } 79 80 //書き込み終わったので、復号化してlistに入ってある要素と違いが無いかを確認する 81 { 82 String str = XOR_getDecryptString(file); 83 String[] split = str.Split('\n'); 84 int str_offset = 0; 85 foreach (String line in list) 86 { 87 if (!line.Equals(split[str_offset++])) 88 { 89 MessageBox.Show("XOR暗号化エラー\n出力ファイルと元ファイルで差異があります\n" + line + "\n" + split[str_offset], "NotCheckUploadServer", MessageBoxButtons.OK, MessageBoxIcon.Error); 90 } 91 } 92 while (split.Length > str_offset) 93 { 94 String checkString = split[str_offset++]; 95 if (checkString.Length != 0) 96 { 97 MessageBox.Show("XOR暗号化エラー\n出力ファイルと元ファイルで差異があります\n" + "[" + checkString + "]", "NotCheckUploadServer", MessageBoxButtons.OK, MessageBoxIcon.Error); 98 } 99 } 100 } 101 102 } 103 return file; 104 105 } 106 107 private static String ReplaceLast(String str, String key, String val) 108 { 109 int last = str.LastIndexOf(key); 110 111 if (last != -1) 112 { 113 //StringBuilderを作成する 114 System.Text.StringBuilder sb = new System.Text.StringBuilder(str); 115 116 sb.Replace(key, val, last, str.Length - last); 117 118 return sb.ToString(); 119 } 120 121 return str; 122 } 123 124 private static byte[] XOR_EnCrypt(String text) 125 { 126 byte[] byte_text = new System.Text.UTF8Encoding(false).GetBytes(text); 127 128 for (int i = 0; i < byte_text.Length; i++) 129 { 130 byte_text[i] ^= Byte_Key[offset++ % Byte_Key.Length]; 131 } 132 return byte_text; 133 } 134 135 private static string XOR_getDecryptString(String FileName) 136 { 137 offset = 0; 138 List<byte> list = new List<byte>(); 139 try 140 { 141 using (System.IO.BinaryReader read = new BinaryReader(File.OpenRead(FileName))) 142 { 143 long length = read.BaseStream.Length; 144 145 for (long i = 0; i < length; ++i) 146 { 147 list.Add(XOR_Decrypt(read.ReadByte())); 148 } 149 } 150 } 151 catch (Exception e) 152 { 153 MessageBox.Show("エラーA:\n" + e.Message, "ERR"); 154 } 155 return new System.Text.UTF8Encoding(false).GetString(list.ToArray()); 156 } 157 158 private static byte XOR_Decrypt(byte text) 159 { 160 return (text ^= Byte_Key[offset++ % Byte_Key.Length]); 161 } 162 } 163} 164
上記のPHPを動作させるとbinファイルは正常に作成され、データも同じ容量なのですが、WinMergeなどで見てみるとバイナリデータに大量の差分がありました。
自分なりに考察したのは暗号化に使用する$keyに原因があるのではないかと思われるのですが、
確証な原因を突き止めておりません。どの箇所に原因があるのか、その改善方法を是非ご教授願います。
正直まだ未熟なところはございますが、何卒よろしくお願いいたします。
回答2件
あなたの回答
tips
プレビュー