2012-02-09 3 views
1

BouncyCastle 제품군을 사용하여 Java에서 3DES를 사용하여 일반 텍스트를 암호화하는 데 실패했습니다. 이 결과는 나중에 해독 할 예정이므로 기존 C# 구현에 의해 생성 된 결과와 일치해야합니다.CES 구현과 다른 출력을보고하는 3DES 암호화 구현

나는 Java에서 C# algo의 "동급"을 제작했다고 확신하지만 다른 결과가 계속 나타납니다. 누군가가 친절하게 두 발췌문을보고 조언 할 수 있습니까? 나는 가장 감사 할 것입니다.

C 번호 암호화 : 나는 진수로 결과를 변환에 사용이 도우미 기능이 있습니다

public static byte[] encryptStringToBytes_3DES(string plainText, string passKey) 
    { 
     // Check arguments. 
     if (plainText == null || plainText.Length <= 0) 
      throw new ArgumentNullException("plainText"); 

     // Declare the streams used 
     // to encrypt to an in memory 
     // array of bytes. 
     MemoryStream msEncrypt = null; 
     CryptoStream csEncrypt = null; 
     StreamWriter swEncrypt = null; 
     ASCIIEncoding ascii = new System.Text.ASCIIEncoding(); 


     // used to encrypt the data. 
     TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider(); 
     string passphrase = passKey; 
     byte[] iv = ascii.GetBytes("AVREWASH"); 
     byte[] key = ascii.GetBytes(passphrase); 

     try 
     { 
      // Create a TripleDES object 
      // with the specified key and IV. 
      //Console.WriteLine("Key size is " + tdes.KeySize+" and IV is "+tdes.IV+" and that of key is "+key.Length); 
      tdes.Key = key; 
      tdes.IV = iv; 
      tdes.Padding = PaddingMode.Zeros; 

      // Create a decrytor to perform the stream transform. 
      ICryptoTransform encryptor = tdes.CreateEncryptor(tdes.Key, tdes.IV); 

      // Create the streams used for encryption. 
      msEncrypt = new MemoryStream(); 
      csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write); 
      swEncrypt = new StreamWriter(csEncrypt); 

      //Write all data to the stream. 
      swEncrypt.Write(plainText); 

     } 
     catch (Exception ex) 
     { 
      Console.WriteLine("Error is " + ex.Message); 
      while (true) 
      { 
      } 
     } 

     finally 
     { 
      // Clean things up. 

      // Close the streams. 
      if (swEncrypt != null) 
       swEncrypt.Close(); 
      if (csEncrypt != null) 
       csEncrypt.Close(); 
      if (msEncrypt != null) 
       msEncrypt.Close(); 

      // Clear the TripleDES object. 
      if (tdes != null) 
       tdes.Clear(); 
     } 

     // Return the encrypted bytes from the memory stream. 
     return msEncrypt.ToArray(); 

} 

... 자바는 "해당"암호화를 수행 할 예정 스 니펫을

public static string ByteArrayToString(byte[] ba) 
    { 
     string hex = BitConverter.ToString(ba); 
     return hex.Replace("-", ""); 
    } 

도 다음 :

public void encrypt(String plaintext, String IV, String tripleDesKey){ 

try{ 

    SecretKey keySpec = new SecretKeySpec(tripleDesKey.getBytes("US-ASCII"),"DESede"); 

    IvParameterSpec iv = new IvParameterSpec(IV.getBytes("US-ASCII")); 

    Cipher e_cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); 
    e_cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv); 

    byte [] cipherText = e_cipher.doFinal(plaintext.trim().getBytes("US-ASCII")); 

     System.out.println("Ciphertext: " + asHex(cipherText)); 
} 
catch(Exception exc){ 
ex.printStackTrace(); 
} 
} 

여기에 해당하는 16 진수입니다. function

public static String asHex (byte buf[]) { 
    StringBuffer strbuf = new StringBuffer(buf.length * 2); 
    int i; 

    for (i = 0; i < buf.length; i++) { 
    if (((int) buf[i] & 0xff) < 0x10) 
     strbuf.append("0"); 

    strbuf.append(Long.toString((int) buf[i] & 0xff, 16)); 
    } 

    return strbuf.toString(); 
} 

제발 도와주세요.

+0

문자 세트 (UTF 등)를 두 번 확인합니다. String은 때때로 이런 종류의 물건을 다룰 때, 특히 getBytes()를 호출 할 때 기본값을가집니다. 모든 javadoc을 읽으십시오. –

답변

3

다른 채우기 모드를 사용하고 있습니다. C#에서는 tdes.Padding = PaddingMode.Zeros; 을, 자바에서는 PKCS5Padding을 CBC 모드로 사용했습니다. 이것은 같은 것이 아닙니다.

+0

네 말이 맞다! 나는 그것을 분 전에 알아 챘다. 나는 자바의 패딩 계획을 DESede/CBC/ZeroBytePadding으로 업데이트해야했다. 무리 감사!! – user1197611

+1

ZeroBytePadding이 항상 최상의 패딩 방식이 아닙니다.암호 해독 중에 메시지에서 '0x00' 바이트를 잃을 수 있습니다. PKCS7, ISO 10126 또는 ANSI x.923 패딩 모드를 사용하는 것이 좋습니다. 이러한 패딩 모드는 해독 후 메시지 길이가 그대로 유지되도록합니다. – werewindle

3

일부 의견 :

  1. 의 .NET TripleDESCryptoServiceProvider의 기본 모드는 실제로 당신이 당신의 자바 코드에서 명시 적으로 지정하는 것입니다 CBC,하지만 당신이 명시 적으로 지정하면이 해치지 않을 것이다 당신의 C# 코드도 있습니다.

  2. 원본 코드에서 C# 코드에서는 PaddingMode.Zeros를 사용하지만 자바 코드에서는 PKCS5Padding을 사용합니다. AFAIK에는 PaddingMode.Zeros와 동일한 기능을 제공하는 Java의 암호 공급자가 없습니다. 여전히 C# 코드를 변경할 수 있으면 PaddingMode.Pkcs7을 대신 사용해야합니다. 그렇지 않으면 작업을 수행 할 Java 용 타사 암호 공급자를 검색해야합니다.

  3. 실제로 입력에 7 비트 ASCII가 포함되지 않는다면 ASCII 인코딩을 사용하지 마십시오. 다른 문자로 문자열을 전달하면 결과는 정의되지 않습니다.

  4. 3DES 생성자에 전달하는 키 데이터의 길이는 8, 16 또는 24이며 일반적으로 DES 패리티 비트가 설정되어야합니다. AFAIK .NET과 Java는 패리티 비트를 무시하지만 키 길이가 올바른 값 중 하나에 속하지 않으면 다르게 동작 할 수 있습니다. 따라서 암호화가 가능한 모든 키 입력에 대해 작동하도록하려면 .NET 및 Java에서 모두 지원되는 키 파생 함수를 사용해야합니다. Java에서 PBEWithHmacSHA1AndDESede를 시도하고 C#에서 System.Security.Cryptography.Rfc2898DeriveBytes를 사용하여 passKey를 변환하는 코드를 추가합니다.

관련 문제