3

I am really baffled as to why the encoded values are different

Heres the complete code

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.security.Key;
import java.security.KeyStore;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

import org.bouncycastle.util.encoders.Base64;

public class KeyStoreDemo {

    private static final String KEY_STORE_TYPE = "JCEKS";
    private static final String KEY_STORE_NAME = "sampleKeyStore.store";
    private static final String KEY_STORE_PASSWORD = "letmein";


    public static void main(String[] args) throws Exception {
        File storeFile = new File(KEY_STORE_NAME);
        storeFile.createNewFile();

        //Create a keystore
        createKeyStore(KEY_STORE_TYPE, storeFile,KEY_STORE_PASSWORD);

        //Generate a key and store it in keystore
        KeyStore keyStore = loadKeyStore(KEY_STORE_TYPE,storeFile,KEY_STORE_PASSWORD);      


        // Get the KeyGenerator     
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");keyGenerator.init(128); Key keytemp = keyGenerator.generateKey();       
        System.out.println("key- Base64 before:"+Base64.encode (keytemp.getEncoded()) );
        //createSecretKeyAndStore( keyStore, keytemp, "samplekey" ,"samplepwd");
        createSecretKeyAndStore(storeFile, keyStore, KEY_STORE_PASSWORD, keytemp, "samplekey" ,"samplepwd");

        Key key = getKeyFromStore(keyStore, "samplekey", "samplepwd");
        System.out.println("key- Base64  after :"+Base64.encode (key.getEncoded()) );



    }   

    private static KeyStore createKeyStore(String keyStoreType,File keyStoreFile,String keyStorePassword) throws Exception{     

        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load((InputStream) null, keyStorePassword.toCharArray());

        // Write KeyStore to disk
        final FileOutputStream fileOutputStream = new FileOutputStream(keyStoreFile);

        try {
            keyStore.store(fileOutputStream, keyStorePassword.toCharArray());
            fileOutputStream.flush();
        } finally {
            fileOutputStream.close();
        }       

        return keyStore;
    }

    private static KeyStore loadKeyStore(String keyStoreType,File keyStoreFile,String keyStorePassword) throws Exception{
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load((InputStream) new FileInputStream(keyStoreFile), keyStorePassword.toCharArray());     
        return keyStore;
    }



    private static void createSecretKeyAndStore(File  keyStorefile ,KeyStore keyStore,String keyStorePwd, Key key, String keyAlias ,String keyAccessPassword) throws Exception{
        keyStore.setKeyEntry(keyAlias, key, keyAccessPassword.toCharArray(), null);

        // Write KeyStore to disk
        final FileOutputStream fileOutputStream = new FileOutputStream(keyStorefile);

        try {
            keyStore.store(fileOutputStream, keyStorePwd.toCharArray());
        } finally {
            fileOutputStream.close();
        }
    }




    private static Key getKeyFromStore(KeyStore keyStore, String keyAlias,String keyAccessPassword) throws Exception {
        Key  keyFromStore = null;
        keyFromStore =  keyStore.getKey(keyAlias, keyAccessPassword.toCharArray());
        return keyFromStore;
    }   

}

Result

key- Base64 before:[B@c7e553
key- Base64  after :[B@1ac04e8
Davin Tryon
  • 66,517
  • 15
  • 143
  • 132
Sudhakar
  • 4,823
  • 2
  • 35
  • 42
  • 2
    You are getting the default Java `Object.toString()` behaviour. Your problem is with Java, not encryption. Try `Arrays.toString(Base64.encode (key.getEncoded()))` – rossum Mar 07 '13 at 17:11
  • @PresidentJamesK.Polk Seriously `new String(Base64.encode(key.getEncoded()))` and that is three time use of `encode' just to encode! That is Java. – Atul Aug 21 '22 at 18:05

3 Answers3

6

Base64.encode returns a char[] - the fact that you're getting two separate arrays is not telling you that the values within the arrays are different, just that they are two separate instances.

What you need to do is compare the actual arrays returned to check if they're they contain the same encoded value:

boolean areEqual = Arrays.equals(Base64.encode (keytemp.getEncoded()), 
                                 Base64.encode (key.getEncoded()));
Sean Landsman
  • 7,033
  • 2
  • 29
  • 33
3

Well thats because , what your printing is not the Encoded String ,its a toString value of the char[] array.

System.out.println("key-Base64 before:"+new String(Base64.encode(keytemp.getEncoded())));

System.out.println("key-Base64  after :"+new String(Base64.encode(key.getEncoded())) );
rocky
  • 91
  • 2
0

Well, it seems to me the result output you are showing does not support the conclusion you are drawing.

The following line does not print the base64 representation of the key :

System.out.println(Base64.encode (key.getEncoded()));

What it does print is the result of invoking toString() on the byte[] instance that is returned by the Base64 conversion. Calling toString() on a byte[] does not convert the byte[] to its string representation at all.

As a consequence the only conclusion you can support out of your result is that the two byte[] instances are not the same object instance inside you JVM, which seems reasonnable given what you are doing.

If you want to compare byte[] instances by comparing their contents, byte by byte, you may use

Arrays.equals(tempKey.getEncoded(), key.getEncoded())

Or to compare the Base64 of the encoded keys :

Arrays.equals(Base64.encode(tempKey.getEncoded()), Base64.encode(key.getEncoded()))

If you want to compare the String representations, you need to convert the byte[] to a String, which is easy seeing base64 only uses ASCII safe values:

String tempKeyEncoded = new String(Base64.encode(tempKey.getEncoded), "US-ASCII");
String keyEncoded = new String(Base64.encode(key.getEncoded), "US-ASCII");
System.out.println(tempKeyEncoded.equals(keyEncoded));

Hope this helps.

GPI
  • 9,088
  • 2
  • 31
  • 38