javax.crypto.BadPaddingException: Data must start with zero

Hello,

I saw that a lot of other developers have the same problem but I did not find my solution in posted messages.

I'm getting RSA encrypted data from an external device and I have to decrypt it with the private key.

Code I use to decode is the following:

private String decodeCryptedData(String szData){

String szDecodedData ="";

try{

Cipher decrypt = Cipher.getInstance("RSA");

//Cipher decrypt = Cipher.getInstance("RSA/ECB/PKCS1Padding");

decrypt.init(Cipher.DECRYPT_MODE, privateKeyRSA);

byte[] decodeData= decrypt.doFinal(szData.getBytes("ISO-8859-1"));

szDecodedData = new String(decodeData, "ISO-8859-1");

}catch(Exception ex){

log.error("Exception occured in function decodeCryptedData: " + ex);

return "";

}

return szDecodedData ;

}

When using this code I get the exception : javax.crypto.BadPaddingException: Data must start with zero

As you can see I tried with "RSA" an also "RSA/ECB/PKCS1Padding" but the result is always the same.

I'm now looking for a solution on internet for 8 hours but I cannot find it.

Does anyone of you has an idea?

Thanks in advance.

Alain.

null

[1241 byte] By [Philipinaa] at [2007-10-3 3:40:31]
# 1

byte[] decodeData= decrypt.doFinal(szKey.getBytes("ISO-8859-1"));

szDecodedData = new String(decodeData, "ISO-8859-1");

Are you really getting the data as a Java String from the external device? Unlikely. Did you really get it as a byte[] array and converted it to a String? Don't do this. Read the data as bytes, into a byte[] array, leave it that way, and pass it directly to decrypt.doFinal.

ejpa at 2007-7-14 21:36:06 > top of Java-index,Security,Cryptography...
# 2

Data I get from the external device is represented by an hexa string "4021614D28395C79" (this is a DES key encoded with the RSA public modulus and exponent)

I convert it in normal string "@!aM(9\y" and then try to decrypt it:

szData = "@!aM(9\y";

I tried both

byte[] decodeData= decrypt.doFinal(szData .getBytes("ISO-8859-1"));

and

byte[] decodeData= decrypt.doFinal(szData .getBytes());

the result should be the DES key I will use later...

But I still get the same exception in both cases.

Alain

Philipinaa at 2007-7-14 21:36:06 > top of Java-index,Security,Cryptography...
# 3
If it's hex you need to convert it straight to binary. Do not pass String, do not collect $200.You could try new BigInteger(String,16).toByteArray(). where the String is the data in hex
ejpa at 2007-7-14 21:36:06 > top of Java-index,Security,Cryptography...
# 4

> Data I get from the external device is represented by

> an hexa string "4021614D28395C79" (thi

> I convert it in normal string "@!aM(9\y" and then try

> to decrypt it:

>

> szData = "@!aM(9\y";

>

> I tried both

> byte[] decodeData= decrypt.doFinal(szData

> .getBytes("ISO-8859-1"));

> and

> yte[] decodeData= decrypt.doFinal(szData

> .getBytes());

> the result should be the DES key I will use later...

> But I still get the same exception in both cases.

>

> Alain

s is a DES key

> encoded with the RSA public modulus and exponent)

Looks a bit small for an RSA encrypted and hexed DES key. If you have a 1024 bit RSA key then your encyption result will be approx 1024/8 = 128 bytes which converted to Hex would be 256 hex characters. You have just 16 hex chars so it looks to me like it is just the DES key.

In your previous thread I showed you how to convert Hex to byte[] using Jakarta Commons Codec

sabre150a at 2007-7-14 21:36:06 > top of Java-index,Security,Cryptography...
# 5

This time I tried

Cipher decrypt = Cipher.getInstance("RSA");

decrypt.init(Cipher.DECRYPT_MODE, privateKeyRSA);

byte[] decodedData = decrypt.doFinal(new BigInteger(szData,16).toByteArray());

where szData = "4021614D28395C79"

But I still get the excpetion "javax.crypto.BadPaddingException: Data must start with zero"

