En/Decryption

G

guyzdancin

I've deployed an application via java web start that I want to protect
via password encryption. The client enters a username and password.
The username is sent to a web server which searches a data base for the
user's password. The server then encrypts a string, known to the
client using the password as the key. Client then decrypts the string
with the user entered password.

I am having trouble with the encrypt (server side) and decrypt (client
side) methods. Below is code that can be compiled and run which tests
these methods. Main takes 2 args - arg[0] is an 8 bit ("DES"
algorithm) password and arg[1] is a message for en/decryption. There
are several System.out() statements for variable states.

The problem is that the decrypted string has 8 leading spaces then 8
bytes of the decrypted string followed by 8 bits of some junk. It then
follows alternating with 8 bits of string and 8 bits of junk.

Thanks in advance for any help.



-----------------------------------------

import java.io.*;
import java.net.*;
import java.awt.*;
import com.guysussman.lpt.error.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;




public class TestDeEnCrypt
{
//method decrypts encrypted application key from server with client
entered password
public String decrypt(String password, String encryptedAppKey)throws
GeneralSecurityException{
Cipher cipher = Cipher.getInstance("DES");
SecretKeySpec key = new SecretKeySpec( password.getBytes(), "DES" );
cipher.init(Cipher.DECRYPT_MODE, key);

String decryptedAppKey = new String("");

int blockSize = cipher.getBlockSize();
int outputSize = cipher.getOutputSize(blockSize);
byte[] inBytes = new byte[blockSize];// 8
byte[] outBytes = new byte[outputSize];

int indexPosition = 0;
//number of 8 byte chunks in appKey
int numberOfChunks = encryptedAppKey.length()/blockSize;
//number of chunks needing padding
int paddingDeficiency = encryptedAppKey.length()%blockSize;

boolean more = true;

//build the decrypted app key
for(int i = 1; i <= numberOfChunks; i++){
String stringChunk = encryptedAppKey.substring(indexPosition,
indexPosition + blockSize);
int outLength = cipher.update(stringChunk.getBytes(), 0, blockSize,
outBytes);
decryptedAppKey += new String(outBytes);

indexPosition += blockSize;
}
//pad last chunk
if(paddingDeficiency == 0){
outBytes = cipher.doFinal();
decryptedAppKey += new String(outBytes);
}
else{
String deficientString = encryptedAppKey.substring(indexPosition);
outBytes = cipher.doFinal( deficientString.getBytes(), 0,
deficientString.length() );
decryptedAppKey += new String(outBytes);
}

return decryptedAppKey;
}



//method encrypts encrypted application key from server data base
public String encrypt(String password, String AppKey)throws
GeneralSecurityException{
Cipher cipher = Cipher.getInstance("DES");
SecretKeySpec key = new SecretKeySpec( password.getBytes(), "DES" );
cipher.init(Cipher.ENCRYPT_MODE, key);

String encryptedKey = new String("");

int blockSize = cipher.getBlockSize();
int outputSize = cipher.getOutputSize(blockSize);
byte[] inBytes = new byte[blockSize];// 8
byte[] outBytes = new byte[outputSize];

int indexPosition = 0;
int numberOfChunks = AppKey.length()/blockSize;

System.out.println("number of Chunks: " + numberOfChunks);

int paddingDeficiency = AppKey.length()%blockSize;

System.out.println("paddingDeficiency: " + paddingDeficiency);

boolean more = true;

for(int i = 1; i <= numberOfChunks; i++){
String stringChunk = AppKey.substring(indexPosition, indexPosition +
blockSize);

System.out.print(stringChunk + " : ");

int outLength = cipher.update(stringChunk.getBytes(), 0, blockSize,
outBytes);
encryptedKey += new String(outBytes);

System.out.println("indexPosition: " + indexPosition);

indexPosition += blockSize;
}
if(paddingDeficiency == 0){
outBytes = cipher.doFinal();
encryptedKey += new String(outBytes);
}
else{
String deficientString = AppKey.substring(indexPosition);

System.out.println(deficientString);

outBytes = cipher.doFinal( deficientString.getBytes(), 0,
deficientString.length() );
encryptedKey += new String(outBytes);
}

return encryptedKey;
}

public static void main(String[]args){
TestDeEnCrypt test = new TestDeEnCrypt();

System.out.println("original string: " + args[1]);

try{
String encryptedString = test.encrypt(args[0], args[1]);
System.out.println( "encrypted string: " + encryptedString );

String decryptedString = test.decrypt(args[0], encryptedString );
System.out.println( "decrypted string: " + decryptedString );
}catch(GeneralSecurityException e){System.out.println( e.getMessage()
);}
System.out.println("Jesus Lives");
}
}
 
M

Matt Humphrey

guyzdancin said:
I've deployed an application via java web start that I want to protect
via password encryption. The client enters a username and password.
The username is sent to a web server which searches a data base for the
user's password. The server then encrypts a string, known to the
client using the password as the key. Client then decrypts the string
with the user entered password.

I am having trouble with the encrypt (server side) and decrypt (client
side) methods. Below is code that can be compiled and run which tests
these methods. Main takes 2 args - arg[0] is an 8 bit ("DES"
algorithm) password and arg[1] is a message for en/decryption. There
are several System.out() statements for variable states.

