문제

제발, 왜 그런지 묻지 마세요. 이 코드는 .NET에 데이터의 문자열을 암호화/해독하는이 코드를 가지고 있습니다. 나는 이제 Java에서 동일한 기능을 '정확하게'만들어야합니다. Desede Crypt에 대한 몇 가지 예를 시도했지만 .NET 에서이 클래스와 동일한 결과를 제공하지 않았습니다.

비록 .NET에 쓰여진이 두 가지 방법을 제공하기 위해 SSL 뒤에 .NET WEBSERBVICE를 만들지 만 모든 위치를 소진하지 않고 너무 어리석은 일입니다.

아마도이 지역에서 더 관련이있는 자바 사람들 중 일부는 머리 위에 그것을 만드는 방법을 가질 것입니다.

감사 !!!

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"
도움이 되었습니까?

해결책

코드는 다음과 같이하지만 먼저 몇 가지 메모가 있습니다.

  1. 모든 메시지마다 다른 초기화 벡터를 선택해야합니다. 초기화 벡터를 하드 코딩하는 것은 의미가 없습니다. IV는 암호 텍스트와 함께 메시지 수신자에게 보내야합니다 (비밀이 아닙니다).
  2. Base-64 인코딩에 내 자신의 유틸리티 클래스를 사용했습니다. 당신이 사용할 수있는 sun.misc.BASE64Encoder 그리고 sun.misc.BASE64Decoder 대신, Bouncycastle과 같은 타사 도서관을 사용하거나 직접 작성하십시오.
  3. 첫 번째 키와 세 번째 키는 동일한 2 키 트리플 DES를 사용하고 있습니다. 나는 수정했다 sharedkey 이를 반영하기 위해 Java Desede Cipher는 항상 192 비트 키가 필요하기 때문입니다. 키잉 옵션을 처리하는 것은 키 생성기에 달려 있습니다.
  4. CBC IV는 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

다른 팁

몇 가지 문제가 있습니다.

  1. .NET 및 Java에서 동일한 키 재료를 생성하려면 키가 24 바이트 여야합니다.
  2. IV는 블록 크기 여야하며 트리플 DES의 경우 8 바이트입니다.
  3. Java에서는 "desede/cbc/nopadding"인 기본 모드와 패딩을 지정해야합니다.

이러한 변경을 수행하면 Java 측에서 해독 할 수 있어야합니다.

.NET 코드가 Java 코드와 동일한 패딩을 사용하는지 확인 했습니까? .NET 코드에 지정된 패딩이 보이지 않기 때문에 묻는 이유입니다.

Java 코드의 소스를 가지고 있습니까? 실수를 찾는 데 도움이 될 것입니다.

다음을 시도하십시오. 실제 사용을 위해 Commons Codec과 같은 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)));
    }

}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top