RSA decryption seems not easy to use for me :(

Any other idea?

Thanks already for previous replies.

Alain

Philipinaa at 2007-7-14 21:36:06 > top of Java-index,Security,Cryptography...
# 6

> But I still get the excpetion

> "javax.crypto.BadPaddingException: Data must start

> with zero"

>

> RSA decryption seems not easy to use for me :(

>

> Any other idea?

>

Did you read my reply? I don't think your value IS an RSA encrypted DES key.

sabre150a at 2007-7-14 21:36:06 > top of Java-index,Security,Cryptography...
# 7

No, I posted the previous reply before reading your post.

I now understand that I don't decrypt de full data.

I first extract DES key and try to decrypt it but If I understand correcly I have to decrypt and AFTER extract the DES key.

I going to do some tests and will come back to you...

Thank you :)

Alain

Philipinaa at 2007-7-14 21:36:06 > top of Java-index,Security,Cryptography...
# 8

OK, now I'm trying to decode the full string received before extracting DES key:

When I ask java to generate public/private key of 512 bits I get:

RSA public Modulus:

9ee892fecc002ace0192

548559d24e2916a78979

3f92c22e11e530821159

d3e6fe3654b09d47f505

3df23bad260642c38017

d2d9f935aca1d520a2f3

0497d23d

and

RSA public exponent:

10001

Public modulus and exposant is sent to the external device.

The external device returns me the DES key encoded with RSA:

Encrypted DES:

004F95242EAEB003E45A

6251F4BBE7F9CA00A3AC

60250DE30EEC3F084A98

E431239DC5581BB7CB21

0A61769AB7C6AF54C1FB

70B4C7136584716C88B3

7015FF0D

OK, the length is similar to RAS modulus.

This DES encrypted key is stored in szData and I use the following code to decrypt:

Cipher decrypt = Cipher.getInstance("RSA");

decrypt.init(Cipher.DECRYPT_MODE, privateKeyRSA);

szData = converter.hexStringToAsciiString(szData);

byte[] decodedData = decrypt.doFinal(szData.getBytes("ISO-8859-1"));

-

the function converter.hexStringToAsciiString( HexString) is converting an Hex string in ascii string. This is not the first time I use it and it works well.

This time, szData has a correct length of 64 bytes (512 bits) but when I execute the line byte[] decodedData = decrypt.doFinal(szData.getBytes("ISO-8859-1"));

I still get the exception "javax.crypto.BadPaddingException: Data must start with zero".

Alain

Philipinaa at 2007-7-14 21:36:06 > top of Java-index,Security,Cryptography...
# 9

> This DES encrypted key is stored in szData and I use

> the following code to decrypt:

What is the data type of szData because ...

>

> Cipher decrypt =

> Cipher.getInstance("RSA");

> decrypt.init(Cipher.DECRYPT_MODE,

> privateKeyRSA);

> szData =

> converter.hexStringToAsciiString(szData);

> byte[] decodedData =

> decrypt.doFinal(szData.getBytes("ISO-8859-1"));

... it does not make sense to do

szData.getBytes("ISO-8859-1")

I don't understand why you want

converter.hexStringToAsciiString(szData);

becuaue you need a byte[] array not a String. You really need

converter.hexStringToByteArray(szData);

method.

P.S. You would do well to forget about String.getBytes("encoding") when you are considering encryption. The only way you should need it is if you want to encrypt a String and then only to convert the String to bytes so the bytes can be encrypted.

sabre150a at 2007-7-14 21:36:06 > top of Java-index,Security,Cryptography...
# 10

Thank you for your patience.

Data in szData is the string "004F95242EAEB003E45A6251F4BBE7F9CA00A3AC60250DE30EEC3F084A98E431239DC5581BB7CB210A61769AB7C6AF54C1FB70B4C7136584716C88B37015FF0D"

This is the data I get from the external device (String representing hexadecimal value).

I cannot convert this one because, this string has 128 byte and not 64, this is why I convert this hexadecimal string in acsii string. Then after convertion szData has the correct length (64 bytes)

Isn't it correct?

Do you think that my function converter.hexStringToAsciiString is not working well?

Alain

Philipinaa at 2007-7-14 21:36:06 > top of Java-index,Security,Cryptography...
# 11

Some more info about last tests:

If I use Cipher decrypt = Cipher.getInstance("RSA/ECB/NoPadding"); instead of Cipher decrypt = Cipher.getInstance("RSA");

I do not get an exception and data can de decrypted but unfortunately result of decryption is not correct.

I got a confirmation from the manufacturer that ECB or CBC are not used.

Then I tried Cipher decrypt = Cipher.getInstance("RSA/NONE/NoPadding");

but then I get the exception "java.security.NoSuchAlgorithmException: Invalid transformation format:RSA/NONE/NoPadding"

I don't understand because I think mode NONE should exist.

Thanks in advance for you help.

Alain

Philipinaa at 2007-7-14 21:36:06 > top of Java-index,Security,Cryptography...
# 12

>

> Data in szData is the string

> "004F95242EAEB003E45A6251F4BBE7F9CA00A3AC60250DE30EEC3

> F084A98E431239DC5581BB7CB210A61769AB7C6AF54C1FB70B4C71

> 36584716C88B37015FF0D"

>

> This is the data I get from the external device

> (String representing hexadecimal value).

But not long enough for RSA 1024 bit encryption of anything. I would expect about 1024/8 = 128 bytes or 256 hex digits.

>

> I cannot convert this one because, this string has

> 128 byte and not 64, this is why I convert this

> hexadecimal string in acsii string. Then after

> convertion szData has the correct length (64 bytes)

I really don't understand you.

>

> Isn't it correct?

> Do you think that my function

> converter.hexStringToAsciiString is not working

> well?

Use Jakarta Commons Codec. It is known to work.

sabre150a at 2007-7-14 21:36:06 > top of Java-index,Security,Cryptography...
# 13

> If I use Cipher decrypt =

> Cipher.getInstance("RSA/ECB/NoPadding"); instead of

> Cipher decrypt = Cipher.getInstance("RSA");

> I do not get an exception and data can de decrypted

> but unfortunately result of decryption is not

> correct.

> I got a confirmation from the manufacturer that ECB

> or CBC are not used.

> Then I tried Cipher decrypt =

> Cipher.getInstance("RSA/NONE/NoPadding");

>

> but then I get the exception

> "java.security.NoSuchAlgorithmException: Invalid

> transformation format:RSA/NONE/NoPadding"

>

> I don't understand because I think mode NONE should

> exist.

>

> Thanks in advance for you help.

>

> Alain

I'm totally lost. What are you trying to do? This fragmented approach to problem solving will not work.

A simple example of how to encrypt and decrypt a DES key using RSA -

import java.util.*;

import java.security.PublicKey;

import java.security.KeyPair;

import java.security.KeyPairGenerator;

import javax.crypto.Cipher;

import org.apache.commons.codec.binary.*;

public class RSAEncryptDESKey

{

public static void main(String[] args) throws Exception

{

Hex encoder = new Hex();

// Generate the RSA key pari

KeyPairGenerator rsaKeyPairGenerator = KeyPairGenerator.getInstance("RSA");

rsaKeyPairGenerator.initialize(1024);

KeyPair rseKeyPair = rsaKeyPairGenerator.generateKeyPair();

PublicKey publicKey = rseKeyPair.getPublic();

// Generate the RSA Cipher

Cipher cipher = Cipher.getInstance("RSA");

cipher.init(Cipher.ENCRYPT_MODE, publicKey);

// Generate a 'not very random' DES key

byte[] desKey = new byte[8];

Random random = new Random(31415926);

random.nextBytes(desKey);

String hexEncodedDeskey = new String(encoder.encode(desKey));

System.out.println("Random DES key : " + hexEncodedDeskey);

// Encrypt the key

byte[] encryptedDesKey = cipher.doFinal(desKey);

// Hex encode

String hexEncodedEncryptedDesKey = new String(encoder.encode(encryptedDesKey));

System.out.println("RSA Encrypted DES key : " + hexEncodedEncryptedDesKey);

// Now make sure we get back the DES key

cipher.init(Cipher.DECRYPT_MODE, rseKeyPair.getPrivate());

byte[] decryptedDesKey = cipher.doFinal(encryptedDesKey);

String hexEncodedDecryptedDeskey = new String(encoder.encode(decryptedDesKey));

System.out.println("Recovered DES key : " + hexEncodedDecryptedDeskey);

}

}

You can test things by providing your own RSA key.

sabre150a at 2007-7-14 21:36:06 > top of Java-index,Security,Cryptography...
# 14

>But not long enough for RSA 1024 bit encryption of anything. I would expect about 1024/8 = 128 bytes or 256 hex digits.

This is normal I have a key of 512 bits

>A simple example of how to encrypt and decrypt a DES key using RSA -

I'm now using your code. I can encrypt data and than decrypt it after. This is working well.

But a.s.a. I try to decrypt data encrypted by the external device (where I do not control the encryption) I'm still getting the exception : javax.crypto.BadPaddingException: Data must start with zero

This exception is a Padding error, this is why I tried to change string in the getInstance call (Cipher.getInstance("RSA/ECB/NoPadding");)

If I use "RSA/ECB/NoPadding") I do not get the exception but decrypted data is not correct.

