0

Please help me :(, I am trying this answer in this post Converting string to SecretKey

But it doesn't seem to be working for RC4, please tell me what I am doing wrong. This is my RC4 class in a separate file:

public class RC4 {
    SecretKey k;


    public RC4() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
       KeyGenerator kg = KeyGenerator.getInstance("RC4");
       k = kg.generateKey();
    }

    public byte[] encrypt(final byte[] plaintext) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        Cipher cipher = Cipher.getInstance("RC4");  // Transformation of the algorithm
        cipher.init(Cipher.ENCRYPT_MODE, k);
        byte[] cipherBytes = cipher.doFinal(plaintext);
        return cipherBytes;
    }

    public byte[] decrypt(final byte[] ciphertext) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        Cipher cipher = Cipher.getInstance("RC4");
          cipher.init(Cipher.DECRYPT_MODE, k);
          byte[] plainBytes = cipher.doFinal(ciphertext);
          return plainBytes;
    }
    
    public SecretKey getK() {
        return k;
    }

    public void setK(SecretKey k) {
        this.k = k;
    }

}

This code below is also from another file in a main method

RC4 rc4Client = new RC4();
SecretKey k = rc4Client.getK();

String encodedK = Base64.getEncoder().encodeToString(k.getEncoded());

//print
System.out.println("Random k: " + k.toString());

byte[] decodedKey = Base64.getDecoder().decode(encodedK);
k = new SecretKeySpec(decodedKey, 0, decodedKey.length, "RC4");

//print
System.out.println("Random k: " + k.toString());

The printed output is:

Random k: javax.crypto.spec.SecretKeySpec@2c97f72b
Random k: javax.crypto.spec.SecretKeySpec@fffe4170

They should be the same, why are they different??

Astoach167
  • 91
  • 1
  • 7
  • 1
    You are seeing a default implementation of toString() method in Object class, SecretKey does not override that, you should look into getEncoded() and getFormat() methods of SecretKey. – suff Jul 30 '20 at 11:56
  • I have looked into it did what this answer say for Java 8 https://stackoverflow.com/questions/48305410/converting-string-to-secretkey, but I still couldn't get the back the same key after encoding and decoding from string to key and vice versa :( – Astoach167 Jul 30 '20 at 13:02
  • Just to make this clear... what do you mean by "same key" if you are expecting the k.toString() to be identical that will not happen as you are constructing a different instance.... the key material should be the same though. – suff Jul 31 '20 at 15:13

2 Answers2

0

Convert the k to a byte array and then to String:

byte[] kByte = k.getEncoded();
String encodedK = Base64.getEncoder().encodeToString(kByte)
0

As per comments. Running...

    public static void main( String[] args ) throws NoSuchAlgorithmException {
        KeyGenerator kg = KeyGenerator.getInstance("RC4");
        SecretKey k1 = kg.generateKey();
        String b64k1 = Base64.encode(k1.getEncoded());
        byte[] bk1 = Base64.decode(b64k1);
        SecretKey k2 = new SecretKeySpec( bk1, 0, bk1.length, "RC4");
        String b64k2 = Base64.encode(k2.getEncoded());
        byte[] bk2 = Base64.decode(b64k2);
        System.out.println(k1);
        System.out.println(k2);
        System.out.println(Arrays.toString(bk1));
        System.out.println(Arrays.toString(bk2));
        System.out.println(b64k1);
        System.out.println(b64k2);
    }

Gives the following output:

javax.crypto.spec.SecretKeySpec@d36802be
javax.crypto.spec.SecretKeySpec@1b4e5
[107, -27, -118, -72, 46, -37, -57, -67, -84, 94, 20, 79, 123, 79, -50, 101]
[107, -27, -118, -72, 46, -37, -57, -67, -84, 94, 20, 79, 123, 79, -50, 101]
a+WKuC7bx72sXhRPe0/OZQ==
a+WKuC7bx72sXhRPe0/OZQ==

To clarify, k1.toString() and k2.toString() are only dependent on object instance in Object.toString() default implementation and since k1 and k2 are distinct objects, the output is different. The actual key material is shown in next 4 lines as byte[] and then as base64 encoded String of that byte array and is equal as expected.

As an additional note, RC4 is not considered safe and should not be used in real production code.

suff
  • 66
  • 4