【问题标题】:Error javax.crypto.IllegalBlockSizeException: in Decryption错误 javax.crypto.IllegalBlockSizeException:在解密
【发布时间】:2015-05-31 04:43:21
【问题描述】:

我正在尝试使用 jks Keystore 文件加密和解密字符串。但是在解密时我收到以下错误...

这是我的加密解密课:

package com.Encrypt;

import java.io.FileInputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.UnrecoverableEntryException;
import java.security.UnrecoverableKeyException;
import java.security.KeyStore.PrivateKeyEntry;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.apache.commons.codec.binary.Base64;

public class Encrypt {

public String encyptCard(String card) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnrecoverableKeyException{
        FileInputStream is = new FileInputStream("C:/Users/admin/Desktop/keystore/ksjksformat.jks");    
        String keystpassw = "9801461740";
        String alias = "ksjksformat";       
            KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());                      
            ks.load(is,keystpassw.toCharArray() );          
            Certificate cert = ks.getCertificate(alias);            
            PublicKey publicKey = cert.getPublicKey();          
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] cipherData = cipher.doFinal(card.getBytes());        
        String cipherData1 = Base64.encodeBase64String(cipherData);
        return cipherData1;             
    }
public String decrypte (String encCardNo) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableEntryException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{
    FileInputStream is = new FileInputStream("C:/Users/admin/Desktop/keystore/ksjksformat.jks");    
    String keystpassw = "9801461740";
    String alias = "ksjksformat";       
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());                      
        ks.load(is,keystpassw.toCharArray() );      
        Key key = ks.getKey(alias, keystpassw.toCharArray());
        Certificate cert = ks.getCertificate(alias);
        PublicKey publicKey = cert.getPublicKey();
        new KeyPair(publicKey, (PrivateKey) (key));     
        KeyStore.ProtectionParameter protParam = new KeyStore.PasswordProtection(keystpassw.toCharArray());
        KeyStore.PrivateKeyEntry pkentry = (PrivateKeyEntry) ks.getEntry(alias, protParam);
        PrivateKey myPrivateKey =pkentry.getPrivateKey();
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, myPrivateKey); 
        byte[] cipherData = cipher.doFinal(encCardNo.getBytes());
        String decrypted =Base64.decodeBase64(cipherData).toString();
        return decrypted;
}
}

这是我调用这些方法的班级:-

package com.Encrypt;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableEntryException;
import java.security.cert.CertificateException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
public class CryptoHelper {
    public static void main(String[] argv) throws InvalidKeyException, KeyStoreException, NoSuchAlgorithmException, CertificateException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, IOException, UnrecoverableEntryException {

                Encrypt obj = new Encrypt();
                String answerEnc = obj.encyptCard("student");
                System.out.println("encrypted data----------->"+answerEnc);
                String Orginial_data = obj.decrypte(answerEnc);
                System.out.println("Decrypted data-------->"+Orginial_data);

}   
}

现在我收到此错误:-

Exception in thread "main" javax.crypto.IllegalBlockSizeException: Data must not be longer than 256 bytes
    at com.sun.crypto.provider.RSACipher.a(DashoA13*..)
    at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..)
    at javax.crypto.Cipher.doFinal(DashoA13*..)
    at com.Encrypt.Encrypt.decrypte(Encrypt.java:56)
    at com.Encrypt.CryptoHelper.main(CryptoHelper.java:17)

这个错误是在解密的时候出现的

byte[] cipherData = cipher.doFinal(encCardNo.getBytes());

public String decrypte (String encCardNo) 方法中。请解释我该如何解决这个问题。

