【问题标题】:javax.crypto.IllegalBlockSizeException: Input length not multiple of 8 bytesjavax.crypto.IllegalBlockSizeException:输入长度不是 8 个字节的倍数
【发布时间】:2014-08-21 11:43:19
【问题描述】:

我在解密时遇到了这个错误,我浏览了类似的帖子,但我没有从那里得到任何帮助。我想将一个对象直接存储在一个加密的文件中,因为我已经发布了我的问题here。但是在使用流时,我遇到了与使用字符串时相同的错误。

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("tarunvermacdac@gmail.com") ;

        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);
    }
}

【问题讨论】:

    标签: java des tripledes


    【解决方案1】:

    我不完全知道您想要实现什么,但我至少可以解释您遇到的错误。

    DES3DESblock-length64 bit。这意味着您必须将长度为 64 位的倍数明文 传递给加密函数。为了达到这个目的,你通常pad / 用某种模式的数据填充明文的最后一个块,这样你就可以在解密后轻松地再次删除它。

    在您的代码中,您可以像这样指定加密参数:DESede/ECB/NoPadding
    因此,您明确选择不自动应用任何填充。


    要解决此问题,只需指定填充模式(例如 PKCS5Padding)而不是 NoPadding

    注意:密码模式ECB 根本不安全!你应该更好地使用:

    Cipher.getInstance("DESede/CBC/PKCS5Padding"); // or "AES" instead of "DESede"
    

    (您必须提供额外的IV,但使用CBCCTR 等模式时)

    【讨论】:

    • (Classic/Single)DES 确实太弱了,但DESede 是 Java(或 JCA)的名称,大多数人称之为 Triple-DES,并且仍然可以安全地使用完整的 192-真正的 168 位密钥; AES 支持 128、192 或 256 位密钥,如果您有“无限强度策略”模式,请参阅 Oracle 网站。 CBC 适用于大多数情况,但您需要更改代码以提供 IV。 JCA 使用拼写 PKCS5Padding,尽管它实际上实现了 PKCS7 增强,即块大小为 16 和 8。
    • 非常感谢您指出我的错误。我用你的信息更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-28
    • 1970-01-01
    • 1970-01-01
    • 2013-06-18
    • 2012-06-05
    • 1970-01-01
    相关资源
    最近更新 更多