The problem is that the decrypted string has 8 leading spaces then 8
bytes of the decrypted string followed by 8 bits of some junk. It then
follows alternating with 8 bits of string and 8 bits of junk.

Thanks in advance for any help.



-----------------------------------------

import java.io.*;
import java.net.*;
import java.awt.*;
import com.guysussman.lpt.error.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;




public class TestDeEnCrypt
{
//method decrypts encrypted application key from server with client
entered password
public String decrypt(String password, String encryptedAppKey)throws
GeneralSecurityException{
Cipher cipher = Cipher.getInstance("DES");
SecretKeySpec key = new SecretKeySpec( password.getBytes(), "DES" );

I would think the problem is here at getBytes() and all other places where
you convert bytes to strings and back. This method uses the default
platform encoding which is likely to be different between the client and the
server. You must be sure to use the same encoding on both ends.

<remaining code snipped./>

Cheers,
Matt Humphrey (e-mail address removed) http://www.iviz.com/
 
G

guyzdancin

Thank you Mat for your suggestions. The first code in this trail does
not communicate through a server client but is rather executed on a
stand alone box. So I imagine the encoding will be the same. In the
version immediately below, I invoked trim() on all the Strings before I
called String.getBytes(). This produced a curious result in that it
successfully encrypted and decrypted all messages except those exactly
15 bytes in length. Try running the code below which can be compiled
and run.

I'm still stuck!


Guy

---------------------------------------------------------------------------------------------


import java.io.*;
import java.net.*;
import java.awt.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;

/*
arg[0] - 8 byte password
arg[1] - string to encrypt
*/


public class TestDeEnCrypt
{
//started with decrypt from archive 12
public String crypt(String password, String AppKey, String mode)throws
GeneralSecurityException{

Cipher cipher = Cipher.getInstance("DES");
SecretKeySpec key = new SecretKeySpec( password.getBytes(), "DES" );
if( mode.equals("-encrypt") ){
cipher.init(Cipher.ENCRYPT_MODE, key);
}
else{
cipher.init(Cipher.DECRYPT_MODE, key);
}

String encryptedKey = ( new String("") ).trim();

int blockSize = cipher.getBlockSize();
int outputSize = cipher.getOutputSize(blockSize);
byte[] inBytes = new byte[blockSize];// 8
byte[] outBytes = new byte[outputSize];

System.out.println("blockSize: " + blockSize);
System.out.println("outputSize: " + outputSize);
System.out.println("inBytes: " + inBytes.length);
System.out.println("outBytes: " + outBytes.length);

int indexPosition = 0;
int numberOfChunks = AppKey.length()/blockSize;
int paddingDeficiency = AppKey.length()%blockSize;

boolean more = true;
int outLength = 0;

for(int i = 0; i < numberOfChunks; i++){
String stringChunk = AppKey.substring(indexPosition, indexPosition +
blockSize);
inBytes = ( stringChunk.trim() ).getBytes();
System.out.println("inBytes: " + inBytes + " iteration: " + i);
System.out.println("you are here line 54 - iteration: " + i);

outLength = cipher.update(inBytes, 0, blockSize, outBytes);
encryptedKey += (new String(outBytes)).trim();

indexPosition += blockSize;
}
if(paddingDeficiency == 0){
outBytes = cipher.doFinal();
encryptedKey += (new String(outBytes)).trim();
}
else{
String deficientString = AppKey.substring(indexPosition);
inBytes = ( (deficientString.trim()).getBytes() );
System.out.println("Deficient String: " + deficientString);
System.out.println("Deficient byte array: " + inBytes);

outBytes = cipher.doFinal( inBytes, 0,
(deficientString.trim()).length() );
encryptedKey += new String(outBytes);
}

return encryptedKey;
}

public static void main(String[]args){
TestDeEnCrypt test = new TestDeEnCrypt();

try{
System.out.println("Start to call Encrypt");
String encryptedString = test.crypt(args[0], args[1], "-encrypt");
System.out.println("Encrypt returns");
System.out.println( "encrypted string: " + encryptedString );

System.out.println("Start to call Decrypt");
String decryptedString = test.crypt(args[0], encryptedString,
"-decrypt" );
System.out.println("Decrypt returns");
System.out.println( "decrypted string: " + decryptedString );

}catch(GeneralSecurityException e){System.out.println( e.getMessage()
);}
System.out.println("Moses Rules");
}
}
 
G

Greg Stark

There are a number of problems with the code. The data coming out of
the encrypt operation is essentially random. It does not make sense to
run trim() on it. It will fail a certain percentage of the time.

Also, you are ignoring the outLength value returned and instead
converting all 16 bytes of outBytes, of which only the first 8 are
really correct. Although, since the last 8 bytes just happen to be
zeros, trim gets rid of them for you.

Note that the SunJCE provider handles the padding /unpadding for you.

Unless you are encrypting large amounts of data, use the simplest
method of Cipher, e.g. just use

// encrypt
byte [] outBytes = cipher.doFinal (appKey.getBytes());

..
..
..
// decrypt

String appKeyFromCipher = new String(cipher.doFinal(outBytes));

If you need to encode the cipher for some reason, then use base64
encoding or something similar.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top