gpt4 book ai didi

java - java中AES解密算法异常

转载 作者:搜寻专家 更新时间:2023-10-31 08:18:22 24 4
gpt4 key购买 nike

我在 java 中的 AES 算法的以下代码中遇到异常。

代码解密加密的字符串并返回原始字符串。

请帮我解决这个问题。

代码:

public class AES 

{

public byte[] encrypted;

public byte[] original;

public String originalString;

public static String asHex (byte buf[])

{

StringBuffer strbuf = new StringBuffer(buf.length * 2);

int i; for (i = 0; i < buf.length; i++)

{

if (((int) buf[i] & 0xff) < 0x10) strbuf.append("0");

strbuf.append(Long.toString((int) buf[i] & 0xff, 16));

}

return strbuf.toString();

}

public String AESencryptalgo(byte[] text)

{

String newtext="";

// Get the KeyGenerator

try

{

KeyGenerator kgen = KeyGenerator.getInstance("AES");

kgen.init(128); // 192 and 256 bits may not be available

// Generate the secret key specs.

SecretKey skey = kgen.generateKey();

byte[] raw = skey.getEncoded();

SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");

// Instantiate the cipher Cipher cipher = Cipher.getInstance("AES");

cipher.init(Cipher.ENCRYPT_MODE, skeySpec); encrypted = cipher.doFinal(text);

System.out.println("encrypted string: " + asHex(encrypted));

cipher.init(Cipher.DECRYPT_MODE, skeySpec); original = cipher.doFinal(encrypted);

originalString = new String(original); System.out.println("Original string: " + originalString + " " + asHex(original));

}

catch(Exception e)

{ }

finally

{

newtext=new String(encrypted);

System.out.println("ENCRYPTED "+newtext);

//AESdecryptalgo(newtext.getBytes());

return newtext;

}

}

public String AESdecryptalgo(byte[] text)

{

// Get the KeyGenerator

try

{

KeyGenerator kgen = KeyGenerator.getInstance("AES");

kgen.init(128); // 192 and 256 bits may not be available

// Generate the secret key specs.

SecretKey skey = kgen.generateKey();

byte[] raw = skey.getEncoded();

SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");

// Instantiate the cipher

Cipher cipher = Cipher.getInstance("AES");

cipher.init(Cipher.DECRYPT_MODE, skeySpec);

original = cipher.doFinal(text); //Exception occurs here

originalString = new String(original);

System.out.println("Original string: " + originalString + " " + asHex(original));

}

catch(Exception e)

{

System.out.println("exception");

}

finally

{

System.out.println("DECRYPTED "+originalString);

return originalString;

}

}

public static void main(String[] args)

{

AES a=new AES();

a.AESencryptalgo("hello".getBytes());

System.out.println();

}}
`

异常(exception):

javax.crypto.BadPaddingException: Given final block not properly padded at  
com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) at
com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) at
com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..) at
javax.crypto.Cipher.doFinal(DashoA13*..)

最佳答案

根据 Java™ Cryptography Architecture (JCA) Reference Guide (强调我的):

Cipher objects are obtained by using one of the Cipher getInstance() static factory methods. Here, the algorithm name is slightly different than with other engine classes, in that it specifies not just an algorithm name, but a "transformation". A transformation is a string that describes the operation (or set of operations) to be performed on the given input to produce some output. A transformation always includes the name of a cryptographic algorithm (e.g., DES), and may be followed by a mode and padding scheme.

A transformation is of the form:

  • "algorithm/mode/padding" or
  • "algorithm"

For example, the following are valid transformations:

  • "DES/CBC/PKCS5Padding"
  • "DES"

If just a transformation name is specified, the system will determine if there is an implementation of the requested transformation available in the environment, and if there is more than one, returns there is a preferred one.

If both a transformation name and a package provider are specified, the system will determine if there is an implementation of the requested transformation in the package requested, and throw an exception if there is not.

If no mode or padding is specified, provider-specific default values for the mode and padding scheme are used. For example, the SunJCE provider uses ECB as the default mode, and PKCS5Padding as the default padding scheme for DES, DES-EDE and Blowfish ciphers. This means that in the case of the SunJCE provider:

Cipher c1 = Cipher.getInstance("DES/ECB/PKCS5Padding");

and

Cipher c1 = Cipher.getInstance("DES");

are equivalent statements.

Using modes such as CFB and OFB, block ciphers can encrypt data in units smaller than the cipher's actual block size. When requesting such a mode, you may optionally specify the number of bits to be processed at a time by appending this number to the mode name as shown in the "DES/CFB8/NoPadding" and "DES/OFB32/PKCS5Padding" transformations. If no such number is specified, a provider-specific default is used. (For example, the SunJCE provider uses a default of 64 bits for DES.) Thus, block ciphers can be turned into byte-oriented stream ciphers by using an 8 bit mode such as CFB8 or OFB8.

Appendix A of this document contains a list of standard names that can be used to specify the algorithm name, mode, and padding scheme components of a transformation.

The objects returned by factory methods are uninitialized, and must be initialized before they become usable.

因为您的代码没有指定模式或填充,所以使用了提供者特定的默认值。您的提供者似乎是 SunJCE,它的默认填充可能是 "NoPadding"。使用此填充,您负责确保被加密的字节数组的大小是 key 中字节数的倍数。您可以通过在转换中指定模式和填充来让您的生活更轻松:

Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

警告:您不应在实际代码中使用 ECB 模式。试试 CBC。

更新:我认为推荐 CBC 模式而不提供其工作原理的一些示例是不公平的:

public static void main(String... args) throws Exception {
byte[] data = "hello".getBytes();

KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128); // 192 and 256 bits may not be available

SecretKey secretKey = keyGenerator.generateKey();

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

// By initializing the cipher in CBC mode, an "initialization vector" has been randomly
// generated. This initialization vector will be necessary to decrypt the encrypted data.
// It is safe to store the initialization vector in plain text for later use. You can obtain
// it's bytes by calling iv.getIV().
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
IvParameterSpec iv = cipher.getParameters().getParameterSpec(IvParameterSpec.class);
byte[] encryptedData = cipher.doFinal(data);

// When decrypting the encrypted data, you must provide the initialization vector used
// during the encryption phase.
cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
byte[] decryptedData = cipher.doFinal(encryptedData);

if (!Arrays.equals(data, decryptedData)) {
throw new Exception("Data was not decrypted successfully");
}
}

关于java - java中AES解密算法异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3180878/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com