Now I do really believe that the problem comes from this configuration string. As I said, the manufacturer said that ECB or CBC are not used this is why I tried the mode NONE --> Cipher.getInstance("RSA/NONE/NoPadding");)

But then I have the exception "java.security.NoSuchAlgorithmException: Invalid transformation format:RSA/NONE/NoPadding"

I don't understand because I think that mode NONE should exist --> http://java.sun.com/j2se/1.5.0/docs/guide/security/jce/JCERefGuide.html

Alain

Philipinaa at 2007-7-14 21:36:07 > top of Java-index,Security,Cryptography...
# 15
Without access to test data I can't help you. I would need1) A test RSA private and public key2) A test DES key to be encrypted.3) The test DES key encrypted by the manufacturer using the test keys from 1).Without this I would be guessing.
sabre150a at 2007-7-21 10:15:34 > top of Java-index,Security,Cryptography...
# 16

Hello,

Here is an example

- Public key:

Sun RSA public key, 512 bits

modulus: 8523905342310592998908027341720590114772004180240747046800793247237399654072674677880885448874374746493810911163336132629781184265696821125710937425806153

public exponent: 65537

- Private key:

Sun RSA private CRT key, 512 bits

modulus: 8523905342310592998908027341720590114772004180240747046800793247237399654072674677880885448874374746493810911163336132629781184265696821125710937425806153

