VB6からMSXML2.xmlhttpを利用しDESで暗号化したデータを送信。
その後php側で復号化する処理をしています。
短い電文は問題なかったのですが少し長い物に関しては復号化で
PHPで文字化けするようになりました。
VB6側で作成した暗号文(16進数に変更してあります。)
E91EBF24F61D481E82DDF83849846DA0F459BCB47A3744487A338E3C361D7AA604F102581C396989D888E3A14DACB33F2839959F4E2E23B7DB30B611 2 78E1324A0884AE7CF0D9C48
PHP側のPOSTで受け取った時の暗号文
E91EBF24F61D481E82DDF83849846DA0F459BCB47A3744487A338E3C361D7AA604F102581C396989D888E3A14DACB33F2839959F4E2E23B7DB30B611 5C2 78E1324A0884AE7CF0D9C48
スペースで空けている部分が異なる部分です。
VB6 では 2
PHP では 5C2
5Cが不必要なものです。
これが入っている為復号化の時に文字化けがしてしまいます。
VB6側で送信前のバイト配列の内容は問題ありませんでした。
PHP側の問題かもしれません。
よろしくお願いします。
環境 VB6SP6 , PHP5.2.1 , WinXP
Public Function Execute(ByVal sql As String) As clsMysql
Dim cDes As clsPhpDES
Dim xmlhttp As MSXML2.xmlhttp
Dim cMysql As clsMysql
Dim sqlByte() As Byte
Dim SendByte() As Byte
Dim getByte() As Byte
'送信データ電文作成
Call StringAppend("&q=")
'暗号化するかどうか
If EncryptFlg = False Then
Call StringAppend(sql)
Else
Set cDes = New clsPhpDES
sqlByte = cDes.Triple_Des_Encrypt(DesKey, sql)
If InStr(Command, "-t") > 0 Then
Debug.Print cDes.StringToHex(sqlByte)
End If
Call ByteAppend(sqlByte)
Call StringAppend("&enc=1")
Set cDes = Nothing
End If
Set xmlhttp = New MSXML2.xmlhttp
'POSTで対象URLに接続 3番目の引数は同期モードか非同期モードかの区別
Call xmlhttp.Open("POST", TargetURL, False)
'ヘッダー送信
Call xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
'文字コード変換(Shift_JISからUTF-8へ)
SendByte = ShiftJIStoUFT8(SendNoSqlByte)
If InStr(Command, "-t") > 0 Then
Set cDes = New clsPhpDES
Debug.Print cDes.StringToHex(SendByte)
Set cDes = Nothing
End If
'送信
Call xmlhttp.send(SendByte)
'データを受け取る
getByte = xmlhttp.responseBody()
Set xmlhttp = Nothing
'デバック用
Call debug_Chk(getByte)
'受け取ったバイナリーデータを加工する
Set cMysql = New clsMysql
'暗号化しているかどうかセットする
cMysql.setEncrypt = EncryptFlg
If cMysql.DataChg(getByte) = True Then
Set Execute = cMysql
End If
End Function
Private Sub StringAppend(ByVal s As String)
Dim adoStream As ADODB.Stream
Dim NewByte() As Byte
Dim i As Long
Set adoStream = New ADODB.Stream
With adoStream
.Charset = "Shift_JIS"
.Type = adTypeText
Call .Open
Call .WriteText(s)
.Position = 0
.Type = adTypeBinary
NewByte = .Read()
Call .Close
End With
Set adoStream = Nothing
For i = 0 To UBound(NewByte)
ReDim Preserve SendNoSqlByte(UBound(SendNoSqlByte) + 1)
SendNoSqlByte(UBound(SendNoSqlByte)) = NewByte(i)
Next
End Sub
Private Sub ByteAppend(ByRef data() As Byte)
Dim i As Long
For i = 0 To UBound(data)
ReDim Preserve SendNoSqlByte(UBound(SendNoSqlByte) + 1)
SendNoSqlByte(UBound(SendNoSqlByte)) = data(i)
Next
End Sub
Private Function ShiftJIStoUFT8(ByRef data() As Byte) As Byte()
Dim adoStream As ADODB.Stream
Set adoStream = New ADODB.Stream
With adoStream
.Charset = "UTF-8"
.Type = adTypeBinary
Call .Open
Call .Write(data)
.Position = 0
ShiftJIStoUFT8 = .Read()
Call .Close
End With
Set adoStream = Nothing
End Function
> 5Cが不必要なものです。
5C って、エスケープ文字としても使われる「\」のコードですね…。
> VB6側で送信前のバイト配列の内容は問題ありませんでした。
このような時は、どの時点でデータが破損したかを、正確に突き止める必要があるでしょう。
(a) そもそも、処理前の元データは正しいのか?
(b) エンコードした後のバイト配列の内容は正しいか?
(c) それを xmlhttp.send した際、Web 上に流されたデータは正しいか?
(d) Web サーバ側で受け取ったとき、それをデータ破損せずに受け取れているか?
なお、手順 c の確認には、フリーソフトの InetSpy 等が便利です。
> PHP側の問題かもしれません。
もし、上記 d で問題があるとしたら、この掲示板では板違いですね。
> Private Function ShiftJIStoUFT8(ByRef data() As Byte) As Byte()
これ、プロシージャの名前のスペルミスはさておき、実装がおかしいです。
バイナリモードで書きこんで、バイナリモードで読み直しているだけなので、
何の変換にもなっていません。(Charset プロパティは、テキストモード専用です)
Shift_JIS バイナリを UTF-8 バイナリにするなら、この部分の処理は、
下記のいずれかに置き換える必要があるでしょう。
=== 案(1) String → UTF-8 Binary にする手法 ===
1. Shift_JIS バイナリを、StrConv 関数の vbUnicode で、
VB の標準的な文字列に変換する。
2. それを adTypeText / UTF-8 モードの Stream に WriteText する。
3. その Stream の Position を 0 に戻す。
4. Type プロパティを、adTypeBinary に変更。
5. 先頭の BOM 3 バイトも必要なら、Position は 0 のままにしておき、
先頭の EF BB BF が不要なら、Position を 3 にしておく。
6. Read メソッドで取り出せば、UTF-8 バイナリの取得が完了。
=== 案(2) Shift_JIS Binary → UTF-8 Binary にする手法 ===
こちらは、任意の文字コード変換に使える手法です。
1. adTypeBinary で開いた Stream を用意する。
2. そこに、変換元のバイナリ(Shift_JISデータ)を Write する。
3. Position を 0 に戻す。
4. Type を adTypeText に変更。
5. Charset に、変換元の文字コード "Shift_JIS" を指定。
6. ReadText で、VB の標準的な文字列として取得する。
7. もうひとつ、別の Stream を用意し、adTypeText / UTF-8 モードで開いておく。
8. 手順 6 で得た文字列を、手順 7 の Stream に WriteText。
あとは、案(1)の手順 2 以降の手法と同様。
魔界の仮面弁士さま
スペルミス指摘されるまでまったく気づきませんでした・・・・
恥ずかしい限りです。
ADODB.Streamの変換手順ありがとうございました。
案(2)今後使えそうなので関数化しました。
過去ログ内容を見たのですが前回掲ヲしたプログラムではsendの際Byte配列を渡していたので
結局Shift_JISのコードの入ったものを送っていたんですね。
http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200501/05010059.txt
>「内部処理形ョがStringのVariant型」をsendすると、
>文字列がUTF-8で送信されます。
>この場合はStrConv関数を併用して、sendの引数に、
>「内部処理形ョがByte配列のVariant型」を渡してみてください。
>(a) そもそも、処理前の元データは正しいのか?
VB側で秘密Key(24Byte)と平文をunicode→shift_jisに変換後3DESで暗号化。
変換した時点で文字として意味のないバイナリデータになります。
>(b) エンコードした後のバイト配列の内容は正しいか?
単体でVB6版とPHP版で同じキーで同じ文字列を暗号化したものは同じ内容のバイト配列になりました。
今回の「5C」が入らないものをPHP側で作成し複合化するとVB側で暗号化した文字列が出てきました。
>(c) それを xmlhttp.send した際、Web 上に流されたデータは正しいか?
InetSpy導入しました。
VB6側でMSXML2.XMLHTTPのsendで送る時のSendByteの内容をウォッチリストで確認しました。
sendbyte(64)「17=&h11」
sendbyte(65)「39=&h27」
になっていて「92=&h5C」が入っていませんでした。
PHP側のスクリプトでPOSTで受け取った物を16進数に変換して出力。
不必要な「5C」が混入していました。
InetSpyの情報
リクエスト情報
test=・ソ$・Hみ・I・瑶Y軸z7DHz3・6zヲ・X9i華遺@M?(9福N.#頚0カ'・$焉E舅
廩
応答情報
16進数データ: E91EBF24F61D481E82DDF83849846DA0F459BCB47A3744487A338E3C361D7AA604F102581C396989D888E3A14DACB33F2839959F4E2E23B7DB30B6115C278E1324A0884AE7CF0D9C48
受信データ:
・ソ$・Hみ・I・瑶Y軸z7DHz3・6zヲ・X9i華遺@M?(9福N.#頚0カ\'・$焉E舅
廩
>(d) Web サーバ側で受け取ったとき、それをデータ破損せずに受け取れているか?
ローカル、レンタルサーバーでも同じ動きをします。
「5C」が付加される理由がわかりません。
これさえなければデータは破損していないと思うのですが。
(c)で確認のために利用したソースです。
***********************************************************
VB6ソース
***********************************************************
Option Explicit
Private Const TargetURL As String = "http://127.0.0.1/test.php"
Private Sub Form_Load()
Dim xmlhttp As Object
Dim SendByte As Variant
Dim desByte() As Byte
Dim getByte() As Byte
Dim bSendByte() As Byte
Set xmlhttp = CreateObject("MSXML2.XMLHTTP")
With xmlhttp
SendByte = "": getByte = "": desByte = "": bSendByte = ""
Call .open("POST", TargetURL, False)
Call .setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
desByte = HexToByte("E91EBF24F61D481E82DDF83849846DA0F459BCB47A3744487A338E3C361D7AA604F102581C396989D888E3A14DACB33F2839959F4E2E23B7DB30B611278E1324A0884AE7CF0D9C48")
Call StringAppend(bSendByte, "test=")
Call ByteAppend(bSendByte, desByte)
SendByte = bSendByte
Call .send(SendByte)
getByte = .responseBody()
End With
Set xmlhttp = Nothing
End Sub
Private Sub StringAppend(ByRef addByte() As Byte, ByVal s As String)
Dim adoStream As Object
Dim NewByte() As Byte
Set adoStream = CreateObject("ADODB.Stream")
With adoStream
.Type = 2: .Charset = "SHIFT_JIS": Call .open: Call .Writetext(s): .position = 0
.Type = 1: NewByte = .Read(): Call .Close
End With
Set adoStream = Nothing
Call ByteAppend(addByte, NewByte)
End Sub
Private Sub ByteAppend(ByRef addByte() As Byte, ByRef data As Variant)
Dim i As Long
For i = 0 To UBound(data)
ReDim Preserve addByte(UBound(addByte) + 1): addByte(UBound(addByte)) = data(i)
Next
End Sub
Public Function HexToByte(ByVal s As String) As Byte() '16進数表記の文字列をバイト配列に
Dim NewByte() As Byte, i As Long
NewByte = ""
For i = 1 To Len(s) Step 2
ReDim Preserve NewByte(UBound(NewByte) + 1): NewByte(UBound(NewByte)) = CLng("&h" & Mid(s, i, 2))
Next
HexToByte = NewByte
End Function
***********************************************************
PHPソース
***********************************************************
<?php
$test = $_POST["test"];
echo "\n 16進数データ: ";
echo stringToHex( $test );
echo "\n受信データ:\n";
echo $test ;
function stringToHex ($s) {
$hexes = array ("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F");
for ($i=0; $i<strlen($s); $i++) { $r .= ($hexes [(ord($s{$i}) >> 4)] . $hexes [(ord($s{$i}) & 0xf)]); }
return $r;
}
?>
phpソースに下記のものを追加で解決できました。
PHP側のマジッククオートがONのためバイナリの意味のないデータでしたが
エスケープされてしまったようです。
VB6の送信データを下記のように変えても前に「5C」が付着します。
'desByte = HexToByte("27")
'desByte = HexToByte("5C")
-----phpソース---------
$test = stripslashes($_POST["test"]);
完全にこれは(d)の問題でした。
板違いですね。
またまたご迷惑をおかけしました。
魔界の仮面弁士さまADODB.Streamの利用方法
本当に勉強になりました。
ありがとうございます。
>> VB6側でMSXML2.XMLHTTPのsendで送る時のSendByteの内容をウォッチリストで確認しました。
> sendbyte(64)「17=&h11」
> sendbyte(65)「39=&h27」
> になっていて「92=&h5C」が入っていませんでした。
入っていないのが正しいのでしょうか?
それとも、入っているのが正しいのでしょうか?
入っているのが正しいなら、VB 側の事前処理上の問題でしょうね。
逆に入っていないのが正しいなら、何らかのモジュールの障害等により、
そのデータが、Send で送られる時に化けてしまっているか…、または
PHP 側で受信するときの処理方法に問題がある、ということでしょう。
> InetSpyの情報
> リクエスト情報
非可読文字列を掲示板に貼りつけないでくださいませ。
他のテキスト部に悪影響を与える可能性がありますので。
というか、送信データが非可読のバイナリになっている時点で、何かがおかしいです。
私は PHP の知識が無いので判断が付かないのですが、お使いの Web サーバは、
本当に application/x-www-form-urlencoded なデータを要求しているのでしょうか?
(なにか別の Content-Type を要求されていたりはしませんか?)
もし、本当に Content-Type: application/x-www-form-urlencoded が要求されているなら、
バイナリデータは流せないでしょう。「URL エンコードされた ASCII データ」が必要です。
> VB6ソース
あれ。前のコードでは、『文字コード変換(Shift_JISからUTF-8へ)』と
ありましたが……今回はそれに相当する処理が無くなっていますね。
とりあえず、URL エンコードが必要かどうかは別としても、その Web サーバ側では、
どの文字コードのデータが送信されてくることが期待されているのでしょうか?
それによって、文字コード変換処理の部分が大きく変わってくるかと思います。
> PHPソース
私は PHP の文法を全く知らないのですが、こちらはノーコメントで。
ただ、PHP 側にも手を加えられるなら、バイナリ値を送信する代わりに、
(たとえば 16 進数表現に変更するなどして)ASCII テキストとして送信し、
PHP 側で、それをバイナリに復元するような設計にするというのはどうでしょう?
逃げの手ではありますが、これなら 0x5C が入る余地は無さそうですし。
>非可読文字列を掲示板に貼りつけないでくださいませ。
>他のテキスト部に悪影響を与える可能性がありますので。
掲示板の管理者様、皆様、大変ご迷惑をおかけしました。
今後気をつけます。
>送信データが非可読のバイナリになっている時点で、何かがおかしいです。
下記事情により非可読バイナリにしています。
少し脱線しますが・・・・・
///////////////////////////////
1.友人が経営する店でネットで確認できる会員制ポイントシステムを導入したい。
2.趣味程度で触っていたPHPで管理画面を作成。
3.PHPで管理画面を作成するも制御面やデザイン時間がかかる。セッションの管理も面倒でした。
4.VBからデータベースにアクセスする方法に切り替える(MyODBC経由)。
5.ところがレンタルサーバーによってはMYSQLの標準ポート3306が閉じられている。
6.VBからPHPスクリプトにアクセスしそこからMySQLの情報を取り出しVB側に渡す。
PHPスクリプトがアダプターの役割をします。
7.問題点1:安いレンタルサーバーを利用しているのでSSLが使えない。
8.7の事情によりVBとPHPのやり取りを暗号化しようという考えになりました。
///////////////////////////////
6内にデータベース接続情報を持たせても良かったのですが外部アクセスでクエリーを
はじらせられたらまずいのでVB側からデータベース接続パラメーターを渡すようにしました。
VB側からはクエリーをMSXML2.xmlhttpでsendしresponseBodyで受け取ったデータを加工クラスに
渡すだけでフィールド名Key付きオブジェクトコレクションを生成できるようにしました。
ポイントデータやブログデータに関しては個人情報などの情報が付加されていないのですが顧客
情報に関しては個人情報満載です。
登録時やデータ検索時に平文でやり取りは盗聴の可能性があります。
そこで特定のクエリーや特定の結果だけ暗号化すれば盗聴の可能性がなくなると思いました。
(↑の心配していましたがInetSpy知りませんでした。)
登録時
クライアント(insert into userm values('0115','48aa','まさあき','061515','大阪')etc )
↓ ↑結果(Mysqlの情報)
WWWサーバー
データ取得時
クライアント(select * from userm where id='0115')
↓ ↑結果('0115','48aa','まさあき','061515','大阪')
WWWサーバー
POSTで送る内容
サンプル
host=localhost&port=3306&login=XXX<暗号化>XXX&etc=XXX<暗号化>XXX
上記の理由で非可読のメッセージを送りたかったのです。
3番以降は私の勝手な自己満足で製作に取り掛かっています。
私の気づいていない問題点などありましたらご指摘くださいませ。
>本当に application/x-www-form-urlencoded なデータを要求しているのでしょうか?
>(なにか別の Content-Type を要求されていたりはしませんか?)
>もし、本当に Content-Type: application/x-www-form-urlencoded が要求されているなら、
>バイナリデータは流せないでしょう。「URL エンコードされた ASCII データ」が必要です。
この辺勉強不足なので・・・
出直してきます。
ありゃ。入れ違いで解決してたんですね。
> 6.VBからPHPスクリプトにアクセスしそこからMySQLの情報を取り出しVB側に渡す。
> PHPスクリプトがアダプターの役割をします。
私も VB6 で同様の実装を行った事があります。サーバ側が IIS だったので、あまり参考には
ならないと思いますが、その時には ADODB.Recordset を直接交換していました。
受け取った側は Call rs.Open(stream) だけで開きなおせますし、更新の手間も楽だったので。
http://support.microsoft.com/kb/296772/ja
非IIS だと、SOAP でデータ交換する手法もありますが…VB6 の場合は手間がかかるんですよね。
http://www.microsoft.com/japan/msdn/vstudio/downloads/soaptoolkit/
> 7.問題点1:安いレンタルサーバーを利用しているのでSSLが使えない。
> 8.7の事情によりVBとPHPのやり取りを暗号化しようという考えになりました。
3DES で施錠しているようなので、データを解読される可能性は低いと思われますが、
そのキーが固定値になっていたりはしませんか?
たとえばログイン要求のように、同一リクエストを繰り返すページがあるとすれば、
そのリクエスト内容が毎回一緒であると、盗聴者による「なりすまし」を防げません。
同じデータを送信すればログインできる仕様になっているなら、ログイン情報が
平文であっても暗号化データであっても、攻撃者にとっては同じことですから。
# 私の場合は実装が面倒だったので、結局、SSL を導入しました。(^_^;)
>> もし、本当に Content-Type: application/x-www-form-urlencoded が要求されているなら、
>> バイナリデータは流せないでしょう。「URL エンコードされた ASCII データ」が必要です。
> この辺勉強不足なので・・・
クライアント側は(汎用のブラウザではなく)自作の VB6 製ツール、サーバも固定的となれば、
その間で交換されるデータ形式は、独自のフォーマットでも構わない、という見方もありますね。
ただ本来であれば、Content-Type: application/x-www-form-urlencoded にて POST されるデータは、
通常は「name1=value1&name2=value2」のような US-ASCII 形式のデータとなるはずです。
この場合、名前や値に「=」や「&」あるいはバイナリを含める事ができないため、そのような
データが含まれる場合には、URL エンコードが施されて送信されます。
これにより、「-」「_」「.」および英数字はそのまま送信されますが、空白文字は「+」となり、
その他のバイナリは「%00」〜「%FF」形式のテキストに変換されて送られる事になります。
たとえば、アンパサンド(&)記号は「%29」となり、チルダ(~)記号は「%7E」となります。
なお、URL エンコードされたバイナリを送る以上、文字列を送る事も可能ですが、
文字の符号化に関する規定は特に定義されておらず、どの文字コードが使われるかは、
処理系依存となっています。たとえば、"弁士"という漢字 2文字を name という名前で送る場合、
EUC-JP なら「name=%CA%DB%BB%CE」、UTF-8 なら「name=%E5%BC%81%E5%A3%AB」となります。
魔界の仮面弁士さま
本当にわかりやすい説明ありがとうございます。
いろいろな知識を吸収できました。
>非IIS だと、SOAP でデータ交換する手法もありますが…VB6 の場合は手間がかかるんですよね。
>http://www.microsoft.com/japan/msdn/vstudio/downloads/soaptoolkit/
SOAPの名前は聞いたことがあったのですが難しそうなのでPASSしていました。
今回のプログラムが完成したらチャレンジしてみます?!
余力があればAESも作成してみたいです。
http://www.ipa.go.jp/security/enc/CRYPTREC/fy15/cryptrec20030425_spec01.html
>たとえばログイン要求のように、同一リクエストを繰り返すページがあるとすれば、
>そのリクエスト内容が毎回一緒であると、盗聴者による「なりすまし」を防げません。
>同じデータを送信すればログインできる仕様になっているなら、ログイン情報が
>平文であっても暗号化データであっても、攻撃者にとっては同じことですから。
現在固定24byteキーにしています。
考えられるアイデアとしてはPOSTでデータを送る際ランダムにキーを生成することぐらいしか
思い浮かびません。
クライアント
(固定20Byte(秘密鍵)+ランダム4Byte)
↓
サーバー
(固定20Byte(秘密鍵)+POSTで受け取った4Byte)で復号化
↓
サーバー
結果データを送るときは(固定20Byte(秘密鍵)+POSTで受け取った4Byte)で暗号化
↓
クライアント
メモリーに残っている4Byteキーを固定20Byteとあわせて復号化
>ただ本来であれば、Content-Type: application/x-www-form-urlencoded にて POST されるデータは、
>通常は「name1=value1&name2=value2」のような US-ASCII 形式のデータとなるはずです。
>この場合、名前や値に「=」や「&」あるいはバイナリを含める事ができないため、そのような
>データが含まれる場合には、URL エンコードが施されて送信されます。
解決してからいろいろなクエリーを送っていたのですが問題発生しました。
途中でクエリー切れていたのです。
送信POSTを確認したところ「&」(&h26=38)でカットされていました。
復号化も途中で失敗。
対策として前回の暗号化の部分を下記のように変更しました。
sqlByte = cDes.Triple_Des_Encrypt(DesKey, sql)
sqlByte = Byte_Replace(sqlByte, Chr(38), "00000000") '&
sqlByte = Byte_Replace(sqlByte, Chr(61), "11111111") '=
暗号化しているデータなので画像データのように連続して8Byte同じデータが続かない、
また8Byte単位で暗号化しているので連続した8バイトデータはないという考えで安易に対応しました。
盲点があるかもしれません。
PHP側もこの対応に伴って修正しました。
>たとえば、アンパサンド(&)記号は「%29」となり、チルダ(~)記号は「%7E」となります。
今回の場合下記の認識でよろしいでしょうか。
クライアント:「name1=value1&name2=valu&e2」
↓
サーバー:「name1=%76%61%6C%75%65%31%29name2=%76%61%64%75%29%65%32」
name1は「%76%61%6C%75%65%31」 = value1
name2は「=%76%61%64%75」= valu
private Function Byte_Replace(ByRef expression() As Byte, _
ByRef find As String, _
ByRef replacewith As String) As Byte()
Dim i As Long
Dim j As Long
Dim findByte() As Byte
Dim replacewithByte() As Byte
Dim newByte() As Byte
findByte = find
replacewithByte = replacewith
findByte = CodeChgFromTo(findByte, "unicode", "SHIFT_JIS")
replacewithByte = CodeChgFromTo(replacewithByte, "unicode", "SHIFT_JIS")
newByte = ""
For i = 0 To UBound(expression)
For j = 0 To UBound(findByte)
If expression(i + j) <> findByte(j) Then
Exit For
End If
Next
If j = UBound(findByte) + 1 Then
For j = 0 To UBound(replacewithByte)
ReDim Preserve newByte(UBound(newByte) + 1)
newByte(UBound(newByte)) = replacewithByte(j)
Next
i = i + UBound(findByte)
Else
ReDim Preserve newByte(UBound(newByte) + 1)
newByte(UBound(newByte)) = expression(i)
End If
Next
Byte_Replace = newByte
End Function
> 現在固定24byteキーにしています。
VB の話から離れつつあるので、続けるべきかどうか悩みますが、深く考えるのであれば、
どのレベルのセキュリティレベルを求める必要があるか、線引きしておく必要があります。
今回の場合、どこまでの対策を必要とする情報を扱っているのでしょうか?
暗号化を施せば、送信時および受信時の「盗聴」に対する、情報漏洩対策にはなるでしょうが、
それだけでは十分とは言えないでしょう。
通信途中でデータが横取りされ、内容が書きかえれているかも知れませんから。
たとえば暗号化を行うだけで、復元したあとのデータ検証チェックが行われていなければ、
それも脆弱性となりえます。検証機構が無いと、ゴミデータをサーバに投げられてしまい、
生の SQL エラーが表示され、そのメッセージからデータ構造が漏洩……なんて可能性もあるわけで。
> (固定20Byte(秘密鍵)+POSTで受け取った4Byte)で復号化
秘密鍵が固定的とのことで、ネットワーク上には送信しないつもりかと思いますが、
残る 4 バイトについては、ランダムであろうとなかろうと、鍵自体を無保護で
送信している以上、そこがセキュリティホールとなりえる可能性があります。
(そのランダムキーが、こっそり別のキーに改竄されて送信されていたらどうなりますか?)
で……そもそもこれって、共通鍵暗号化方式ですよね。
共通鍵暗号化方式の場合、盗聴者が秘密鍵を拾えばデータを開けてしまいますので、
より安全に通信を行うために、公開鍵暗号化を使った方が良いのではないでしょうか。
# 共通鍵との併用という手もアリですが。
なお実装には、CryptoAPI を使用できます。(PHP 側の実装手法は知りませんが…)
さらに、電子署名として、「元データのハッシュ値を自身の秘密鍵で暗号化したもの」も、
データ本体と一緒に送信しておくと、データが改竄されていない事の確認もできます。
> 今回の場合下記の認識でよろしいでしょうか。
> クライアント:「name1=value1&name2=valu&e2」
えぇと、どこまで[キー]で、どこからが[値]なのでしょうか?
それとも、すべて一つの値としたいのでしょうか?
もし、
キー名 "name1" に対して "value1" という値
キー名 "name2" に対して "value2" という値
を渡したいなら、送信データは「name1=value1&name2=value2」ですし、
キー名 "name1" に対して "value1" という値
キー名 "name2" に対して "valu&e2" という値
を渡したいなら、送信データは「name1=value1&name2=valu%26e2」となり、
キー名 "name" に対して "name1=value1&name2=valu&e2" という値
を渡したいなら、「name=name1%3Dvalue1%26name2%3Dvalu%26e2」となります。
> ReDim Preserve newByte(UBound(newByte) + 1)
バイト配列で管理するよりも、Stream オブジェクトのまま管理した方が楽ですよ。
Stream であれば、「x バイト目から y バイト取得する」といった作業や、
末尾へのデータ追加や切捨てなども、ループ無しで容易に行えますので。
魔界の仮面弁士さま
プログラム完成いたしました。
いろいろ勉強になりました。
ありがとうございます。
ツイート | ![]() |