3

DESアルゴリズムを使用してJavaで暗号化された暗号化された文字列を復号化する際に問題が発生しました。私の主な問題は、JavaコードにsaltまたはIVの仕様が表示されないことだと思います。

私は次の情報を持っています:このHexSequenceは私が解読しなければならない暗号化されたデータです:9465E19A6B9060D75C3F7256ED1F4D21EDC18BB185304B92061308A32725BE760F1847E3B19C1D3548F61165EA2E785E48F61165EA2E78

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

復号化後、次のようになります:550000000018h000000273Al2011112214340600000000000000000000000000

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

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 "";
}
}

次の.netコードを使用してデータを復号化しようとしました。

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バイトにする必要があります。配列のandに0バイトを追加しますが、これを行わないと、cryptostreamは、復号化するデータが短すぎるというエラーをスローします。

この方法で試してみると、出力としてガベージしか取得できません。Javaコードが使用しているソルトとIVがわからないため、空のソルトとIVを使用しています。わからないデフォルト値はありますか?

編集:hexCodeからバイトを取得するJavaコード:

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

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

4

1 に答える 1

2

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

これの例外は、キーストリームを効果的に作成するモードで使用されるDESであり、その後、プレーンテキストとXORされて、暗号文が生成されます。これには、CFB、OFB、およびCTRモードが含まれます。したがって、1つの可能性は、これらのいずれかを使用した復号化が機能することです(頭から離れて、.NET暗号ライブラリがCTRをサポートしているかどうかを思い出せません)。ECBがJavaコードで指定されていることを確認しますか?

ただし、Javaコードはキーテキストから16進変換を行ってキーバイトを取得しているように見えるのに対し、.NETコードはRFC-2898互換の変換を行っているため、同じキーバイト。

于 2012-01-10T15:05:55.840 に答える