public exponent: 65537

private exponent: 4142750399976761343992225565535258500323754171674447639267877176419513462342139782130539539832501585023829390105731947172765023990864870017249342337278913

prime p: 114560549547768419266496571631038916785917390979070895492845840794695340967093

prime q: 74405241385092799618598480929503686982382077258054055582884417138075917620421

prime exponent p: 97283034987594119923681793505686998731810436244537170558056511249327552540421

prime exponent q: 68747958967192721487169269484492214497629801582071277015517692225445917811113

crt coefficient: 2917988844066098063901651380439145960335711729317656226215832146371785355963

In this case the data received from the external device (DES key encrypted with RSA) is :

33DF9EE0895578C0B9CAEC91FCA5CB0953918763C693A4D5AAA6F76AD26FEE6F74693D673E00A9042E4DCD81BF47CFA96DF270B808573CE4DEC253B5081EB1EA

To find the DES key I have to decrypt this data. In the decrypted string the DES key will be present from byte 17 to byte 24

I know that DES key generater by the external device must be 739DAE26929B1C79 because I can see it on the device display with a special firmware

If I decrypt the string received I get :47F66CF7FFADE4A3E4533B9F834C5B67015E69393A70D029B47422FECF661A44E31997B09559484CF91F45CF4179D73B248DE940500D28A4D4A156AAADD3C275

and if I take bytes(17-24), I have : 015E69393A70D029 and not 739DAE26929B1C79

Hope that I have provided all needed information.

I think I really have to buy a book about encryption/decryption and read it.

Thanks in advance.

Philipinaa at 2007-7-21 10:15:34 > top of Java-index,Security,Cryptography...
# 17

Hello,

I solved the problem.

It was a problem in the command where I was sending the public key.

The external device was waiting for a string in hexadecimal representation. The modulus was converted correctly but not the exponent. I changed the exponent from 65537 to 10001

