views:

338

answers:

2

Hello everyone.

I try to implement an RSA algorithm in a Java program. I am facing the "BadPaddingException : data must start with zero". Here are the methods used to encrypt and decrypt my data :

public byte[] encrypt(byte[] input)  throws Exception
{
    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");//
    cipher.init(Cipher.ENCRYPT_MODE, this.publicKey);
    return cipher.doFinal(input);
}

public byte[] decrypt(byte[] input)  throws Exception
{   
    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");///
    cipher.init(Cipher.DECRYPT_MODE, this.privateKey);
    return cipher.doFinal(input);
}

privateKey and publicKey attributes are read from files this way :

public PrivateKey readPrivKeyFromFile(String keyFileName) throws IOException {
    PrivateKey key = null;
    try {
        FileInputStream fin = new FileInputStream(keyFileName);
        ObjectInputStream ois = new ObjectInputStream(fin);
        BigInteger m = (BigInteger) ois.readObject();
        BigInteger e = (BigInteger) ois.readObject();
        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(m, e);
        KeyFactory fact = KeyFactory.getInstance("RSA");
        key = fact.generatePrivate(keySpec);
        ois.close();
    }
    catch (Exception e) {
       e.printStackTrace();
    }
    return key;
}

Private key and Public key are created this way :

public void Initialize() throws Exception
{
    KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA");
    keygen.initialize(2048);
    keyPair = keygen.generateKeyPair();
    KeyFactory fact = KeyFactory.getInstance("RSA");
    RSAPublicKeySpec pub = fact.getKeySpec(keyPair.getPublic(), RSAPublicKeySpec.class);
    RSAPrivateKeySpec priv = fact.getKeySpec(keyPair.getPrivate(), RSAPrivateKeySpec.class);

    saveToFile("public.key", pub.getModulus(), pub.getPublicExponent());
    saveToFile("private.key", priv.getModulus(), priv.getPrivateExponent());
}

and then saved in files :

public void saveToFile(String fileName, BigInteger mod, BigInteger exp) throws IOException {
    FileOutputStream f = new FileOutputStream(fileName);
    ObjectOutputStream oos = new ObjectOutputStream(f);
    oos.writeObject(mod);
    oos.writeObject(exp);
    oos.close();
}

I can't figured out how the problem come from. Any help would be appreciate !

Thanks in advance.

A: 

So far, I've tracked this down to CipherSpi.engineDoFinal(). The explanation provided for BadPaddingException is

[Thrown when the] cipher is in decryption mode, and (un)padding has been requested, but the decrypted data is not bounded by the appropriate padding bytes

More specific behavior seems to be Spi-dependent. Do you know what Spi you're using? Just the default?

EDIT: Unfortunately, I'm having a hard time tracking down what the default Spi is. It looks like it's chosen in Cipher.java's chooseFirstProvider() method, lines 644 to 721 here. If you have a debugger handy, you might want to find out what Spi you have, then check the documentation for it... but I still think it's more likely that something's going on with the input, not the logic (I asked about that earlier, in a comment).

Lord Torgamus
Yes the default one
Robin Monjo
Thanks for you help. Indeed I think the logic is good maybe a problem in the input. As I said in an other comment : "The algorithm works when I use a "RSA/ECB/NoPadding". The problem is that the encrypted data are gzip archive, and once decrypted with the "RSA/ECB/NoPadding" cipher, data are not recognized as gzip archive. I supposed it could be due to this "NoPadding"... " Thanks again for your help
Robin Monjo
The problem usually signals that a incorrect private key is being used, or that the data is corrupted.
GregS
A: 

In principle the code looks OK -- I would put some logging in to make sure the key you're generating is genuinely the one that is then read from the file (you're not doing something silly like generating data with a new key, then trying to read it with an old one, for example?)

Neil Coffey
Haha no don't worry I take care of that ! The algorithm works when I use a "RSA/ECB/NoPadding". The problem is that the encrypted data are gzip archive, and once decrypted with the "RSA/ECB/NoPadding" cipher, data are not recognized as gzip archive. I supposed it could be due to this "NoPadding"...
Robin Monjo
You generally need the padding. One thing: if you just specify "RSA", you'll get padding by default. N.B. RSA is only suitable for encrypting small bits of data (you can encrypt a piece of data approximately the size of the key). If you're encrypting an archive, you'll probably need to consider using RSA to encrypt an AES key (or key for other scheme allowing arbitrary data size), then storing the actual gzip data encrypted using that key.
Neil Coffey
Yes I know but file that I encrypt using RSA are really small archive. I tried using just "RSA" in option for the cipher but still the bad padding exception... I really don't understand where that problem could come from. I may consider not to archive the data before encrypting and use a "NoPadding" option.
Robin Monjo
If possible you may want to try posting the full code, including the bit that's dealing with the archiving. As I say, I don't think there's anything wrong with the actual encryption code.
Neil Coffey
No it's okay I wont use archiving anymore. Thanks for everything !
Robin Monjo