Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / Security / February 2006

Tip: Looking for answers? Try searching our database.

Same encrypted value for different keys

Thread view: 
Wojtek Bok - 01 Feb 2006 00:09 GMT
I have a basic mis-understanding on how to encrypt/decrypt information.
I am using the class shown below.

For a given value and two different keys, I am getting the same
encrypted string. Yet I should be getting two different encrypted
strings since the keys are different, even though the value is the same.

For instance:
key = 5
value = abcd
encrypted = x765tra=

key = 4
value = abcd
encrypted = x765tra=

Any help would be appreciated.

-------------------------------------------
package ca.mycomp.utility.tools.encryption;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import ca.mycomp.utility.exceptions.DecryptionException;
import ca.mycomp.utility.exceptions.EncryptionException;
import ca.mycomp.utility.exceptions.EncryptionInitializationException;

import com.sun.crypto.provider.SunJCE;

public class Encryption
{
    // DO NOT change these. They are saved in the database. Changes WILL
make the data unreadable!
    private static final String    ENCODING_SCHEME    = "UTF8";
    private static final String    ENCRYPTION_SCHEME= "DES";

    private static final int    MIN_ENCRYPT_LENGTH    = 10;

    // must be at least MIN_ENCRYPT_LENGTH long
    private static final String    ENCRYPT_PADDING        = "a6kskdkr56xcv3";
    private static final int    PADDING_LENGTH        = ENCRYPT_PADDING.length();
    // DO NOT change these. They are saved in the database. Changes WILL
make the data unreadable!

    private boolean                ivIsUsable    = false;

    private Cipher                ivEncryptCipher;
    private Cipher                ivDecryptCipher;
    private SecretKey            ivKey;

    private static Provider        cvProvider;
    private static boolean        cvIsInitialized        = false;

    public Encryption( long key ) throws EncryptionInitializationException
    {
        this( "" + key );
    }

    public Encryption( String key ) throws EncryptionInitializationException
    {
        super();

        setup( key );
    }

    /**
    * This is only run once for all instances
    *
    */
    private static synchronized void initialize()
    {
        if (!cvIsInitialized)
        {
            cvProvider = new SunJCE();
            Security.addProvider( cvProvider );

            cvIsInitialized = true;
        }
    }

    private void setup( String keyIn ) throws EncryptionInitializationException
    {
        String encryptKey;
        KeySpec keySpec;
        SecretKeyFactory secretKey;
        byte[] keyBytes;

        initialize();

        try
        {
            // DO NOT change these. They are saved in the database. Changes WILL
make the data unreadable!
            if (keyIn.length() < MIN_ENCRYPT_LENGTH)
                encryptKey = keyIn + ENCRYPT_PADDING.substring( 0, PADDING_LENGTH -
keyIn.length() );
            else
                encryptKey = keyIn;
            // DO NOT change these. They are saved in the database. Changes WILL
make the data unreadable!

            keyBytes = encryptKey.getBytes( ENCODING_SCHEME );
            keySpec = new DESKeySpec( keyBytes );
            secretKey = SecretKeyFactory.getInstance( ENCRYPTION_SCHEME,
cvProvider );
            ivKey = secretKey.generateSecret( keySpec );

            ivEncryptCipher = Cipher.getInstance( ENCRYPTION_SCHEME, cvProvider );
            ivDecryptCipher = Cipher.getInstance( ENCRYPTION_SCHEME, cvProvider );

            ivEncryptCipher.init( Cipher.ENCRYPT_MODE, ivKey );
            ivDecryptCipher.init( Cipher.DECRYPT_MODE, ivKey );

            ivIsUsable = true; // all setup worked, so we can do things .....
        }
        catch (SecurityException e)
        {
            throw new EncryptionInitializationException( e.toString() );
        }
        catch (UnsupportedEncodingException e)
        {
            throw new EncryptionInitializationException( e.toString() );
        }
        catch (InvalidKeyException e)
        {
            throw new EncryptionInitializationException( e.toString() );
        }
        catch (InvalidKeySpecException e)
        {
            throw new EncryptionInitializationException( e.toString() );
        }
        catch (NoSuchAlgorithmException e)
        {
            throw new EncryptionInitializationException( e.toString() );
        }
        catch (NoSuchPaddingException e)
        {
            throw new EncryptionInitializationException( e.toString() );
        }
    }

    public String decrypt( String text ) throws DecryptionException
    {
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] decodedBytes;
        byte[] clearBytes;
        String inClear = "";

        initialize();

        if (!ivIsUsable)
            throw new DecryptionException( "Decryptor not Initialized" );

        try
        {
            decodedBytes = decoder.decodeBuffer( text );
            clearBytes = ivDecryptCipher.doFinal( decodedBytes );
            inClear = new String( clearBytes, ENCODING_SCHEME );
        }
        catch (IOException e)
        {
            throw new DecryptionException( e.toString() );
        }
        catch (IllegalStateException e)
        {
            throw new DecryptionException( e.toString() );
        }
        catch (IllegalBlockSizeException e)
        {
            throw new DecryptionException( e.toString() );
        }
        catch (BadPaddingException e)
        {
            throw new DecryptionException( e.toString() );
        }

