Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rfc2898DeriveBytes for java?_Java_Android_.net_Encryption_Rfc2898 - Fatal编程技术网

Rfc2898DeriveBytes for java?

Rfc2898DeriveBytes for java?,java,android,.net,encryption,rfc2898,Java,Android,.net,Encryption,Rfc2898,我的后端服务器基于.NET。 在服务器上使用Rfc2898DeriveBytes加密 这是.Net的代码 public static string Encrypt(string clearText) { string EncryptionKey = "abc123"; byte[] clearBytes = Encoding.Unicode.GetBytes(clearText); using (Aes encryptor = Aes.Cr

我的后端服务器基于.NET。 在服务器上使用Rfc2898DeriveBytes加密

这是.Net的代码

public static string Encrypt(string clearText)
    {
        string EncryptionKey = "abc123";
        byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
        using (Aes encryptor = Aes.Create())
        {
            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
            encryptor.Key = pdb.GetBytes(32);
            encryptor.IV = pdb.GetBytes(16);
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(clearBytes, 0, clearBytes.Length);
                    cs.Close();
                }
                clearText = Convert.ToBase64String(ms.ToArray());
            }
        }
        return clearText;
    }
我正在用JAVA编写客户机。这是密码

try {
        String encryptKey = "abc123";
        byte[] salt = new byte[]{0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76};
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        KeySpec spec = new PBEKeySpec(encryptKey.toCharArray(), salt, 1024, 128);
        SecretKey tmp = factory.generateSecret(spec);
        SecretKeySpec secret = new SecretKeySpec(tmp.getEncoded(), "AES");
        System.out.println("Key:" + Base64.encodeToString(secret.getEncoded(), Base64.DEFAULT));


        String cleartext = "12345";
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secret);
        AlgorithmParameters params = cipher.getParameters();
        byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
        byte[] ciphertext = cipher.doFinal(cleartext.getBytes("UTF-8"));
        System.out.println("IV:" + Base64.encodeToString(iv, Base64.DEFAULT));
        System.out.println("Cipher text:" + Base64.encodeToString(ciphertext, Base64.DEFAULT));;
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (InvalidKeySpecException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (InvalidParameterSpecException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
我在java中没有得到与.Net相同的结果。 服务器上
12345
的加密值为
dAQWIrbtHv/eDbu+4oJD0g==

当我得到
tcvGLK5r99jt6PFLALpRfQ==


我需要应用什么修复?

Rfc2898DeriveBytes的默认迭代计数是1000,而不是1024(per)

我不知道
PBEKeySpec
keyLength
值是字节还是位,但在Java中是128位,在C#中是256位(32字节)

嗯,实际上,你要求的是384位的C。因为前256成为您的密码密钥,然后下128成为您的IV(您似乎让它在Java中随机生成)


因此,您可能需要请求384位,调用
getEncoded()
,将答案拆分为一个32字节的密钥和一个16字节的IV,然后从那里开始。

Rfc2898DeriveBytes的默认迭代计数是1000,而不是1024(per)

我不知道
PBEKeySpec
keyLength
值是字节还是位,但在Java中是128位,在C#中是256位(32字节)

嗯,实际上,你要求的是384位的C。因为前256成为您的密码密钥,然后下128成为您的IV(您似乎让它在Java中随机生成)


因此,您可能需要请求384位,调用
getEncoded()
,将答案拆分为一个32字节的密钥和一个16字节的IV,然后从那里开始。

我还对.Net代码进行了一些调整,从而解决了这个问题。 Android代码如下所示

public class AES256Cipher {

private static byte[] encrypt(byte[] ivBytes, byte[] keyBytes, byte[] textBytes)
        throws java.io.UnsupportedEncodingException,
        NoSuchAlgorithmException,
        NoSuchPaddingException,
        InvalidKeyException,
        InvalidAlgorithmParameterException,
        IllegalBlockSizeException,
        BadPaddingException {

    AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
    SecretKeySpec newKey = new SecretKeySpec(keyBytes, "AES");
    Cipher cipher = null;
    cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, newKey, ivSpec);
    return cipher.doFinal(textBytes);
}

private static byte[] decrypt(byte[] ivBytes, byte[] keyBytes, byte[] textBytes)
        throws java.io.UnsupportedEncodingException,
        NoSuchAlgorithmException,
        NoSuchPaddingException,
        InvalidKeyException,
        InvalidAlgorithmParameterException,
        IllegalBlockSizeException,
        BadPaddingException {

    AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
    SecretKeySpec newKey = new SecretKeySpec(keyBytes, "AES");
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, newKey, ivSpec);
    return cipher.doFinal(textBytes);
}

final static String key = "0123456789abcdefghijklmnopqrstuv";

final static byte[] ivBytes = new byte[]{0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

public static String encryptData(String plainText) {
    String base64Text = "";
    try {
        byte[] keyBytes = key.getBytes("UTF-8");
        byte[] x = plainText.getBytes("UTF-8");
        byte[] cipherData = encrypt(ivBytes, keyBytes, plainText.getBytes("UTF-8"));
        base64Text = Base64.encodeToString(cipherData, Base64.DEFAULT);
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (InvalidAlgorithmParameterException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    }
    return base64Text;
}

//############## Response(decrypt) ##############
public static String decryptData(String base64Text) {
    String plainText = "";
    try {
        byte[] keyBytes = key.getBytes("UTF-8");
        try {
            byte[] cipherData = decrypt(ivBytes, keyBytes, Base64.decode(base64Text.getBytes("UTF-8"), Base64.DEFAULT));
            plainText = new String(cipherData, "UTF-8");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return plainText;
}
}
只需按以下方式调用

String en = AES256Cipher.encryptData("1234");
        Log.e("enc length", en.length() + "");
        Log.e("enc", en);
        String de = AES256Cipher.decryptData(en);
        Log.e("dec", de);
对于使用java的用户,可以使用包java.util中的Base64 将加密方法中的替换为此

base64Text =Base64.getEncoder().encodeToString(cipherData);
在decrypt方法中,替换为此

byte[] cipherData = decrypt(ivBytes, keyBytes,Base64.getDecoder().decode(base64Text.getBytes("UTF-8")));

通过对.Net代码进行一些调整,我能够解决这个问题。 Android代码如下所示

public class AES256Cipher {

private static byte[] encrypt(byte[] ivBytes, byte[] keyBytes, byte[] textBytes)
        throws java.io.UnsupportedEncodingException,
        NoSuchAlgorithmException,
        NoSuchPaddingException,
        InvalidKeyException,
        InvalidAlgorithmParameterException,
        IllegalBlockSizeException,
        BadPaddingException {

    AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
    SecretKeySpec newKey = new SecretKeySpec(keyBytes, "AES");
    Cipher cipher = null;
    cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, newKey, ivSpec);
    return cipher.doFinal(textBytes);
}

private static byte[] decrypt(byte[] ivBytes, byte[] keyBytes, byte[] textBytes)
        throws java.io.UnsupportedEncodingException,
        NoSuchAlgorithmException,
        NoSuchPaddingException,
        InvalidKeyException,
        InvalidAlgorithmParameterException,
        IllegalBlockSizeException,
        BadPaddingException {

    AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
    SecretKeySpec newKey = new SecretKeySpec(keyBytes, "AES");
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, newKey, ivSpec);
    return cipher.doFinal(textBytes);
}

final static String key = "0123456789abcdefghijklmnopqrstuv";

final static byte[] ivBytes = new byte[]{0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

public static String encryptData(String plainText) {
    String base64Text = "";
    try {
        byte[] keyBytes = key.getBytes("UTF-8");
        byte[] x = plainText.getBytes("UTF-8");
        byte[] cipherData = encrypt(ivBytes, keyBytes, plainText.getBytes("UTF-8"));
        base64Text = Base64.encodeToString(cipherData, Base64.DEFAULT);
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (InvalidAlgorithmParameterException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    }
    return base64Text;
}

//############## Response(decrypt) ##############
public static String decryptData(String base64Text) {
    String plainText = "";
    try {
        byte[] keyBytes = key.getBytes("UTF-8");
        try {
            byte[] cipherData = decrypt(ivBytes, keyBytes, Base64.decode(base64Text.getBytes("UTF-8"), Base64.DEFAULT));
            plainText = new String(cipherData, "UTF-8");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return plainText;
}
}
只需按以下方式调用

String en = AES256Cipher.encryptData("1234");
        Log.e("enc length", en.length() + "");
        Log.e("enc", en);
        String de = AES256Cipher.decryptData(en);
        Log.e("dec", de);
对于使用java的用户,可以使用包java.util中的Base64 将加密方法中的替换为此

base64Text =Base64.getEncoder().encodeToString(cipherData);
在decrypt方法中,替换为此

byte[] cipherData = decrypt(ivBytes, keyBytes,Base64.getDecoder().decode(base64Text.getBytes("UTF-8")));

您需要从Java中的PBKDF2获取IV,但您总是生成一个随机IV。@ArtjomB。如果可能的话,你能分享这些代码吗?如果你写了所有的代码,那么你可能也可以进行更改?或者你只是复制并粘贴了你的安全代码?@LukePark我从这个网站复制了代码-@WISHY你找到了什么解决方案吗?你需要从Java中的PBKDF2获取IV,但你总是随机生成一个IV。@ArtjomB。如果可能的话,你能分享这些代码吗?如果你写了所有的代码,那么你可能也可以进行更改?还是你只是复制并粘贴了你的安全代码?@LukePark我是从这个网站复制的代码-@WISHY你找到了解决方案吗?