将.NET Rijndael Managed AES解密函数转换为Java的正确方法是什么?

时间:2018-03-16 18:34:52

标签: java vb.net aes rijndael

需要帮助将以下示例代码从.NET VB代码转换为java以包含在jsp页面中。我看过一些似乎都有部分答案的问题。

Public Function Decrypt(ByVal TokenKey As String, ByVal DataString As String) As String
        Dim ms As MemoryStream = Nothing
        Dim cs As CryptoStream = Nothing
        Try
            Using AES As New RijndaelManaged()
                AES.KeySize = 128
                AES.BlockSize = 128
                Dim EncryptedData As Byte() = System.Convert.FromBase64String(DataString)
                Dim SecretKey As New Rfc2898DeriveBytes(TokenKey, New Byte() {<Your salt>})
                Using Decryptor As ICryptoTransform = AES.CreateDecryptor(SecretKey.GetBytes(16), SecretKey.GetBytes(16))
                    ms = New MemoryStream(EncryptedData)
                    Using ms
                        cs = New CryptoStream(ms, Decryptor, CryptoStreamMode.Read)
                        Using cs
                            Dim PlainText As Byte() = New Byte(EncryptedData.Length - 1) {}
                            Return Encoding.Unicode.GetString(PlainText, 0, cs.Read(PlainText, 0, PlainText.Length))
                        End Using
                    End Using
                End Using

            End Using
        Catch ex As Exception
            Return "Error - " & ex.Message
        Finally
            If ms IsNot Nothing Then
                ms.Close()
            End If
            If cs IsNot Nothing Then
                cs.Close()
            End If
        End Try
End Function

1 个答案:

答案 0 :(得分:0)

我必须查找stackoverflow上的多个问题,每个问题都提供了拼图的部分内容。这是上面例子的一个有效的java解决方案。解决方案的关键如下:

按要求说明:

.NET Rijendael实现在CBC模式下使用AES以及基础算法的PKCS#7填充

RFC2898密钥派生与使用java PBKFD2进行较新的实现相同

在Windows上,密码的编码需要UTF-16LE

解密的最终结果需要一个新的字符串&#39;而不是byte [] toString

注意:该解决方案使用128位AES,但可以通过正确分配后续密钥并相应地修改阵列副本来更改为256,但是128的块大小不能更改。

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException;

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

import org.apache.commons.codec.binary.Base64;


/**
  * Hello world!
  *
  */
public class App 
{
private final String extCharEnc = "UTF-8";
private final String intCharEnc = "UTF-16LE";
private final String cipherTransformation = "AES/CBC/PKCS5Padding";
private final String aesEncryptionAlgorithm = "AES";
private final byte[] salt = {<Your salt>};

public  byte[] decryptInternal(byte[] cipherText, String sharedKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException, UnsupportedEncodingException
{
    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
    //Please note that the last parameter in the following function is key size (128) + blocksize 128 = 256
    //If you do use an AES keysize of 256 then the last parameter will be 384 etc.
    PBEKeySpec pbeKeySpec = new PBEKeySpec(sharedKey.toCharArray(), salt, 1000, 256);
    Key secretKey = factory.generateSecret(pbeKeySpec);
    byte[] key = new byte[16];
    byte[] iv = new byte[16];
    System.arraycopy(secretKey.getEncoded(), 0, key, 0, 16);
    System.arraycopy(secretKey.getEncoded(), 16, iv, 0, 16);

    SecretKeySpec secret = new SecretKeySpec(key, aesEncryptionAlgorithm);
    AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
    Cipher cipher = Cipher.getInstance(cipherTransformation);
    cipher.init(Cipher.DECRYPT_MODE, secret, ivSpec);
    return(cipher.doFinal(cipherText));

}

public byte[] encryptInternal(String plaintext, String sharedKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException, InvalidKeySpecException
{
    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");   
    PBEKeySpec pbeKeySpec = new PBEKeySpec(sharedKey.toCharArray(), salt, 1000, 256);
    Key secretKey = factory.generateSecret(pbeKeySpec);
    byte[] key = new byte[16];
    byte[] iv = new byte[16];
    System.arraycopy(secretKey.getEncoded(), 0, key, 0, 16);
    System.arraycopy(secretKey.getEncoded(), 16, iv, 0, 16);

    SecretKeySpec secret = new SecretKeySpec(key, aesEncryptionAlgorithm);
    AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
    Cipher cipher = Cipher.getInstance(cipherTransformation);
    cipher.init(Cipher.ENCRYPT_MODE, secret, ivSpec);
    return(cipher.doFinal(plaintext.getBytes(intCharEnc)));

}

/// <summary>
/// Encrypts plaintext using AES 128bit key and a Chain Block Cipher and returns a base64 encoded string
/// </summary>
/// <param name="plainText">Plain text to encrypt</param>
/// <param name="key">Secret key</param>
/// <returns>Base64 encoded string</returns>
public String encrypt(String plainText, String key) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException{
    return URLEncoder.encode(Base64.encodeBase64String(encryptInternal(plainText, key)), extCharEnc);
}

/// <summary>
/// Decrypts a base64 encoded string using the given key (AES 128bit key and a Chain Block Cipher)
/// </summary>
/// <param name="encryptedText">Base64 Encoded String</param>
/// <param name="key">Secret Key</param>
/// <returns>Decrypted String</returns>
public String decrypt(String encryptedText, String sharedKey) throws KeyException, GeneralSecurityException, GeneralSecurityException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, IOException{
   String cipheredBytes = URLDecoder.decode(encryptedText, extCharEnc);       
   return new String(decryptInternal(Base64.decodeBase64(cipheredBytes), sharedKey), intCharEnc);
}

public static void main( String[] args )
{ 
    App myApp = new App();
    String SharedKey = <Your Shared Key>;
    String InputStr =  <Test string to encrypt and decrypt>;

    String EncryptedStr = null;
    String DecryptedStr = null;

    try {
        EncryptedStr = myApp.encrypt(InputStr, SharedKey);
        DecryptedStr = myApp.decrypt(EncryptedStr, SharedKey);
        System.out.println( "This is the Encrypted String: " + EncryptedStr + " \nThis is the Decrypted String: " + DecryptedStr);
    } catch (KeyException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvalidAlgorithmParameterException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (BadPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (GeneralSecurityException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }


}

}