質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

2回答

2404閲覧

C#のXOR暗号化をPHPでも同様に処理させたい。

fukkun0412

総合スコア37

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

1クリップ

投稿2018/10/10 18:37

編集2018/10/11 01:20

タイトルでも記載があるとおり私は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に原因があるのではないかと思われるのですが、
確証な原因を突き止めておりません。どの箇所に原因があるのか、その改善方法を是非ご教授願います。
正直まだ未熟なところはございますが、何卒よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2018/10/10 20:57

ソースコードはマークダウンのcode機能を利用してください。
m.ts10806

2018/10/10 20:58

C#はすごく明るいわけではないですが(一応業務経験はあります)、PHPのコードだけ提示されても結果比較ができませんので、C#で再現している内容、サンプルデータなど提示いただければと思います。
fukkun0412

2018/10/11 02:18

C#上では問題なく動作しております。サンプルデータというのは暗号化対象のファイルなどのことでしょうか?
guest

回答2

0

ベストアンサー

C#のほうは

C#

1byte_text[i] ^= Byte_Key[offset++ % Byte_Key.Length];

とoffsetで行っているので、行が変わっても値が継続されますが、
PHPのほうは

PHP

1$string[$i] = ($string[$i] ^ $key[$i % strlen($key)]);

と行が変わったら0から開始し使用するkeyがずれるんじゃないですかね?

追記

実際に試してみました。
まず、PHPのほうはockeghemさんが仰るとおり

PHP

1$key = pack("c*", 0xB5, 0x1A, 0x3, 0xF3, 0x7F, 0x42, 0xD3);

と変更しました。
C#のほうは

C#

1foreach (String str in list) 2{ 3 offset = 0; 4 write.Write(XOR_EnCrypt(str)); 5 write.Write(XOR_EnCrypt("\r\n")); 6}

と1行でoffsetをリセットし、改行コードを変更しました。
これにより、ファイルの最後が改行で終わるものに関しては一致しました。
但し、最後の行が
INSERT INTO Area VALUES (5,'4','フィールド4','00001.bmp');[EOF]
と改行が無いパターンですと、C#のほうが強制で改行コードを入れますので、一致しなくなります。

また、私はPHPのほうを殆ど知らないため、コードを変更する技量がありません。
この為、C#のほうをPHPに寄せましたが、暗号化仕様としてどのような状態が正しいのか分かりませんので、出力されたバイナリファイルが正しいのかは分かりません。

ただ、どちらも読み込み時にテキストファイルとして1行づつ処理するのではなく、バイナリファイルとして開いて、1バイトづつ処理するほうがいいのではないかと思います。

投稿2018/10/11 07:27

編集2018/10/11 08:13
YAmaGNZ

総合スコア10222

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fukkun0412

2018/10/11 09:27

ご回答ありがとうございます。 YAmaGNZさんのおっしゃった通り、XOR暗号化の処理の箇所で$iを指定しておりました。 おかげで解決いたしました。 ご協力いただきありがとうございました。
guest

0

以下の処理に問題があるように思います。

PHP

1$string[$i] = ($string[$i] ^ $key[$i % strlen($key)]); 2$string[$i] = ($string[$i] ^ $key[$i % strlen($key)]);

XORを2回実施しているように見えます。すると、元に戻ると思うのですが、いかがでしょうか?


XOR 2回は誤記とのこと。承知しました。
以下がまずそうに見えます。

$key = pack("cnv*", 0xB5, 0x1A, 0x3, 0xF3, 0x7F, 0x42, 0xD3);

$key をダンプすると以下のようになります。

<?php $key = pack("cnv*", 0xB5, 0x1A, 0x3, 0xF3, 0x7F, 0x42, 0xD3); var_dump(bin2hex($key)); 【実行結果】 string(26) "b5001a0300f3007f004200d300"

以下のようにすべきではないでしょうか?(pack関数の第1引数を "C*" に)

<?php $key = pack("C*", 0xB5, 0x1A, 0x3, 0xF3, 0x7F, 0x42, 0xD3); var_dump(bin2hex($key)); 【実行結果】 string(14) "b51a03f37f42d3"

結果見ました。改行の処理に問題があるようですね。

投稿2018/10/11 00:22

編集2018/10/11 07:05
ockeghem

総合スコア11701

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fukkun0412

2018/10/11 00:43

ご回答ありがとうございます。XORが2回実施されているのは、こちらの記述ミスです。訂正いたします。
fukkun0412

2018/10/11 03:51 編集

