14

javascript ライブラリSlowAESと .NET のRijndaelManagedクラスを使用して、AES 暗号化/復号化をセットアップしようとしています。

この投稿を読んだ後、私はこの方法を選択しました。 Cheeso は、これら 2 つの暗号化方法を一緒にプレイすることができました。

「COM-wrapped-SlowAE のテストでは、CBC モードを使用しました。暗号化は .NET の RijndaelManaged クラスと完全に互換性がありました」 - Cheeso

Cheeso の Windows Scripting Component から JavaScript コード、最新の Slowaes ライブラリを取得し、次の JavaScript スクリプトを使用してテストしました。

var key = "12345678901234567890123456789012";
var message = "watson?";
var decrypted;

slowAES.aes.keySize.SIZE_256;
slowAES.modeOfOperation.CBC;
put_PassPhrase(key);
var result = EncryptString(message);
decrypted = DecryptCommaDelimitedStringToString(result)
document.write("Key:" + key + "<br />original:" + message + "<br />Cypher:" + result + "<br />Decrypted:" + decrypted + "<br />IV(): " + get_IV());

次の出力が得られます。

Key:12345678901234567890123456789012
original:watson?
Cypher:245,159,1,1,168,1,1,143,1,1,146,1,1,239,117,1
Decrypted:watson? 
IV(): 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

MSDNにある次の例を変更して、C# の暗号化と一致するようにしました。

public static void Main()
        {
            try
            {
                string original = "watson?";
                byte[] IV = new byte[16];   // match slowaes IV
                byte[] key = new System.Text.ASCIIEncoding().GetBytes("12345678901234567890123456789012");// match slowaes KEY

                RijndaelManaged myRijndael = new RijndaelManaged();
                myRijndael.BlockSize = 128;
                myRijndael.KeySize = 256;
                myRijndael.Mode = CipherMode.CBC;

                // Encrypt the string to an array of bytes.
                byte[] encrypted = encryptStringToBytes_AES(original, key, IV);

                // Decrypt the bytes to a string.
                string roundtrip = decryptStringFromBytes_AES(encrypted, key, IV);

                //Display the original data and the decrypted data.
                Console.WriteLine("Original:   {0}", original);
                Console.WriteLine("Round Trip: {0}", roundtrip);

            }
            catch (Exception e)
            {
                Console.WriteLine("Error: {0}", e.Message);
            }
        }

バイト配列のウォッチ:

-  encrypted {byte[16]} byte[]
  [0] 139 byte
  [1] 104 byte
  [2] 166 byte
  [3] 35 byte
  [4] 8 byte
  [5] 42 byte
  [6] 216 byte
  [7] 160 byte
  [8] 235 byte
  [9] 153 byte
  [10] 23 byte
  [11] 143 byte
  [12] 105 byte
  [13] 3 byte
  [14] 24 byte
  [15] 255 byte

マネージド .NET クラスですべてのパディング オプションを試しましたが、暗号化された出力を一致させることができません。誰でも私を助けることができますか?

ありがとう、

ボブ

4

1 に答える 1

37

多分私は助けることができます。

あなたの C# コードを少し修正しました。私が使用する C# コード全体は次のとおりです。

using System;
using System.Security.Cryptography;

public class Bob
{
    internal static string FormatByteArray(byte[] b)
    {
        System.Text.StringBuilder sb1 = new System.Text.StringBuilder();
        int i = 0;
        for (i = 0; i < b.Length; i++)
        {
            if (i != 0 && i % 16 == 0)
                sb1.Append("\n");
            sb1.Append(System.String.Format("{0:X2} ", b[i]));
        }
        return sb1.ToString();
    }

    public static void Main()
    {
        try
        {
            string original = "watson?";

            Console.WriteLine("Original:   {0}", original);

            byte[] IV = new byte[16];   // match slowaes IV
            var ascii = new System.Text.ASCIIEncoding();

            // match slowaes KEY
            string passPhrase = "12345678901234567890123456789012";
            byte[] key = ascii.GetBytes(passPhrase);

            RijndaelManaged myRijndael = new RijndaelManaged();
            myRijndael.BlockSize = 128;
            myRijndael.KeySize = 256;
            myRijndael.IV = IV;
            myRijndael.Padding   = PaddingMode.PKCS7;
            myRijndael.Mode = CipherMode.CBC;
            myRijndael.Key = key;

            // Encrypt the string to an array of bytes.
            byte[] plainText = new System.Text.ASCIIEncoding().GetBytes(original);
            ICryptoTransform transform = myRijndael.CreateEncryptor();
            byte[] cipherText = transform.TransformFinalBlock(plainText, 0, plainText.Length);

            Console.WriteLine("cipherText: {0}", FormatByteArray(cipherText));

            // Decrypt the bytes to a string.
            transform = myRijndael.CreateDecryptor();
            plainText = transform.TransformFinalBlock(cipherText, 0, cipherText.Length);


            string roundtrip = ascii.GetString(plainText);

            Console.WriteLine("Round Trip: {0}", roundtrip);

        }
        catch (Exception e)
        {
            Console.WriteLine("Error: {0}", e.Message);
        }
    }

}

