私は、C# で Rijndael を使用して文字列 (json) を暗号化しようとし、PHP Web サービスに提供できる文字列を考え出しました。この Web サービスは、IV とマスターキー (それらが認識している) を使用して文字列をデコードします。PHP サービスと対話できる C# コードを作成する必要があります。PHP サービスを制御または所有していません。
暗号化のための PHP コードは次のとおりです。
function encrypt($plaintext) {
$masterkey = 'masterKeyOfLength29Characters';
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_CBC, '');
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $masterkey, $iv);
$crypttext = mcrypt_generic($td, $plaintext);
mcrypt_generic_deinit($td);
return base64_encode($iv.$crypttext);
}
$param = array("key" => "value");
$encryptedString = rawurlencode(encrypt(json_encode($param)))
上記のコードは C# に変換する必要があるため、JSON を暗号化して PHP Web サービスに提供できます。
2 つの問題があります。1 つ目はマスターキーの長さ、2 つ目 (関連している可能性があります) は暗号化されたデータの rawurlencode です (この時点でテストするのは難しいです)。
var masterkey = "masterKeyOfLength29Characters";
var data = EncryptData(json, masterkey);
// Some code to URL Encode the data, I haven't gotten as far to test this
// since I can't encrypt with the key used in PHP, so I can't call the service
// to test the encoded string from my C# code.
data = HttpUtility.UrlEncode(data);
data = data.Replace("+", "%20");
public static string EncryptData(string json, string encryptionKey) {
Rijndael rj = Rijndael.Create();
rj.Mode = CipherMode.CBC;
rj.Padding = PaddingMode.PKCS7;
rj.BlockSize = 256;
rj.KeySize = 256;
rj.Key = Encoding.UTF8.GetBytes(encryptionKey); // ERROR here
rj.GenerateIV();
var encryptedJSON = EncryptStringToBytes(json, rj.Key, rj.IV);
var r1 = Convert.ToBase64String(rj.IV);
var r2 = Convert.ToBase64String(encryptedJSON);
return r1 + r2;
}
EncryptStringToBytes はいくつかのチェックを行い、次のコードを使用します (インターネット上の多くの例から抜粋)。
using (Rijndael rijAlg = Rijndael.Create()) {
// Basically I do the same here as above, and I could also generate
// the IV here, but then I'd had to return it too. I know I can clean this
// code up quite a bit, but I'd rather focus on getting it to work first ;)
rijAlg.Mode = CipherMode.CBC;
rijAlg.Padding = PaddingMode.PKCS7;
rijAlg.BlockSize = 256;
rijAlg.KeySize = 256;
rijAlg.Key = Key;
rijAlg.IV = IV;
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
using (MemoryStream msEncrypt = new MemoryStream()) {
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) {
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) {
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
私が得るエラー:
Specified key is not a valid size for this algorithm.
したがって、要するに問題は次のとおりです。
1) なぜ PHP コードは Rijndael 256 (CBC モード) で長さ 29 のキーを受け入れ、私の C# は受け入れないのですか? 私はモードで遊んで、後でパディングを追加し、KeySize を設定しました (既に 256 のデフォルトでした)。ここで何が間違っているのかわかりません。
2) 長さ 32 のキーを使用すると、このキーが受け入れられ、コードが機能します。C# で復号化することもできます (ただし、PHP でこれをテストすることはできません)。問題 1 を解決してから、問題 2 に進みたいと思いますが、誰かがここで理解を深めてくれるかもしれません。暗号化された文字列には、IV に 1 つの '=' が含まれ、暗号化された json に 2x '==' (末尾) が含まれます。パディングなどについて読んだことがありますが、受け取ったPHPの例に「=」記号が表示されないのはなぜだろうと思っていました。繰り返しますが、おそらく問題 1 を修正した後は、これは問題にならないでしょう。
読んでくれてどうもありがとう。昨日試した一日の後、私は多くの異なるアプローチを試してみましたが、うまくいかないようです。