从.Net到Java应用TripleDES算法出错 - java

对于我们当前的项目,我们需要将TripleDES MD5 CBC模式的加密数据发送给另一家公司。 pass,salt和init向量的值由公司提供,而不是此处给出的值(但长度相同)。

他们已向我们发送了用于加密它的代码(在.Net C#中),如下:

//Encription parameter def
static private string _pass = "12345678901234";
static private string _salt = "123456";
static private string _alg = "MD5";
static private string _iv = "1234567890123456";

public static string EncriptString(string textPlain)
{
    return EncriptString(textPlain, _pass, _salt, _alg, 1, _iv, 128); 
}

public static string EncriptString(string textPlain, string passBase, string saltValue, string hashAlgorithm, int passwordIterations, string initVector, int keySize)
{
    byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
    byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
    byte[] plainTextBytes = Encoding.UTF8.GetBytes(textPlain);

    PasswordDeriveBytes password = new PasswordDeriveBytes(passBase, saltValueBytes, hashAlgorithm, passwordIterations);
    byte[] keyBytes = password.GetBytes(keySize / 8);
    RijndaelManaged symmetricKey = new RijndaelManaged();
    symmetricKey.Mode = CipherMode.CBC;
    ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
    MemoryStream memoryStream = new MemoryStream();
    CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
    cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
    cryptoStream.FlushFinalBlock();
    byte[] cipherTextBytes = memoryStream.ToArray();
    memoryStream.Close();
    cryptoStream.Close();

    string cipherText = Convert.ToBase64String(cipherTextBytes);
    return cipherText;
}

我在Google和Stackoverflow上搜索了一天,试图将其翻译成JAVA,但我无法。这是我目前的方法:

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * @author alvaro
 */
public class Encriptor {

    // Constants -----------------------------------------------------

    private static final String PASS_PHRASE = "12345678901234";//says wrong length
    private static final String SALT_VALUE = "123456";
    private static final int PASSWORD_ITERATIONS = 1;
    private static final String INIT_VECTOR = "1234567890123456";
    private static final int KEY_SIZE = 128;

    // Attributes ----------------------------------------------------

    // Static --------------------------------------------------------

    // Constructors --------------------------------------------------

    // Public --------------------------------------------------------

    public String encrypt(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidKeySpecException {
        MessageDigest digest = MessageDigest.getInstance(DIGEST);
        digest.update(SALT_VALUE.getBytes());
        byte[] bytes = digest.digest(PASS_PHRASE.getBytes(ENCODING));
        SecretKey password = new SecretKeySpec(bytes, "AES");

        //Initialize objects
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        byte[] IV = INIT_VECTOR.getBytes();
        IvParameterSpec ivParamSpec = new IvParameterSpec(IV);
        cipher.init(Cipher.ENCRYPT_MODE, password, ivParamSpec);
        byte[] encryptedData = cipher.doFinal(text.getBytes(ENCODING));
        return new BASE64Encoder().encode(encryptedData).replaceAll("\n", "");
    }

    // Package protected ---------------------------------------------

    // Protected -----------------------------------------------------

    // Private -------------------------------------------------------

    // Inner classes -------------------------------------------------

}

问题在于,Java中MD5哈希的处理方式与C#中不同。

测试代码:

import org.junit.Test;

import static org.junit.Assert.*;

public class EncriptorTest {

    @Test
    public void shouldEncriptTextCorrectly() {
        // GIVEN
        String input = '<xml><oficina>1234</oficina><empleado>123456</empleado></xml>'
        String expected = 'Lz1aG3CFYoyzjGcMzJXDB7DQgscrv9scP+d5JY8/fiUN6LV2RsnSPqDU/E5BGKz3QbeSl3RyhUgnYyN3uBBRJA=='
        // WHEN
        String output = new Encriptor().encrypt(input)
        //THEN
        assertEquals('Wrong encription', expected, output)
    }
}

最后,我使用了另一个Stackoverlow question中给出的解决方案,其中给出了Java的PasswordDeriveBytes端口。

参考方案

您与另一方的沟通有误。

您说您正在尝试使用Triple DES,MD5,CBC;但是,他们使用的.Net代码说明了这一点:

RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;

Rijndael是被选为AES的算法的名称;他们给您的示例使用的是AES,而不是Triple DES。

三重DES需要3 * 56位的密钥(扩展为3 * 64),即168或192位,具体取决于您对位进行计数的方式。该API可能会消耗168位。 AES仅支持128、192和256位密钥大小,这说明了为什么可能会出现wrong size错误的原因。

您需要确定他们是否打算使用Triple DES或AES并修复代码的两面。

作为旁白:

已知单个DES非常不安全;在Amazon EC2上花费两美元可以破解DES。但是,三重DES大致上是安全的,但不建议进行新开发。
众所周知,MD5非常不安全,特别容易受到长度扩展攻击,图像前攻击,碰撞攻击等的影响。请改用SHA 1、2或3。

Java:我可以在Hashmaps中使用数组吗? - java

我可以在Hashmaps中使用数组吗?如果是这样,则声明这种哈希图的确切语法是什么?谢谢 参考方案 数组也是对象。甚至像int[]这样的原始数组。Map<String,String[]> map = new HashMap<String,String[]>();

Java:找到特定字符并获取子字符串 - java

我有一个字符串4.9.14_05_29_16_21,我只需要获取4.9。数字各不相同,所以我不能简单地获得此char数组的前三个元素。我必须找到最正确的.并将其子字符串化直到那里。我来自Python,因此我将展示Python的实现方法。def foobar(some_string): location = some_string.rfind('.&…

Java string.hashcode()提供不同的值 - java

我已经在这个问题上停留了几个小时。我已经注释掉所有代码,认为这与数组超出范围有关,但是这种情况仍在发生。我正在尝试使用扫描仪从文件中读取输入,存储数据并稍后使用哈希码获取该数据。但是哈希值不断变化。public static void main(String[] args) { //only prior code is to access data char…

Java-搜索字符串数组中的字符串 - java

在Java中,我们是否有任何方法可以发现特定字符串是字符串数组的一部分。我可以避免出现一个循环。例如String [] array = {"AA","BB","CC" }; string x = "BB" 我想要一个if (some condition to tell wheth…

在Java中使用新关键字和直接赋值的字符串 - java

String s="hi"; String s1=new String("hi"); 从内存角度看,s和s1存储在哪里?无论是在堆内存还是堆栈中。s指向“ hi”,而s1指向hi存在的内存位置?请帮忙? 参考方案 考虑以下 String s = "hi"; String s1 = new Strin…