【问题讨论】:

  • @Artjom B. 伙计,这是实际代码。通过字符串学生我得到了这个例外..:(
  • 好吧,Maarten 的回答是正确的。我在看加密函数,而不是解密函数。

标签: java encryption rsa keystore jks


【解决方案1】:

@Maarten Bodewes 答案是正确的,我们必须在解密前解码 ..
谢谢@Maarten Bodewes
这是返回正确输出的解密方法的代码。
`

public String decrypte (String encCardNo) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableEntryException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{
    FileInputStream is = new FileInputStream("C:/Users/admin/Desktop/keystore/ksjksformat.jks");    
    String keystpassw = "9801461740";
    String alias = "ksjksformat";       
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());                      
        ks.load(is,keystpassw.toCharArray() );      
        Key key = ks.getKey(alias, keystpassw.toCharArray());
        Certificate cert = ks.getCertificate(alias);
        PublicKey publicKey = cert.getPublicKey();
        new KeyPair(publicKey, (PrivateKey) (key));     
        KeyStore.ProtectionParameter protParam = new KeyStore.PasswordProtection(keystpassw.toCharArray());
        KeyStore.PrivateKeyEntry pkentry = (PrivateKeyEntry) ks.getEntry(alias, protParam);
        PrivateKey myPrivateKey =pkentry.getPrivateKey();
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, myPrivateKey); 
        byte[] decoded = Base64.decodeBase64(encCardNo);        
        byte[] cipherData = cipher.doFinal(decoded);
        return new String(cipherData);      
}`

【讨论】:

  • 将此作为(未经测试的)示例decrypte 的输入,只是为了显示一些编码提示。
【解决方案2】:

你需要在解密之前解码,而不是之后。

作为在发布您自己的答案时接受我的答案的一项特殊服务,对decrypte 进行了一点重写:

public String decrypte(final String encCardNo) throws IllegalBlockSizeException,
        BadPaddingException {
    // --- setup (should be stored differently)
    final char[] keystpassw = "9801461740".toCharArray();
    final String alias = "ksjksformat";

    // --- retrieve private key from store
    final PrivateKey key;
    try (final FileInputStream is = new FileInputStream(
            "C:/Users/admin/Desktop/keystore/ksjksformat.jks")) {
        final KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(is, keystpassw);
        key = (PrivateKey) ks.getKey(alias, keystpassw);
    } catch (final KeyStoreException | IOException | NoSuchAlgorithmException | UnrecoverableKeyException | CertificateException e) {
        throw new IllegalStateException("Could not load key from key store", e);
    }

    // --- initialize cipher
    final Cipher cipher;
    try {
        // should use OAEP instead
        cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, key);
    } catch (final NoSuchAlgorithmException | NoSuchPaddingException e) {
        throw new IllegalStateException(
                "RSA PKCS v1.5 should always be available", e);
    } catch (final InvalidKeyException e) {
        throw new IllegalStateException("Key is not an RSA private key", e);
    }

    // --- decode 
    final byte[] decoded;
    try {
        decoded = Base64.getDecoder().decode(encCardNo);
    } catch (final IllegalArgumentException e) {
        throw new IllegalArgumentException("Invalid encoded ciphertext", e);
    }

    // --- decrypt
    final byte[] cipherData = cipher.doFinal(decoded);
    final String cardNo = new String(cipherData, StandardCharsets.US_ASCII);

    // --- clean up
    try {
        key.destroy();
    } catch (final DestroyFailedException e) {
        // we tried, possibly log this
    }
    Arrays.fill(cipherData, (byte) 0);

    return cardNo;
}

【讨论】:

  • 嗨,如果我在解密之前对其进行解码,那么它将如何返回正确的数据。
  • 好吧,card.getBytes() 的反面是 new String(decryptedBytes),尽管您可能希望为两者指定一个字符编码,例如 StandardCharsets.UTF_8

  • 嗨,
    如果我在解密之前对其进行解码,那么它将如何返回正确的数据。
    这是我在解密之前尝试解码时的输出。然后我输出我得到的是 ;;;-----
    要加密和解密的数据 ->**学生**
    使用编码的加密数据 ->[B@c7e553
    使用编码的加密数据- >hr....(Base 64 编码数据)
    解密数据->[B@1050169.. 那不是学生
  • 能否请您多解释一下
    如何使用StandardCharsets.UTF_8进行代码编码
  • 您没有使用 String 构造函数,您只是打印出字节数组。你甚至搜索过 StandardCharsets 类吗?
猜你喜欢
  • 2022-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-24
  • 1970-01-01
  • 2022-11-22
相关资源
最近更新 更多