I am encrypting some bytes of data On a java smart card using a public key i generated on a desktop app, but when i try to decrypt the data on my desktop i get the `BadPaddingException : Data must start with zero`, I read that this might be caused by the use of a false private key to decrypt the data, please bare with me as i explain the steps i went through, if anyone has a better solution of course i'm all ears.
1. First of all i generated a public/private key pair on a desktop app and loaded them on the smart card using the following code ( being generated in BigInteger type, I converted them to hexadecimal, and from hexa decimal to a byte array ) :
void keyGen(String ID)throws Exception{
// where ID is the name of the user
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(512);
KeyPair kp = kpg.genKeyPair();
this.pubKey = (RSAPublicKey) kp.getPublic();
this.privKey = (RSAPrivateKey) kp.getPrivate();
KeyFactory fact = KeyFactory.getInstance("RSA");
this.pub = fact.getKeySpec(kp.getPublic(), RSAPublicKeySpec.class);
this.priv = fact.getKeySpec(kp.getPrivate(), RSAPrivateKeySpec.class);
saveToFile(ID+".pub", pub.getModulus(), pub.getPublicExponent());
saveToFile(ID+".priv", priv.getModulus(), priv.getPrivateExponent());
}
here is the savetofile function :
public void saveToFile(String fileName, BigInteger mod, BigInteger exp) throws IOException {
ObjectOutputStream oout = new ObjectOutputStream(
new BufferedOutputStream(new FileOutputStream(fileName)));
try {
oout.writeObject(mod);
oout.writeObject(exp);
} catch (Exception e) {
throw new IOException();
} finally {
oout.close();
}
}
this is the line used to store the public key on the smart card :
Main.sRmi.setPub(Crypto.hexStringToByteArray(Main.crypto.getPubMod().toString(16)),
toByteArray("0"+Main.crypto.getPubexp().toString(16)));
( The zero is added to the string because we cannot convert a string of odd hexadecimals into bytes )
2. Then I try to encrypt the data using that public key inside the card, and this is the function i'm using :
private Cipher cipherRSA = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false);
private byte[] cipherText = new byte[64];
public byte[] encrypt(byte[] clearText){
cipherRSA.init(rsa_PublicKey, Cipher.MODE_ENCRYPT);
cipherRSA.doFinal(clearText, (short)0, (short)clearText.length,cipherText, (short)0 );
return cipherText;
}
3. Then I try to get this encrypted value on another desktop application, and decrypt it using the private key i'm reading from the file :
This is how I read the private key from the file :
public void init (String ID ) throws FileNotFoundException, IOException, Exception{
Object o[] = openFile(ID+".pub");
setPubMod((BigInteger) o[0]);
setPubexp((BigInteger) o[1]);
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(this.pubMod, this.pubexp);
KeyFactory fact = KeyFactory.getInstance("RSA");
pubKey = (RSAPublicKey) fact.generatePublic(keySpec);
o = openFile(ID+".priv");
setPrivMod((BigInteger) o[0]);
setPrivexp((BigInteger) o[1]);
RSAPrivateKeySpec keySpec1 = new RSAPrivateKeySpec(this.privMod, this.privexp);
fact = KeyFactory.getInstance("RSA");
privKey = (RSAPrivateKey) fact.generatePrivate(keySpec1);
cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
}
After getting the private key in the BigInteger Variable, I decrypt using the following method :
public byte[] rsaDecrypt(byte[] data) throws Exception, BadPaddingException {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privKey);
byte[] clearData = cipher.doFinal(data);
return clearData;
}
To sum it all up, I create a key pair in BigInteger Format, I save the BigInteger Variable into a Serialized array of two BigIntegers to be used by the other desktop App, then I convert them into Hexa String, then into an array of bytes which i put inside the smart card.
Can anyone please tell me what's wrong with this procedure ? is it too much ? is there a better way to do so ? Thank you
If you need anymore Information please let me know.
**EDIT : **
I think i know where the problem is, it's with the key stored inside the smart card, converting it the way I did obviously is not working, seing how i read it from the card and printed it out and got
a completely different result, so the question is now, how do i export successfully a public key created on java.crypto ( in BigInteger) to the Smart card where public keys are stored in Bytes ?
I found this :
Sets the public exponent value of the key. The plaintext data format is big-endian and right-aligned (the least significant bit is the least significant bit of last byte). Input exponent data is copied into the internal representation.
so how can i convert a big integer to this big-endian byte format ? thank you