获取javax.crypto.IllegalBlockSizeException:加密加密数据时出现异常

时间:2015-05-04 16:45:49

标签: java

当我尝试使用RSA加密和解密数据时,它的工作正常。
这里c是用户定义的类,它有rsaEncrypt和rsaDecrypt方法。

byte b[]=c.rsaEncrypt("voterpublickey.key",(""+randomnumber).getBytes(),"public")<br>
new String(c.rsaDecrypt("voterprivatekey.key",b,"private"));


但在这里我需要使用RSA进行E(priv(LA),E(Pub(VF),vnumber))加密。 但它在加密和解密时都会引发错误。

加密时

b=c.rsaEncrypt("vfpublickey.key",(vnumber+"").getBytes(),"public");
b=c.rsaEncrypt("laprivatekey.key",b,"private");


stacktrace:
    javax.crypto.IllegalBlockSizeException: Data must not be longer than 245 bytes
        at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:344)
        at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
        at javax.crypto.Cipher.doFinal(Cipher.java:2165)
        at cli.rsaEncrypt(cli.java:79)
        at LaSer.main(LaSer.java:108)
解密时

byte b[]=c.rsaDecrypt("lapublickey.key",b,"public");
new String(c.rsaDecrypt("vfprivatekey.key",b,"private"));


stacktrace:
    javax.crypto.BadPaddingException: Decryption error
        at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:380)
        at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:291)
        at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:363)
        at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
        at javax.crypto.Cipher.doFinal(Cipher.java:2165)
        at cli.rsaDecrypt(cli.java:99)
        at ConnectionWithLaser.run(VfSer.java:371)

我做错了什么。加密加密数据是对的吗?

有没有办法处理这种情况?

更新

PrivateKey readKeyFromFileDecrypt(String keyFileName) throws IOException {
  InputStream in =
    cli.class.getResourceAsStream(keyFileName);
  ObjectInputStream oin =
    new ObjectInputStream(new BufferedInputStream(in));
  try {
    BigInteger m = (BigInteger) oin.readObject();
    BigInteger e = (BigInteger) oin.readObject();
    RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(m, e);
    KeyFactory fact = KeyFactory.getInstance("RSA");
    PrivateKey priKey = fact.generatePrivate(keySpec);
    return priKey;
  } catch (Exception e) {
    throw new RuntimeException("Spurious serialisation error", e);
  } finally {
    oin.close();
  }
}
//similar function readKeyFromFileEncrypt
public byte[] rsaEncrypt(String keyFileName,byte[] data,String key)throws Exception {
if(key.equals("public")){
  PublicKey pubKey = readKeyFromFileEncrypt(keyFileName);
  Cipher cipher = Cipher.getInstance("RSA");
  cipher.init(Cipher.ENCRYPT_MODE, pubKey);
}
else if(key.equals("private"))
{
  PrivateKey priKey = readKeyFromFileDecrypt(keyFileName);
  Cipher cipher = Cipher.getInstance("RSA");
  cipher.init(Cipher.ENCRYPT_MODE, priKey);
}
  byte[] cipherData = cipher.doFinal(data);
  return cipherData;
}
public byte[] rsaDecrypt(String keyFileName,byte[] data,String key)throws Exception{
if(key.equals("public")){
  PublicKey pubKey = readKeyFromFileEncrypt(keyFileName);
  Cipher cipher = Cipher.getInstance("RSA");
  cipher.init(Cipher.DECRYPT_MODE, pubKey);
}
else if(key.equals("private"))
{
  PrivateKey priKey = readKeyFromFileDecrypt(keyFileName);
  Cipher cipher = Cipher.getInstance("RSA");
  cipher.init(Cipher.DECRYPT_MODE, priKey);

}
  byte[] originalData = cipher.doFinal(data);
  return originalData;
}

最后生成公钥和私钥

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair kp = kpg.genKeyPair();
Key publicKey = kp.getPublic();
Key privateKey = kp.getPrivate();

1 个答案:

答案 0 :(得分:0)

基本上你的代码很好。

我使用以下代码复制了您的问题:

package foo;

import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;

public class FooTest
{

    public static void main( String[] args ) throws Exception
    {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance( "RSA" );
        int keysize = 2048;
        kpg.initialize( keysize );
        KeyPair keys = kpg.genKeyPair();

        SecureRandom rng = new SecureRandom();

        byte[] data = new byte[keysize / 8 - 11];
        rng.nextBytes( data );

        // "encryption"
        byte[] cipherText = encrypt( data, keys.getPublic() );
        byte[] decrypted = decrypt( cipherText, keys.getPrivate() );

        if ( !Arrays.equals( data, decrypted ) )
        {
            throw new IllegalStateException( "decrypted was not equal to message" );
        }

        // "signature"
        cipherText = encrypt( data, keys.getPrivate() );
        decrypted = decrypt( cipherText, keys.getPublic() );

        if ( !Arrays.equals( data, decrypted ) )
        {
            throw new IllegalStateException( "decrypted was not equal to message" );
        }

        data = new byte[keysize / 8 - 10];
        rng.nextBytes( data );
        try
        {
            encrypt( data, keys.getPublic() );
        }
        catch ( IllegalBlockSizeException e )
        {
            System.err.println( "data size of " + data.length + " may not exceed " + (keysize / 8 - 11) );
        }
    }

    static byte[] encrypt( byte[] data, Key key ) throws Exception
    {
        Cipher cipher = Cipher.getInstance( "RSA" );
        cipher.init( Cipher.ENCRYPT_MODE, key );

        return cipher.doFinal( data );
    }

    static byte[] decrypt( byte[] data, Key key ) throws Exception
    {
        Cipher cipher = Cipher.getInstance( "RSA" );
        cipher.init( Cipher.DECRYPT_MODE, key );

        return cipher.doFinal( data );
    }
}

RFC 3447描述了为什么限制比实际密钥大小11个字节。