2012-01-10 12 views
3

DESアルゴリズムを使用してJavaで暗号化された暗号化文字列の復号化に問題があります。私は私の主な問題は、私はJavaコードで塩やIVの仕様が表示されないと思う。私は、以下の情報をしているJavaから.NetへのDES暗号化データの復号

: このHexSequenceは私が解読する必要が暗号化されたデータである。9465E19A6B9060D75C3F7256ED1F4D21EDC18BB185304B92061308A32725BE760F1847E3B19C1D3548F61165EA2E785E48F61165EA2E78

アルゴリズム:キーDES/ECB/NoPadding、::DES、パディングTESTKEY123

復号化した後、私は取得する必要があります:550000000018h000000273Al2011112214340600000000000000000000000000

データを暗号化するために使用されるJavaコードは次のようになります。

私は、データを復号化するために、次の.NETのコードを使用しようとしました
public class Encryptor { 

private SecretKey secretKey; 
private Cipher cipher; 

public Encryptor(String algorithmName, String paddingName, String key) { 
    String keyHexCode = StringUtils.convertUnicodeToHexCode(key.getBytes()); 
    try { 
     byte[] desKeyData = StringUtils.convertHexStringToByteArray(keyHexCode); 

     DESKeySpec desKeySpec = null; 
     try { 
      desKeySpec = new DESKeySpec(desKeyData); 
     } catch (InvalidKeyException e) { 
      e.printStackTrace(); 
     } 
     SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithmName); 
     try { 
      secretKey = keyFactory.generateSecret(desKeySpec); 
     } catch (InvalidKeySpecException e) { 
      e.printStackTrace(); 
     } 

     try { 
      cipher = Cipher.getInstance(paddingName); 
     } catch (NoSuchPaddingException e) { 
      // TODO: handle exception 
     } 
    } catch (NoSuchAlgorithmException e) { 
     // TODO: handle exception 
    } 
} 

private void initEncryptor(int mode) { 
    try { 
     cipher.init(mode, secretKey); 
    } catch (InvalidKeyException e) { 
     // TODO: handle exception 
    } 
} 

public String encrypt(String clearText) { 
    initEncryptor(Cipher.ENCRYPT_MODE); 
    try { 
     // Encrypt the cleartext 
     byte[] encryptedBytes = cipher.doFinal(clearText.getBytes()); 
     return StringUtils.convertUnicodeToHexCode(encryptedBytes).toUpperCase(); 
    } catch (IllegalBlockSizeException e) { 
     // TODO: handle exception 
    } catch (BadPaddingException e) { 
     // TODO: handle exception 
    } 
    return ""; 
} 

public String decrypt(String encryptedTextHex) { 
    byte[] encryptedText = StringUtils.convertHexCodeSequenceToUnicode(encryptedTextHex); 
    initEncryptor(Cipher.DECRYPT_MODE); 
    try { 
     // Decrypt the encryptedTextHex 
     return new String(cipher.doFinal(encryptedText)); 
    } catch (IllegalBlockSizeException e) { 
     // TODO: handle exception 
    } catch (BadPaddingException e) { 
     // TODO: handle exception 
    } 
    return ""; 
} 
} 

public class URLDecryptor 
{ 
public static string GetValue(string Data) 
{ 
    DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider(); 
    byte[] bytes = System.Text.UnicodeEncoding.Unicode.GetBytes("TESTKEY123"); 
    byte[] salt = new byte[8]; 
    byte[] iv = new byte[8]; 
    Rfc2898DeriveBytes password = new Rfc2898DeriveBytes("TESTKEY123", salt); 
    cryptoProvider.Key = password.GetBytes(8); 
    cryptoProvider.IV = iv; 
    cryptoProvider.Padding = PaddingMode.None; 
    cryptoProvider.Mode = CipherMode.ECB; 

    MemoryStream memStream = new MemoryStream(convertHexCodeSequenceToUnicode(Data)); 
    CryptoStream cryptoStream = new CryptoStream(memStream, cryptoProvider.CreateDecryptor(cryptoProvider.Key, cryptoProvider.IV), CryptoStreamMode.Read); 
    StreamReader reader = new StreamReader(cryptoStream); 
    string value = reader.ReadToEnd; 

    reader.Close(); 
    cryptoStream.Close(); 

    return value; 
} 

private static byte[] convertHexCodeSequenceToUnicode(string hexCodeSequence) 
{ 
    byte[] bytes = new byte[(hexCodeSequence.Length/2) + 1]; //This is strange 
    int index = 0; 
    int count = 0; 
    while (count < hexCodeSequence.Length) { 
     string hexCode = hexCodeSequence.Substring(count, 2); 
     bytes[index] = getHexValue(hexCode); 
     count += 2; 
     index += 1; 
    } 

    return bytes; 
} 

public static byte getHexValue(string hexCode) 
{ 
    return byte.Parse(hexCode, System.Globalization.NumberStyles.HexNumber); 
} 
} 

奇妙何がそのラインです:

byte[] bytes = new byte[(hexCodeSequence.Length/2) + 1]; 

データは55バイト長であるが、私は配置する必要がありますそれは56バイトです。が配列に0バイトを追加しますが、これを行わなければ、暗号化ストリームは復号化するデータが短すぎるというエラーをスローします。

この方法で試してみると、私は出力としてゴミだけを取得します。私は空の塩とIVを使用しています。なぜなら、Javaコードがどの塩とIVを使用しているのかわからないからです。私が知らないデフォルト値はありますか?

EDIT:hexCodeのうちのバイトを取得する Javaコード:

private static byte getNegativeValueForHexConversion(String hexCode) { 
int i = Integer.parseInt(hexCode, 16); 
return (byte) (i > 127 ? i - 256 : i); 
} 

Javaは符号付きバイトを使用し、.NETがそのすべての機能のための符号なしバイトを使用していますように見えます。これはおそらく問題でしょうか?

答えて

2

DESは、64ビットブロックサイズのブロック暗号です。したがって、(少なくともECBモードで)解読する必要がある暗号文は、64ビット(8バイト)の倍数でなければなりません。あなたのものは55バイトなので、完全な暗号文を持っていないので、ゼロバイトを追加する必要があります。 Javaコードを自分で実行し、出力が55バイトであることを確認しましたか?これはコピー&ペーストエラーですか?

例外は、効果的に鍵ストリームを作成し、次に平文とXORして暗号文を生成するモードで使用されるDESです。これには、CFB、OFB、およびCTRモードが含まれます。したがって、1つの可能性は、これらのいずれかを使った解読がうまくいくことです(私の頭の上からは、.NET暗号ライブラリがCTRをサポートしているかどうか覚えていません)。 JavaコードでECBが指定されていますか?

しかし、.NETコードがRFC-2898互換変換を実行しているのに対して、キーコードをキーテキストから直接変換して16進数の変換を行うようなJavaコードがあるように見えます。同じキーバイトを与えることはありません。

+0

コピー&ペーストのエラーがないことを確認しました。私はJavaコードを実行しようとします。データの解読方法を教えてくれるECBが仕様書に明記されました。上記のポストでは、hexStringをバイト配列に変換する関数を追加しました。 – chrixko

+0

OK。これは、DESを使用したECB暗号化の出力ではないため、ECBを使用して復号化することはできません。暗号化するJavaコードを実行するとどうなるのか教えてください... –

+0

Javaコードを実行しようとしましたが、失敗しました。そこで私は入力文字列をもう一度見て、暗号化されたデータが間違っていることを知りました。オリジナルの暗号化されたデータは64バイト長で、うまくいきました。本当にありがとうあなたのポストは私を助けました! – chrixko