4

理由を聞かないでください。データの文字列を暗号化/復号化するこのコードが.NETにあります。ここで、Javaで「正確に」同じ機能を作成する必要があります。DESede cryptのいくつかの例を試しましたが、.netのこのクラスと同じ結果が得られるものはありません。

sslの背後に.netwebserbviceを作成して、.netで記述されたこの2つのメソッドを提供しているにもかかわらず、すべての可能性を使い果たすことなく実行するには愚かすぎます。

たぶん、その地域でより関係のあるジャワの人々の何人かは、あなたの頭の上にそれを作る方法を持っているでしょう。

ありがとう !!!

public class Encryption
{
  private static byte[] sharedkey = {...};
  private static byte[] sharedvector = {...};

  public static String Decrypt(String val)
  {
    TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
    byte[] toDecrypt = Convert.FromBase64String(val);
    MemoryStream ms = new MemoryStream();
    CryptoStream cs = new CryptoStream(ms, tdes.CreateDecryptor( sharedkey, sharedvector ), CryptoStreamMode.Write);

    cs.Write(toDecrypt, 0, toDecrypt.Length);
    cs.FlushFinalBlock();
    return Encoding.UTF8.GetString(ms.ToArray());
  }

  public static String Encrypt(String val)
  {
    TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
    byte[] toEncrypt = Encoding.UTF8.GetBytes(val);
    MemoryStream ms = new MemoryStream();
    CryptoStream cs = new CryptoStream(ms, tdes.CreateEncryptor( sharedkey, sharedvector ), CryptoStreamMode.Write);
    cs.Write(toEncrypt, 0, toEncrypt.Length);
    cs.FlushFinalBlock();
    return Convert.ToBase64String(ms.ToArray());
  }
}

Samle入力/出力

String plain = "userNameHere:passwordHere";
Console.WriteLine("plain: " + plain);


String encrypted = Encrypt(plain);
Console.WriteLine("encrypted: " + encrypted);
// "zQPZgQHpjxR+41Bc6+2Bvqo7+pQAxBBVN+0V1tRXcOc="

String decripted = Decrypt(encrypted);
Console.WriteLine("decripted: " + decripted); 
// "userNameHere:passwordHere"
4

4 に答える 4

8

コードは続きますが、最初にいくつかの注意事項があります。

  1. メッセージごとに異なる初期化ベクトルを選択する必要があります。初期化ベクトルをハードコーディングしても意味がありません。IVは、暗号文とともにメッセージ受信者に送信する必要があります(秘密ではありません)。
  2. base-64エンコーディングには独自のユーティリティクラスを使用しました。代わりに、BouncyCastleなどのサードパーティライブラリを使用するか、独自のライブラリを作成するsun.misc.BASE64Encoderことができます。sun.misc.BASE64Decoder
  3. 最初のキーと3番目のキーが同じである2キートリプルDESを使用しています。sharedkeyJava DESede暗号は常に192ビットの鍵を必要とするため、これを反映するように変更しました。キーイングオプションを処理するのはキージェネレーター次第です。
  4. CBCIVはわずか64ビットです。の最初の64ビットのみを使用しましたsharedvector

このクラスは、C#バージョンと相互運用する必要があります。

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class Encryption
{

  private static byte[] sharedkey = {
    0x01, 0x02, 0x03, 0x05, 0x07, 0x0B, 0x0D, 0x11, 
    0x12, 0x11, 0x0D, 0x0B, 0x07, 0x02, 0x04, 0x08, 
    0x01, 0x02, 0x03, 0x05, 0x07, 0x0B, 0x0D, 0x11
  };

  private static byte[] sharedvector = {
    0x01, 0x02, 0x03, 0x05, 0x07, 0x0B, 0x0D, 0x11
  };

  public static void main(String... argv)
    throws Exception
  {
    String plaintext = "userNameHere:passwordHere";
    String ciphertext = encrypt(plaintext);
    System.out.println(ciphertext);
    System.out.println(decrypt(ciphertext));
  }

  public static String encrypt(String plaintext)
    throws Exception
  {
    Cipher c = Cipher.getInstance("DESede/CBC/PKCS5Padding");
    c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(sharedkey, "DESede"), new IvParameterSpec(sharedvector));
    byte[] encrypted = c.doFinal(plaintext.getBytes("UTF-8"));
    return Base64.encode(encrypted);
  }

  public static String decrypt(String ciphertext)
    throws Exception
  {
    Cipher c = Cipher.getInstance("DESede/CBC/PKCS5Padding");
    c.init(Cipher.DECRYPT_MODE, new SecretKeySpec(sharedkey, "DESede"), new IvParameterSpec(sharedvector));
    byte[] decrypted = c.doFinal(Base64.decode(ciphertext));
    return new String(decrypted, "UTF-8");
  }

}

出力:

zQPZgQHpjxR + 41Bc6 + 2Bvqo7 + pQAxBBVN + 0V1tRXcOc =

userNameHere:passwordHere

于 2009-09-09T18:11:32.513 に答える
2

いくつか問題があります、

  1. .NETとJavaの両方で同じキーマテリアルを生成する場合は、キーを24バイトにする必要があります。
  2. IVはブロックサイズである必要があります。これはトリプルDESの場合は8バイトです。
  3. Javaでは、デフォルトのモードとパディングを指定する必要があります。これは「DESede / CBC/NoPadding」です。

これらの変更を行うと、Java側で復号化できるようになります。

于 2009-09-09T18:06:23.863 に答える
0

.NETコードがJavaコードと同じパディングを使用していることを確認しましたか?.NETコードでパディングが指定されていないので、質問します。

たまたまJavaコードのソースがありますか?それは間違いを見つけるのに役立ちます。

于 2009-09-09T16:57:59.987 に答える
0

次のことを試してください。実際の使用法としては、commonsコーデックのようなbase64ライブラリを入手するか、BouncyCastleに付属のコーデックを使用します。

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;

public class Encryption {

    private static SecretKey sharedkey;
    private static byte [] sharedvector;

    static {
        int keySize = 168;
        int ivSize = 8;
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
            keyGenerator.init(keySize);
            sharedkey = keyGenerator.generateKey();

            sharedvector = new byte [ivSize];
            byte [] data = sharedkey.getEncoded();

            int half = ivSize / 2;
            System.arraycopy(data, data.length-half, sharedvector, 0, half);
            System.arraycopy(sharedvector, 0, sharedvector, half, half);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    public static void main(String [] args) throws Exception {
        System.out.println(Decrypt(Encrypt("Hello World")));

    }

    public static String Encrypt(String val) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, sharedkey, new IvParameterSpec(sharedvector));

        return new sun.misc.BASE64Encoder().encode(cipher.doFinal(val.getBytes()));
    }

    public static String Decrypt(String val) throws GeneralSecurityException, IOException {
        Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, sharedkey, new IvParameterSpec(sharedvector));

        return new String(cipher.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(val)));
    }

}
于 2009-09-09T17:15:43.470 に答える