ご回答ありがとうございます。 ご回答通り実装してみましたが、一部はc#と同じ内容であることが確認出来ましたが、その他はまだ差分がある状態でございます。 ご回答いただいたもの以外に原因があるのでしょうか? 動作させると、下記のように文字化け?のようなものがありました。 動作結果の一部↓ "▒TP▒-▒▒TW▒_"▒b▒_▒▒OF▒_j▒*4▒On▒S▒▒▒▒04▒▒e▒e▒▒▒l▒▒OV▒▒▒▒▒=1▒Ou▒4a▒e▒▒61▒Ou▒6$▒Vy▒"
ockeghem

2018/10/11 05:32

文字化けしたものを見せられてもどうしようもないですね。 以下のすべてを16進ダンプのような可読性のある形式で示されたらどうでしょうか? 暗号化キー(これは現状のソースと同じ?) 元ファイルの内容 C#版の暗号結果 PHP版の暗号結果 もちろん、巨大な結果を貼り付けても皆が迷惑しますし、見るのが大変なので、数十バイト程度のものがよいと思います。
fukkun0412

2018/10/11 06:54 編集

ockeghemさん、こちらになります。 PHPの暗号結果に関してはvar_dump(bin2hex($line));を使用した値になります。 C#の暗号結果に関してはBitConverter.ToString(byte_text)を使用した値になります。 暗号化キー:ソースと同じ。(0xB5, 0x1A, 0x3, 0xF3, 0x7F, 0x42, 0xD3) 元ファイルの内容 INSERT INTO `Area` VALUES (1,'フィールド0','フィールド0','00001.bmp'); INSERT INTO `Area` VALUES (2,'フィールド1','フィールド1','00001.bmp'); INSERT INTO `Area` VALUES (3,'フィールド2','フィールド2','00001.bmp'); INSERT INTO `Area` VALUES (4,'フィールド3','フィールド3','00001.bmp'); INSERT INTO `Area` VALUES (5,'フィールド4','フィールド4','00001.bmp'); C#版の暗号結果 "FC5450B62D16F3FC5457BC5F2292C77F62935F1492F94F46A05F6AE2993DE070EAA15116F9804F9CC17856998AC3586EF456999610FDE13036A6E070D4A1503C2A24DF5872E3852A32DD1D2FA3923338" "360C80F04857D3360C87FA3A63B20D27B2D53A55B2331796E63A2BC1536530368FE071DCA15009F980589CC15A843D2FD49CC1465698A010FCFE3036B1E070F673F4993D33C34F72E29B786E83586BE8" "534DA03A108795534DA73062B3F46866921F6285F45656B62C62FB86362410FCD73037B9E070C3A1501EF9807A4D65FF92F980669CC0705699BF10FCE930369331D45365E3852A33C25120BEC53D2AC8" "0B9DE65F51A75F0B9DE15523933E30B6D47A23A53E0E86F04923DB4B6EF456999610FDE13036A6E070D4A1503C2924DF58A15020F981509CC16F5699A810FCCBE0923624C34F72E38434619E0F65FA8E" "4ABD2C0781E13A4ABD2B0DF3D55B71961E22F3E35B4FA63A11F39D2F2FD49CC1465698A010FCFE3036B1E070F676F4993DE070EAA15116F9804F9CC17856998AC7586EF4852A33C34E6CB1D86A24DA44" PHP版の暗号結果 string(162) "fc5450b62d16f3fc5457bc5f2292c77f62935f1492f94f46a05f6ae2993de070eaa15116f9804f9cc17856998ac3586ef456999610fde13036a6e070d4a1503c2a24df5872e3852a32dd1d2fa3923338f9" string(162) "fc5450b62d16f3fc5457bc5f2292c77f62935f1492f94f46a05f6ae1993de070eaa15116f9804f9cc17856998ac2586ef456999610fde13036a6e070d4a1503c2b24df5872e3852a32dd1d2fa3923338f9" string(162) "fc5450b62d16f3fc5457bc5f2292c77f62935f1492f94f46a05f6ae0993de070eaa15116f9804f9cc17856998ac1586ef456999610fde13036a6e070d4a1503c2824df5872e3852a32dd1d2fa3923338f9" string(162) "fc5450b62d16f3fc5457bc5f2292c77f62935f1492f94f46a05f6ae7993de070eaa15116f9804f9cc17856998ac0586ef456999610fde13036a6e070d4a1503c2924df5872e3852a32dd1d2fa3923338f9" string(162) "fc5450b62d16f3fc5457bc5f2292c77f62935f1492f94f46a05f6ae6993de070eaa15116f9804f9cc17856998ac7586ef456999610fde13036a6e070d4a1503c2e24df5872e3852a32dd1d2fa3923338f9" binファイルの差分を見てみると、最初のSQL文以外は全て差異がありました。
fukkun0412

2018/10/11 09:28

ockeghemさん、ご協力いただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問