3

私はRijndaelを使用して暗号化されたmp4を持っており、次の方法でC#で復号化しています。

System.Security.Cryptography.Rijndael crypt = System.Security.Cryptography.Rijndael.Create();

crypt.Key = convertedSecureString;

byte[] initializationVectorLength = new byte[sizeof(int)];
CryptoStream cryptostream = new CryptoStream(inputStream, crypt.CreateDecryptor(), CryptoStreamMode.Read);
byte[] buffer = new byte[1024];
int len;
while ((len = cryptostream.Read(buffer, 0, buffer.Length)) > 0)
{
    outputStream.Write(buffer, 0, len);
    buffer = new byte[1024];
}

outputStream.Flush();
cryptostream.Close();
inputStream.Close();

次に、このコードをJava/Androidに相当するものに変換する必要があります。率直に言ってどこから始めればいいのかわからない。私は非常に多くのオプションに混乱しています-BouncyCastleを使用すると言う人もいれば、Apache Commonsと言う人もいれば、ネイティブJavalibを言う人もいます。これを行うにはどうすればよいですか。そして、CryptoStreamなどについてどうすればよいですか?

アップデート

キーを割り当てるためにC#で次のコードを使用しています

byte[] convertedSecureString = new byte[this.key.Length];
IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(this.key);

for (int i = 0, j = 0; i < this.key.Length * UnicodeByteLength; i = i + UnicodeByteLength, j++)
{
    convertedSecureString[j] = System.Runtime.InteropServices.Marshal.ReadByte(ptr, i);
}

try
{
    crypt.Key = convertedSecureString;
}

キーが安全な場所。私はJavaで同等の安全でないキーを持っています。このコードをJavaに変換するにはどうすればよいですか

アップデート

  Rfc2898DeriveBytes newKey = new Rfc2898DeriveBytes(crypt.Key.ToString(), crypt.IV);
                Array.Copy(newKey.GetBytes((int)crypt.KeySize / 8), crypt.Key, (int)crypt.KeySize / 8);
                Array.Copy(newKey.GetBytes((int)crypt.BlockSize / 8), crypt.IV, (int)crypt.BlockSize / 8);

私はこれをC#で使用して、Rfc 2898を使用してキーを変更し、バイトを派生させています-Javaで同等のものを見つけることができません-2番目のコメントでC#のRfc2898DerivedBytesに相当するJavaを見つけました-しかし、イテレーターとdklenにどのような値を与えますか?

4

2 に答える 2

6

Cipherオブジェクトを取得する必要があります。byte[] aesKey、およびbyte[] iv(初期化ベクトル、AES では常に 16 バイトである必要があります)を使用して取得する方法の 1 つを次に示します。

// aesKey is 128, 196 or 256-bit key (8, 12 or 16 byte array)
SecretKeySpec key = new SecretKeySpec(aesKey, "AES");

// initialization vector
IvParameterSpec ivSpec = new IvParameterSpec(iv);

// create and initialize cipher object
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);

オブジェクトをCipher復号化モードにすると、updateメソッドを使用して暗号化されたデータを渡すことができ、プレーンテキスト データが返されます。完了したら、いずれかのdoFinalメソッドを呼び出して最終ブロックを取得する必要があります。

CipherInputStream または、 Cipher オブジェクトと、暗号化されたデータを提供する元の入力ストリームを使用して作成できます。からデータをCipherInputStream読み取ると、元の入力ストリームからデータが読み取られ、復号化され、プレーンテキスト データが返されます。

Cipher.ENCRYPT_MODE暗号化するには、メソッドに渡し、代わりにCipher.init使用する必要があります。CipherOutputStream

更新: 完全な例、元の C# コードと多かれ少なかれ同等:

// Algorithm, mode and padding must match encryption.
// Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");

// If you have Bouncycastle library installed, you can use
// Rijndael/CBC/PKCS7PADDING directly.
Cipher cipher = Cipher.getInstance("Rijndael/CBC/PKCS7PADDING");

// convertedSecureString and initVector must be byte[] with correct length
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(convertedSecureString, "AES"),
    new IvParameterSpec(initVector));

CipherInputStream cryptoStream = new CipherInputStream(inputStream, cipher);
byte[] buffer = new byte[1024];
int len = cryptoStream.read(buffer, 0, buffer.length);
while (len > 0) {
    outputStream.write(buffer, 0, len);
    len = cryptoStream.read(buffer, 0, buffer.length);
}

outputStream.flush();
cryptoStream.close();
// no need to close inputStream here, as cryptoStream will close it

デフォルトでは、Java は Rijndael アルゴリズム (AES が機能する場合と機能しない場合があります。他の回答を参照) と PKCS7 パディングをサポートしていません。そのためには Bouncycastle 拡張機能をインストールしてから、 を使用する必要がありますCipher.getInstance("Rijndael/CBC/PKCS7PADDING");。CBC と PKCS7 パディングを使用する理由 これらはSystem.Security.Cryptography.Rijndaelクラスのデフォルトのようです。間違っている場合は、状況に応じて正しいモードとパディングを使用してください。

于 2012-04-10T11:35:36.997 に答える
1

C# での実装について心配する必要はありません。Java 言語の暗号化/復号化については、以下のリンクを参照してください。Java での RjIndeal の実装

于 2012-04-10T11:32:25.573 に答える