Encrypt with the RSAPublic key contained in a byte[]
Hello, i need a way to put the RSAPublicKey i receive from server(byte[128]) into a correct object to invoke to the .init method of Cipher properly, the code is:
private doEncrypt (byte[] toEncrypt,byte[] key){
Cipher rsa = Cipher.getInstance("RSA/ECB/nopadding");
rsa.init(Cipher.ENCRYPT_MODE, key);/*can`t use it because parameters must be
(int opmode, Key key) and i have (int opmode, byte[] key)*/
byte[] encripted = rsa.doFinal(toEncrypt);
}
i think it cant be very difficult but im getting crazy :S, thanks in advance :)
[817 byte] By [
jbeata] at [2007-11-26 23:52:55]

# 1
128 bytes does not seem enough. That is 1024 bits but I suspect that that is just the modulus. What about the exponent?
# 2
Thanks for the quick answer, i really dont know very much about criptographic concepts ( i mean modulus and exponent)
not enough? the server only send 128 i know for sure im looking at the source code of it and transform the modulus of the public key in a byte array and then make some xor operations, this is the code:
private byte[] scrambleModulus(BigInteger modulus)
{
byte[] scrambledMod = modulus.toByteArray();
if (scrambledMod.length == 0x81 && scrambledMod[0] == 0x00)
{
byte[] temp = new byte[0x80];
System.arraycopy(scrambledMod, 1, temp, 0, 0x80);
scrambledMod = temp;
}
// step 1 : 0x4d-0x50 <-> 0x00-0x04
for (int i = 0; i < 4; i++)
{
byte temp = scrambledMod[0x00 + i];
scrambledMod[0x00 + i] = scrambledMod[0x4d + i];
scrambledMod[0x4d + i] = temp;
}
// step 2 : xor first 0x40 bytes with last 0x40 bytes
for (int i = 0; i < 0x40; i++)
{
scrambledMod[i] = (byte) (scrambledMod[i] ^ scrambledMod[0x40 + i]);
}
// step 3 : xor bytes 0x0d-0x10 with bytes 0x34-0x38
for (int i = 0; i < 4; i++)
{
scrambledMod[0x0d + i] = (byte) (scrambledMod[0x0d + i] ^ scrambledMod[0x34 + i]);
}
// step 4 : xor last 0x40 bytes with first 0x40 bytes
for (int i = 0; i < 0x40; i++)
{
scrambledMod[0x40 + i] = (byte) (scrambledMod[0x40 + i] ^ scrambledMod[i]);
}
_log.fine("Modulus was scrambled");
return scrambledMod;
}
and then, it sends to me
any idea of how to reverse this process? :)
jbeata at 2007-7-11 15:33:16 >

# 3
The code for getting the RSA key in the RSAPublicKey format from a byte[] is the following:
byte _key[];
RSAPublicKey rsaKey;
KeyFactory kfac = KeyFactory.getInstance("RSA");
BigInteger modulus = new BigInteger(_key);
RSAPublicKeySpec kspec1 = new RSAPublicKeySpec(modulus, RSAKeyGenParameterSpec.F4);
rsaKey = (RSAPublicKey)kfac.generatePublic(kspec1);
The RSAPublicKey is scrambled with the code from your previous post! I tried reversing the steps and it seem to unscramble correctly but when i try to encrypt i get an exception:
javax.crypto.BadPaddingException: Message is larger than modulus
at sun.security.rsa.RSACore.parseMsg(RSACore.java:165)
at sun.security.rsa.RSACore.crypt(RSACore.java:95)
at sun.security.rsa.RSACore.rsa(RSACore.java:74)
at com.sun.crypto.provider.RSACipher.a(DashoA13*..)
at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at walker.RequestAuth.<init>(RequestAuth.java:24)
at walker.LoginThread.run(LoginThread.java:52)
The message before encryption goes thru a padding function so the size it's always a multiple of 8. In this case the message size is 16 and the RSA modulus read from a network stream is 128 bytes.
Code used to encrypt the data[] is:
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/nopadding");
rsaCipher.init(Cipher.ENCRYPT_MODE, _key);
data = rsaCipher.doFinal(data);
Any help would be appreciated!
Message was edited by:
pSal
pSala at 2007-7-11 15:33:16 >

# 4
I found what is the problem that generate the exception. But it generates another problem!
I read 128 bytes from the stream which represents the modulus of the RSAPublicKey, i pass it thru the unscrambler and then i make the public key! When i use System.out.println( _key.getModulus().signum())
i get sometimes a negative BigInteger and when encrypting i get the exception from previous post!
Using new BigInteger(byte array).abs()
i don't get the exception anymore but it alters the key and thus making it unuseable with it's pair!
pSala at 2007-7-11 15:33:16 >

# 5
I figured it out! When the server scrambles the key if it has 129 length and first byte is 0 then it strips the first byte and scrambles the next 128 bytes! So if u use only the 128 bytes sometimes you get a negative modulus, fix for this is to add a 0x00 before the rest!
This is the correct unscrambler code:
public class UnscrambledKeyPair {
public RSAPublicKey rsaKey;
public byte[] unscrambledModulus;
public UnscrambledKeyPair(RSAPublicKey rsa) {
this.rsaKey=rsa;
unscrambledModulus=unscrambleModulus(rsa.getModulus().toByteArray());
}
public static byte[] unscrambleModulus(byte[] unscrambledMod){
for (int i = 0; i < 0x40; i++){
unscrambledMod[0x40 + i] = (byte) (unscrambledMod[0x40 + i] ^ unscrambledMod[i]);
}
for (int i = 0; i < 4; i++){
unscrambledMod[0x0d + i] = (byte) (unscrambledMod[0x0d + i] ^ unscrambledMod[0x34 + i]);
}
for (int i = 0; i < 0x40; i++){
unscrambledMod[i] = (byte) (unscrambledMod[i] ^ unscrambledMod[0x40 + i]);
}
for (int i = 0; i < 4; i++){
byte temp = unscrambledMod[0x00 + i];
unscrambledMod[0x00 + i] = unscrambledMod[0x4d + i];
unscrambledMod[0x4d + i] = temp;
}
if (new BigInteger(unscrambledMod).signum()==-1)
{
byte[] temp = new byte[0x81];
System.arraycopy(unscrambledMod, 0, temp, 1, 0x80);
temp[0]=0x00;
unscrambledMod = temp;
}
return unscrambledMod;
}
}
Now it encrypts correctly!
pSala at 2007-7-11 15:33:16 >

# 6
Check out this Javadoc for one of the BigInteger constructors -
public BigInteger(int signum,
byte[] magnitude)
Translates the sign-magnitude representation of a BigInteger into a BigInteger. The sign is represented as an integer signum value: -1 for negative, 0 for zero, or 1 for positive. The magnitude is a byte array in big-endian byte-order: the most significant byte is in the zeroth element. A zero-length magnitude array is permissible, and will result inin a BigInteger value of 0, whether signum is -1, 0 or 1.
Parameters:
signum - signum of the number (-1 for negative, 0 for zero, 1 for positive).
magnitude - big-endian binary representation of the magnitude of the number.
# 7
Thanks a lot! It's working perfectly!
Make the following changes to the code in my previous post!
/*if (new BigInteger(unscrambledMod).signum()==-1)
{
byte[] temp = new byte[0x81];
System.arraycopy(unscrambledMod, 0, temp, 1, 0x80);
temp[0]=0x00;
unscrambledMod = temp;
}*/
return new BigInteger(1,unscrambledMod).toByteArray();
Now it looks thinner! :)
pSala at 2007-7-11 15:33:16 >