Finally this is working well is I use Cipher.getInstance("RSA/ECB/NoPadding");

Thank a lot for your help and all explanations.

Is there any book you recommend to learn more about encryption/decryption in java?

Thanks again, I send you Duke Dollars.

Alain

Philipinaa at 2007-7-21 10:15:34 > top of Java-index,Security,Cryptography...
# 18

If you want to know everything I suggest Bruce Schneier's Applied Cryptography, Wiley 1996.

If someone knows a first-rate Java-oriented book please follow up, I'm not aware of one.

The Knudsen book (O'Reilly 1998) is seriously out of date. There are also books by Weiss (Morgan Kaufmann (February 27, 2004), not well reviewed at Amazon) and Hook (rox (August 19, 2005), mixed reviews at Amazon).

I haven't read either of them.

ejpa at 2007-7-21 10:15:34 > top of Java-index,Security,Cryptography...
# 19

> I solved the problem.

:-) Very well done.

> It was a problem in the command where I was sending

> the public key.

> The external device was waiting for a string in

> hexadecimal representation. The modulus was converted

> correctly but not the exponent. I changed the

> exponent from 65537 to 10001

Almost all cross platform/language/hardware cryptographic interoperability problems I see are due to poor specification about the secondary algorithms used or the format of the presented data or keys. You did very well to spot this.

>

> Finally this is working well is I use

> Cipher.getInstance("RSA/ECB/NoPadding");

>

> Thank a lot for your help and all explanations.

>

> Is there any book you recommend to learn more about

> encryption/decryption in java?

As suggest by ejp, Bruce Schneier's Applied Cryptography but also

Practical Cryptography by Ferguson and Schneier published by Wiley ISBN 0-471-22357-3 . I like this second book because, being an engineer, it tells me how to build things.

Both these are general to cryptography and the only Java cryptography book I have is "Java Cryptography" by Knudsen which, as ejp says, is seriously out of date though it does give one the basics. If you Google for "JCE Tutorial" then you will find a wealth of online JCE information.

Online there is another general cryptography book - "Handbook Of Applied Cryptograpy" which can be downloaded from http://www.cacr.math.uwaterloo.ca/hac/ .

>

> Thanks again, I send you Duke Dollars.

>

Thank you.

sabre150a at 2007-7-21 10:15:34 > top of Java-index,Security,Cryptography...
# 20

I just experienced the same exception. Anyway, the exception was quite misleading. Checking my code I noticed that I used the wrong key to decrypt an already encrypted text.

As you should know, RSA uses an asimmetric algorithm. That means you should use one key to encrypt (usually the public one, for cipher purposes) and the other one to decrypt (usually the private one, for cipher purposes). Check what key was used to encrypt (just use the other key to decrypt, on your next test).

Good luck.

lvognaa at 2007-7-21 10:15:34 > top of Java-index,Security,Cryptography...
# 21
hehe a late reply. Well I am glad you solved it already.
lvognaa at 2007-7-21 10:15:34 > top of Java-index,Security,Cryptography...
# 22

Hello, I had same problem like, you. My problem was that I use DES demo and rewrite it to RSA demo. Problem was that I forgot that RSA use one key(Private f.e) for encryption and another (public f.e.) for decryption. When I change it, my code works fine.

My solution is, try to use different key for encryption and decryption.

public class CipherRSATest {

public static void main(String[] args) throws Exception {

KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");

KeyPair keyPair = keyPairGen.genKeyPair();

Cipher rsaCipher;

rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

// Initialize the cipher for encryption

rsaCipher.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate());

// Our cleartext

byte[] cleartext = "This is just an example".getBytes();

byte[] ciphertext = rsaCipher.doFinal(cleartext);

System.out.println("sifra " + new String(ciphertext));

rsaCipher.init(Cipher.DECRYPT_MODE, keyPair.getPublic());

// Decrypt the ciphertext

byte[] cleartext1 = rsaCipher.doFinal(ciphertext);

boolean isok = Arrays.equals(cleartext,cleartext1);

System.out.println("..." + isok);

System.out.println(new String(cleartext1));

}

}

Topona at 2007-7-21 10:15:34 > top of Java-index,Security,Cryptography...