        return inClear;
    }

    public String encrypt( String text ) throws EncryptionException
    {
        BASE64Encoder encoder = new BASE64Encoder();
        byte[] clearBytes;
        byte[] encryptedBytes;
        String encrypted = "";

        initialize();

        if (!ivIsUsable)
            throw new EncryptionException( "Encryptor not Initialized" );

        try
        {
            clearBytes = text.getBytes( ENCODING_SCHEME );
            encryptedBytes = ivEncryptCipher.doFinal( clearBytes );
            encrypted = encoder.encode( encryptedBytes );
        }
        catch (UnsupportedEncodingException e)
        {
            throw new EncryptionException( e.toString() );
        }
        catch (IllegalStateException e)
        {
            throw new EncryptionException( e.toString() );
        }
        catch (IllegalBlockSizeException e)
        {
            throw new EncryptionException( e.toString() );
        }
        catch (BadPaddingException e)
        {
            throw new EncryptionException( e.toString() );
        }

        return encrypted;
    }
}
Mike Amling - 01 Feb 2006 01:49 GMT
> I have a basic mis-understanding on how to encrypt/decrypt information.
> I am using the class shown below.
[quoted text clipped - 16 lines]
>
>     private void setup( String keyIn ) throws

  Why on earth would you specify a key as a String? If the parameter is
supposed to be a password rather than a key, then you should hash it to
get the key bytes.

> EncryptionInitializationException
>     {
[quoted text clipped - 13 lines]
> PADDING_LENGTH - keyIn.length() );
>             else

  All keys less than 10 characters get padded to a full 14 characters.

>                 encryptKey = keyIn;
>             // DO NOT change these. They are saved in the database.
> Changes WILL make the data unreadable!
>
>             keyBytes = encryptKey.getBytes( ENCODING_SCHEME );

  keyBytes is 14 bytes long. Since (single) DES needs at most 7 or 8
bytes of key material, which of these 14 bytes actually get used?
  If it's the last 7 or 8 bytes, then all of the key material comes
from the padding for keys of up to 6 or 7 characters.
  If it's the first 8 bytes, then you should realize that DES's 56 bits
of key material is taken from the 7 high-order bits of those bytes, and
your two keys "4" and "5" differ only in the low-order bit of one byte.
  If it's the first 7 bytes, then more investigation is warranted.

>             keySpec = new DESKeySpec( keyBytes );
>             secretKey = SecretKeyFactory.getInstance( ENCRYPTION_SCHEME,
[quoted text clipped - 11 lines]
>             ivIsUsable = true; // all setup worked, so we can do things
> .....

--Mike Amling
Wojtek Bok - 01 Feb 2006 16:53 GMT
>>     private void setup( String keyIn ) throws
>   Why on earth would you specify a key as a String? If the parameter is
> supposed to be a password rather than a key, then you should hash it to
> get the key bytes.

No, it is an actual key. The password would be encrypted.

The key is a unique column in the table, and is immutable, so each row
has its own unique key, which is used to encrypt/decrypt other columns
in that row.

>>             keyBytes = encryptKey.getBytes( ENCODING_SCHEME );
>
>   keyBytes is 14 bytes long. Since (single) DES needs at most 7 or 8
> bytes of key material, which of these 14 bytes actually get used?

Ok, now I understand why I needed to pad the key on the first place. DES
needs AT LEAST 7 (or 8) bytes.

>   If it's the last 7 or 8 bytes, then all of the key material comes from
> the padding for keys of up to 6 or 7 characters.
>   If it's the first 8 bytes, then you should realize that DES's 56 bits
> of key material is taken from the 7 high-order bits of those bytes, and
> your two keys "4" and "5" differ only in the low-order bit of one byte.
>   If it's the first 7 bytes, then more investigation is warranted.

I tried appending the keyIn, rather than prepending it. Then I tried
both appending and prepending

>>             ivKey = secretKey.generateSecret( keySpec );

Ok, ivKey.hashCode() returns the same value for both keyIn values, so
what I am running into is a hash collision.
Mike Amling - 03 Feb 2006 19:34 GMT
>>>     private void setup( String keyIn ) throws
>>
[quoted text clipped - 7 lines]
> has its own unique key, which is used to encrypt/decrypt other columns
> in that row.

  If the key is in a column the table, how can you prevent anyone who
reads a row from decrypting the data?

--Mike Amling
Wojtek Bok - 06 Feb 2006 15:03 GMT
>> The key is a unique column in the table, and is immutable, so each row
>> has its own unique key, which is used to encrypt/decrypt other columns
>> in that row.
>
>   If the key is in a column the table, how can you prevent anyone who
> reads a row from decrypting the data?

The only people who would have accesss to the raw information in the DB
would also need physical access, plus login access to the DB server. All
other access is through a Web application.

The encryption is to prevent some DBA from simply copy/pasting values
from  one place to another. If I used a common key, then that would
work. Since the key is different for each row, then you must use the
decryption/encryption routines to move the information.

Not impossible, but much harder.


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.