上記をコンパイルします

csc.exe /target:exe /out:Bob.exe Bob.cs

あなたが参照した他の投稿の slowAES.wsc を使用しますが、2 つの変更があります。これには本当に PBKDF が必要ですが、今は気にする必要はありません。変更された EncryptString は次のようになります。

function EncryptString(plainText)
{
  // this is really wrong - need a PBBKDF to get the key, instead
  // of just using the passphrase
  var key = cryptoHelpers.convertStringToByteArray(_passphrase);
  // var nkey = slowAES.getPaddedBlock(key, 0, _keysize, _mode);
  var bytesToEncrypt = cryptoHelpers.convertStringToByteArray(plainText);

  var result = slowAES.encrypt(bytesToEncrypt, 
      _mode,
      key,
      _keysize,
      _iv);
  return result['cipher'];
}

つまり、キーサイズに必要な長さと正確に一致する passPhrase を使用する必要があります。AES256 を使用する場合は、32 文字の文字列 (32 * 8 = 256 ビット) を渡します。あなたはすでにこれを理解していたようです。

WSC コンポーネントのクライアントも Javascript です (ただし、任意の COM 言語を使用できます)。これが私が使ったものです。

function toHexString(a)
{
    var ret = '';
    for(var i = 0;i < a.length;i++)
        ret += (a[i] < 16 ? '0' : '') + a[i].toString(16) + ' ';
    return ret.toLowerCase();
}


//var plaintext = "Hello. This is a test. of the emergency broadcasting system.";
var plaintext = "watson?";

try
{
    WScript.echo( "plaintext: " + plaintext);
    WScript.echo( "plaintext.length: " + plaintext.length);

    WScript.echo( "instantiate ");
    var aes = new ActiveXObject("Ionic.Com.SlowAES");

    WScript.echo( "keysize ");
    aes.KeySize = 256;

    WScript.echo( "passphrase ");
    aes.PassPhrase= "12345678901234567890123456789012";  // 32 chars long

    WScript.echo( "mode ");
    aes.Mode = "CBC";

    WScript.echo( "encrypting... ");
    var result = aes.EncryptString(plaintext);

    WScript.echo( "Cryptotext: " + toHexString(result));

    WScript.echo( "decrypting... ");
    var decrypted = aes.DecryptBytesToString(result);

    WScript.echo( "decrypted: " + decrypted);
}
catch(e)
{
    WScript.echo("Exception: " + e); 
    //     WScript.echo(e.Number + ": " + e.Name);
    WScript.echo(e.Message);
}

次にこのコードを実行すると、Javascript と C# は、AES256、12345678901234567890123456789012 のパスフレーズ、およびゼロの 16 バイトの IV を使用して、「watson?」の平文に対して同じ暗号文を生成します。生成される暗号文は次のとおりです。

8B 68 A6 23 08 2A D8 A0 EB 99 17 8F 69 03 18 FF

どちらの場合も正常に復号化されます。

EDIT : 私は WSC に slowAES 暗号化をパッケージ化しましたが、COM 環境外でも相互運用可能です。WSC の部分はこの質問には不要ですが、「VBScript と .NET AES を相互運用するにはどうすればよいですか?」という以前の質問に対する回答を示すために必要でした。

EDIT2 : Javascript または VBScript と .NET の間の AES 相互運用性を示すソース コードが利用可能です。ここで示した基本的な例を拡張して、C#、Javascript、VBScript の 3 つの言語でテスト アプリを作成しました。それらはすべて同じ引数のセットを取ります。これらはそれぞれ、RFC2898 準拠の鍵派生関数を使用します。PBKDF2 で使用するパスワード、ソルト、IV、プレーンテキスト、および RFC2898 の反復回数を指定できます。これらの各テスト プログラムの暗号文が同じであることは簡単に確認できます。たぶん、この例は誰かにとって役立つでしょう。

EDIT3
よく読んでください: Javascript 暗号化は有害と見なされます。

于 2009-07-30T04:20:12.427 に答える