Dragomirus
Dragomirus

Reputation: 449

Java, rsa encryption

So I have a byte array and I want to encrypt this array using rsa, but also I want to leave first byte untouched like this:

//Before encryption:
byteArray[0] = 1;
byteArray[1] = 0;
byteArray[2] = 1;

//After encryption:
byteArray[0] = 1; //untouched
byteArray[1] = -127; //encrypted
byteArray[2] = 230; //encrypted

Which method of doFinal I should use?

@edit Why this isn't working?

        try
        {
            byte[] pack = new byte[4];
            byte[] pack2;
            byte[] pack3;
            pack[0] = 1;
            pack[1] = 2;
            pack[2] = 3;
            pack[3] = 4;

            System.out.println("START!");
            for(int i = 0; i < 4; i++)
            {
                System.out.println(pack[i]);
            }

            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(512);
            KeyPair keyPair = keyPairGenerator.genKeyPair();

            Cipher cip = Cipher.getInstance("RSA");
            cip.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
            pack2 = cip.doFinal(pack, 1, pack.length-1);
            for(int i = 0; i < 4; i++)
            {
                System.out.println(pack2[i]);
            }

            Cipher cip2 = Cipher.getInstance("RSA");
            cip2.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
            pack3 = cip2.doFinal(pack2, 1, pack2.length-1);
            for(int i = 0; i < 4; i++)
            {
                System.out.println(pack3[i]);
            }

            System.out.println("END!");

        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

and output is:

START!
1
2
3
4
111
-44
120
103
java.lang.ArrayIndexOutOfBoundsException: 3

Upvotes: 1

Views: 884

Answers (3)

Dave G
Dave G

Reputation: 9767

I've updated your code a little. Look for the comments I've inserted.

Essentially, RSA returns a block of data (cipher-text) when you encrypt that is significantly larger than your data (plain-text). This is by design. In your case, since you are using 512-bits for your key length, you can expect a 512-bit (64-byte) output block from enciphering the plain-text. To decipher the cipher-text you MUST have the entire block of cipher-text to perform a decrypt.

try
{
    byte[] pack = new byte[4];
    byte[] pack2;
    byte[] pack3;
    pack[0] = 1;
    pack[1] = 2;
    pack[2] = 3;
    pack[3] = 4;

    System.out.println("START!");
    System.out.println("pack");
    for(int i = 0; i < 4; i++)
    {
        System.out.println(pack[i]);
    }
    System.out.println("");

    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(512);
    KeyPair keyPair = keyPairGenerator.genKeyPair();

    Cipher cip = Cipher.getInstance("RSA");
    cip.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
    // I think you said you wanted the last 3 bytes encrypted
    //                        vvvvvvvvvvvvvvvv
    pack2 = cip.doFinal(pack, 1, pack.length-1);
    System.out.println("pack2");
    for(int i = 0; i < 4; i++)
    {
        System.out.println(pack2[i]);
    }
    System.out.println("");

    Cipher cip2 = Cipher.getInstance("RSA");
    cip2.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
    byte[] pack3Tmp= cip2.doFinal(pack2, 0, pack2.length);
    pack3= new byte[pack.length];
    // Copy over the first byte you had mentioned to be 
    // unecrypted
    pack3[0]= pack[0];
    // Use System.arraycopy
    //               Source is pack3Tmp
    //               |         Starting offset is 0
    //               |         |  Destination is pack3
    //               |         |  |      Staring offset in pack3 is 1
    //               |         |  |      |  Copy all of pack3Tmp
    //               |         |  |      |  |
    //               v         v  v      v  v
    System.arraycopy(pack3Tmp, 0, pack3, 1, pack3Tmp.length);
    System.out.println("pack3");
    for(int i = 0; i < 4; i++)
    {
        System.out.println(pack3[i]);
    }
    System.out.println("");

    System.out.println("END!");
}
catch(Exception e)
{
    e.printStackTrace();
}

Upvotes: 2

President James K. Polk
President James K. Polk

Reputation: 41958

This has nothing to do with RSA, it's just basic Java programming mistakes. pack2[0] through pack2[pack2.length-1] contain the result of encrypting pack[1] through pack[pack.length-1]. Thus, in order to decrypt successfully, you must supply pack2[0] through pack2[pack2.length-1]. Since you supply the decryptor with pack2 starting pack2[1] your code should throw a decryption error exception, not the exception you are reporting. Therefore I have to also conclude that code you provided and the output you provided don't go together.

If you want to copy the first byte of pack to pack2 you have to do that yourself, perhaps with the assistance of one of Arrays.copy*() methods and/or System.arraycopy().

Upvotes: 2

Jire
Jire

Reputation: 10270

You should use byte[] doFinal(byte[] input, int inputOffset, int inputLen) specifying 1 as the input offset and the length of the array as the input length.

In your case: doFinal(byteArray, 1, byteArray.length)

Upvotes: 0

Related Questions