java javax.crypto.IllegalBlockSizeException:输入长度不是 8 字节的倍数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25425486/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
javax.crypto.IllegalBlockSizeException: Input length not multiple of 8 bytes
提问by tarun verma
i am getting this error while decryption i have go through the similar posts but i did not get any help from there. I want to store an object directly in a file with encryption for that i have posted my question here. But while using stream i am getting the same error as i am getting with string.
我在解密时遇到这个错误我已经浏览了类似的帖子,但我没有从那里得到任何帮助。我想将一个对象直接存储在一个带有加密的文件中,因为我在这里发布了我的问题。但是在使用流时,我遇到了与字符串相同的错误。
package security;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/**
* This class defines methods for encrypting and decrypting using the Triple DES
* algorithm and for generating, reading and writing Triple DES keys. It also
* defines a main() method that allows these methods to be used from the command
* line.
*/
public class TripleDesEncryptionDecryption {
/**
* The program. The first argument must be -e, -d, or -g to encrypt,
* decrypt, or generate a key. The second argument is the name of a file
* from which the key is read or to which it is written for -g. The -e and
* -d arguments cause the program to read from standard input and encrypt or
* decrypt to standard output.
*/
private static final String UNICODE_FORMAT = "UTF-8";
public static final String DESEDE_ENCRYPTION_SCHEME = "DESede";
private KeySpec myKeySpec;
private SecretKeyFactory mySecretKeyFactory;
private Cipher cipher;
byte[] keyAsBytes;
private String myEncryptionKey;
private String myEncryptionScheme;
SecretKey key;
static String stringToEncrypt="";
public void setKey(String myKey) throws Exception
{
myEncryptionKey = myKey ;
myEncryptionScheme = DESEDE_ENCRYPTION_SCHEME;
keyAsBytes = myEncryptionKey.getBytes(UNICODE_FORMAT);
myKeySpec = new DESedeKeySpec(keyAsBytes);
mySecretKeyFactory = SecretKeyFactory.getInstance(myEncryptionScheme);
cipher = Cipher.getInstance("DESede/ECB/NoPadding");
key = mySecretKeyFactory.generateSecret(myKeySpec);
}
/**
* Method To Encrypt The String
*/
public String encrypt(byte[] plainText) {
String encryptedString = null;
try {
cipher.init(Cipher.ENCRYPT_MODE, key);
//byte[] plainText = unencryptedString.getBytes(UNICODE_FORMAT);
//byte[] encryptedText = cipher.doFinal(plainText);
BASE64Encoder base64encoder = new BASE64Encoder();
encryptedString = base64encoder.encode(plainText);
} catch (Exception e) {
e.printStackTrace();
}
return encryptedString;
}
/**
* Method To Decrypt An Ecrypted String
*/
public String decrypt(String encryptedString) {
String decryptedText=null;
try {
cipher.init(Cipher.DECRYPT_MODE, key);
BASE64Decoder base64decoder = new BASE64Decoder();
System.out.println(myEncryptionKey);
byte[] encryptedText = base64decoder.decodeBuffer(encryptedString);
byte[] plainText = cipher.doFinal(encryptedText);
decryptedText= bytes2String(plainText);
} catch (Exception e) {
e.printStackTrace();
}
return decryptedText;
}
/**
* Returns String From An Array Of Bytes
*/
private static String bytes2String(byte[] bytes) {
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
stringBuffer.append((char) bytes[i]);
}
return stringBuffer.toString();
}
/**
* Testing The DESede Encryption And Decryption Technique
*/
public static void main(String args []) throws Exception
{
TripleDesEncryptionDecryption myEncryptor= new TripleDesEncryptionDecryption();
myEncryptor.setKey("[email protected]") ;
System.out.println("tarun1234".getBytes());
String encrypted=myEncryptor.encrypt("tarun".getBytes());
String decrypted=myEncryptor.decrypt(encrypted);
System.out.println("String To Encrypt: "+stringToEncrypt);
System.out.println("Encrypted Value :" + encrypted);
System.out.println("Decrypted Value :"+decrypted);
}
}
回答by i_turo
I don't exactly know what you want to achieve, but I can at least explain the error you are getting.
我不完全知道您想要实现什么,但我至少可以解释您遇到的错误。
DESand 3DEShave a block-lengthof 64 bit
. That means you must pass a plaintextwhich length is a multiple of 64-bitsto the encryption-function. To achieve this you usually pad/ fill up the last block of the plaintext with data of a certain pattern so that you can easily remove it again after decryption.
DES和3DES的块长度为64 bit
. 这意味着您必须将长度为64 位倍数的明文传递给加密函数。要做到这一点,你通常垫/填充了一定的模式的数据明文的最后一个数据块,这样你可以很容易地解密后再次将其删除。
In your code you specify the encryption-parameters like this: DESede/ECB/NoPadding
So you explicitly opt to not automatically apply any padding.
在您的代码中,您可以像这样指定加密参数:DESede/ECB/NoPadding
因此您明确选择不自动应用任何填充。
To fix this, just specify a padding mode (for example PKCS5Padding
) instead of NoPadding
.
要解决此问题,只需指定填充模式(例如PKCS5Padding
)而不是NoPadding
。
Note:The cipher-mode ECB
is not secure at all! You should instead better use:
注意:密码模式ECB
根本不安全!你应该更好地使用:
Cipher.getInstance("DESede/CBC/PKCS5Padding"); // or "AES" instead of "DESede"
(you must provide an additional IV
though when using a mode like CBC
or CTR
)
(您必须提供一个额外的,IV
但在使用像CBC
或的模式时CTR
)