サーバー上の PhantomJS で実行されるスクリプトを持っています。スクリプトへのコマンド ライン引数としてパスワードを渡す必要があります。PhantomJS に慣れていない方のために説明すると、PhantomJS は、クライアントからの操作なしでサーバー側で実行されるヘッドレス Webkit ブラウザーです。
パスワードを PhantomJS の仮想 Web ページ オブジェクトのコンテキストに読み込むには、特定の Web ページ オブジェクトに含まれる JavaScript ファイルにパスワードを保存する必要があります。パスワード ファイルは、ログインに必要な期間のみ保持され、削除されます。スクリプトがファイルを必要としなくなった後にファイルを削除するフェイルセーフメカニズムがあります。このパスワードを平文で保存したくないので、AES 暗号化を使用します。
パスワードは、AES 暗号化を使用してデータベースに保存されます。この方法でパスワードを保存するのが最も安全な方法ではないことはわかっていますが、スクリプトはパスワードを知る必要があるため、ハッシュはオプションではありません。
ASP.NET MVC3 Web アプリケーションで C# からこの PhantomJS スクリプトを呼び出し、AesManaged または RijndaelManaged を使用して C# から暗号化されたパスワードを渡したいと考えています。私は暗号化の基本を理解しており、C# と JavaScript でコードを動作させることができました。ただし、C# からテキストを暗号化すると、javascript で復号化できません。例として、私の C# コードの一部を次に示します。
class Encrypter
{
public RijndaelManaged rijndael { get; set; }
public byte[] bytesToDecrypt { get; set; }
public byte[] bytesToEncrypt { get; set; }
public Encrypter(string base64key, string base64IV)
{
// CBC/128/PKCS7
rijndael = new RijndaelManaged();
rijndael.BlockSize = 128;
rijndael.KeySize = 192;
rijndael.IV = Convert.FromBase64String(base64IV);
rijndael.Padding = PaddingMode.PKCS7;
rijndael.Mode = CipherMode.CBC;
rijndael.Key = Convert.FromBase64String(base64key);
}
public string Encrypt(string strInptData)
{
bytesToEncrypt = UTF8Encoding.UTF8.GetBytes(strInptData);
ICryptoTransform encryptor = rijndael.CreateEncryptor(rijndael.Key, rijndael.IV);
bytesToDecrypt = encryptor.TransformFinalBlock(bytesToEncrypt, 0, bytesToEncrypt.Length);
return Convert.ToBase64String(bytesToDecrypt);
}
public string Decrypt()
{
ICryptoTransform decryptor = rijndael.CreateDecryptor(rijndael.Key, rijndael.IV);
byte[] decryptBytes = decryptor.TransformFinalBlock(bytesToDecrypt, 0, bytesToDecrypt.Length);
// return original string
return UTF8Encoding.UTF8.GetString(decryptBytes);
}
public string ByteArrayToString(byte[] array)
{
StringBuilder sb = new StringBuilder();
sb.Append('[');
foreach (byte b in array)
{
sb.Append(b);
sb.Append(", ");
}
sb.Append("] length : " + array.Length);
return sb.ToString();
}
}
JavaScript コードは、slowAES 実装を使用します。
$('#encrypt').click(function () {
var plainText = $('#plaintext').val();
var $encrypted = $('#encryptedtext');
var bytesToEncrypt = cryptoHelpers.convertStringToByteArray(plainText);
var key = cryptoHelpers.base64.decode("bALREf3IwJhzO8JdUwZ55coMydj2YD8R");
var iv = cryptoHelpers.base64.decode("v/VCTAlV5+kexBFN16WY5A==");
var result = slowAES.encrypt(bytesToEncrypt,
slowAES.modeOfOperation.CBC,
key,
slowAES.aes.keySize.SIZE_192,
iv);
var base64Result = cryptoHelpers.base64.encode(result);
var hexKey = cryptoHelpers.toHex(key);
$encrypted.val(base64Result);
$('div#results').append('<p>bytes to enrypt: ' + bytesToEncrypt + ' length ' + bytesToEncrypt.length + '</p>');
$('div#results').append('<p>Key: ' + key + '</p>');
$('div#results').append('<p>IV: ' + iv + '</p>');
$('div#results').append('<p>Result: ' + result['cipher'] + '</p>');
$('div#results').append('<p>Hex Key: ' + hexKey + '</p>');
});
$('#decrypt').click(function () {
var $plain = $('#plaintext');
var encrypted = $('#encryptedtext').val();
var bytesToDecrypt = cryptoHelpers.base64.decode(encrypted);
var key = cryptoHelpers.base64.decode("bALREf3IwJhzO8JdUwZ55coMydj2YD8R");
var iv = cryptoHelpers.base64.decode("v/VCTAlV5+kexBFN16WY5A==");
var result = slowAES.decrypt(bytesToDecrypt,
slowAES.modeOfOperation.CBC,
key,
slowAES.aes.keySize.SIZE_192,
iv);
var plainresult = cryptoHelpers.convertByteArrayToString(result);
$plain.val(plainresult);
});
JavaScript のこのコードは、暗号化と復号化の簡単なテストを実行できるようにセットアップしただけです。C# と JavaScript の間で暗号化と復号化が機能するようになったら、PhantomJS からのコマンド ライン引数としてパスワードを処理します。
キーと IV は次のとおりです。
string base64key = "bALREf3IwJhzO8JdUwZ55coMydj2YD8R";
string base64iv = "v/VCTAlV5+kexBFN16WY5A==";
テキスト 'test' の暗号化を実行した後の C# コードの出力は次のとおりです。
BytesToEncrypt: [116, 101, 115, 116, ] length : 4
Base64 Encrypted String: RxNZztdUgbx3KPdvVvMmBg==
Key: [108, 2, 209, 17, 253, 200, 192, 152, 115, 59, 194, 93, 83, 6, 121, 229, 202, 12, 201, 216, 246, 96, 63, 17 ] length : 24
IV: [191, 245, 66, 76, 9, 85, 231, 233, 30, 196, 17, 77, 215, 165, 152, 228 ] length : 16
Result: [71, 19, 89, 206, 215, 84, 129, 188, 119, 40, 247, 111, 86, 243, 38, 6 ] length : 16
Decrypted: test
JavaScript からの出力は次のとおりです。
Bytes to Encrypt: 116,101,115,116,12,12,12,12,12,12,12,12,12,12,12,12 length 16
Base64 Encrypted String: VRPeZsEJpP7OURwg3FdI8g==
Key: 108,2,209,17,253,200,192,152,115,59,194,93,83,6,121,229,202,12,201,216,246,96,63,17 length 24
IV: 191,245,66,76,9,85,231,233,30,196,17,77,215,165,152,228 length 16
Result: 85,19,222,102,193,9,164,254,206,81,28,32,220,87,72,242 length 16
slowAES は PKCS7 パディングを使用するため、C# コードに PKCS7 パディングを適用しました。PKCS7 パディングの独自の実装を使用してみましたが、同じ結果のバイト配列は得られませんでした。何か不足している場合はお知らせください。どうもありがとう。