• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 862
  • Last Modified:

Things to note for DES encryption/decryption using Java

I am using the following class for DES encryption/decryption.

Somehow the other party (using some other classes/program) was unable to decrypt the encrypted file i sent to him. He is using DES as well.

May I know what are the field/values which i should check against his? (eg. passphrase, block size etc)

import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.KeySpec;
 
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
 
public class DesEncrypter {
	Cipher ecipher;
	Cipher dcipher;
	byte[] salt = {(byte)0xA9, (byte)0x9B, (byte)0xC8, (byte)0x32, (byte)0x56, (byte)0x35, (byte)0xE3, (byte)0x03};
    //byte[] salt = new byte[16];
    
    
	int iterationCount = 19;
	byte[] buf = new byte[1024];
 
	DesEncrypter(SecretKey key) {
		try {
			SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
			sr.nextBytes(salt); 
			ecipher = Cipher.getInstance("DES");
			dcipher = Cipher.getInstance("DES");
			ecipher.init(Cipher.ENCRYPT_MODE, key);
			dcipher.init(Cipher.DECRYPT_MODE, key);
 
		} catch (javax.crypto.NoSuchPaddingException e) {
		} catch (java.security.NoSuchAlgorithmException e) {
		} catch (java.security.InvalidKeyException e) {
		}
	}
	
	DesEncrypter(String passPhrase) {
        try {
            // Create the key
            KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount);
            SecretKey key = SecretKeyFactory.getInstance(
                "PBEWithMD5AndDES").generateSecret(keySpec);
            ecipher = Cipher.getInstance(key.getAlgorithm());
            dcipher = Cipher.getInstance(key.getAlgorithm());
 
            // Prepare the parameter to the ciphers
            AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);
 
            // Create the ciphers
            ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
            dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
        } catch (java.security.InvalidAlgorithmParameterException e) {
        } catch (java.security.spec.InvalidKeySpecException e) {
        } catch (javax.crypto.NoSuchPaddingException e) {
        } catch (java.security.NoSuchAlgorithmException e) {
        } catch (java.security.InvalidKeyException e) {
        }
    }
 
	public String encrypt(String str) {
	      
		try {
			// Encode the string into bytes using utf-8
			byte[] utf8 = str.getBytes("UTF8");
			
			
 
			// Encrypt
			byte[] enc = ecipher.doFinal(utf8);
 
			// Encode bytes to base64 to get a string
			return new sun.misc.BASE64Encoder().encode(enc);
		} catch (javax.crypto.BadPaddingException e) {
		} catch (IllegalBlockSizeException e) {
		} catch (UnsupportedEncodingException e) {
		} catch (java.io.IOException e) {
		}
		return null;
	}
 
	public String decrypt(String str) {
		try {
			// Decode base64 to get bytes
			//byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);
			byte[] plaindecrypt = dcipher.doFinal(str.getBytes());
 
			// Decrypt
			//byte[] utf8 = dcipher.doFinal(dec);
 
			// Decode using utf-8
			//return new String(utf8, "UTF8");
			return new String(plaindecrypt, "UTF8");
		} catch (javax.crypto.BadPaddingException e) {
		} catch (IllegalBlockSizeException e) {
		} catch (UnsupportedEncodingException e) {
		} catch (java.io.IOException e) {
		}
		return null;
	}
	
	public void encryptFile(InputStream in, OutputStream out) {
        try {
            // Bytes written to out will be encrypted
            out = new CipherOutputStream(out, ecipher);
 
            // Read in the cleartext bytes and write to out to encrypt
            int numRead = 0;
            while ((numRead = in.read(buf)) >= 0) {
                out.write(buf, 0, numRead);
            }
            out.close();
        } catch (java.io.IOException e) {
        }
    }
	
	public void decryptFile(InputStream in, OutputStream out) {
        try {
            // Bytes read from in will be decrypted
            in = new CipherInputStream(in, dcipher);
 
            // Read in the decrypted bytes and write the cleartext to out
            int numRead = 0;
            while ((numRead = in.read(buf)) >= 0) {
                out.write(buf, 0, numRead);
            }
            out.close();
        } catch (java.io.IOException e) {
        }
    }
}

Open in new window

0
edisonffs
Asked:
edisonffs
  • 11
  • 10
  • 9
2 Solutions
 
CEHJCommented:
You need to ensure you're using the same block size and padding
0
 
objectsCommented:
I assume you can decrypt it, is that correct?

What are they using to decrypt?

0
 
objectsCommented:
>                         return new sun.misc.BASE64Encoder().encode(enc);

you base64 encode the bytes when you encode, make sure the receiver is aware of that (and they are using utf8)
(and you don't base64 decode when u decrypt)

0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

 
edisonffsAuthor Commented:
I have ensured that the other party is using a block size of 8 bytes (64-bit) as well
(let's ignore the decryption because i will doing the encryption only)

thus, i will get the other party to check on the following as well:
- Decode using base64 and UTF-8

any other field/values should i verify as well?
0
 
objectsCommented:
> any other field/values should i verify as well?

that should be sufficient
0
 
CEHJCommented:
>>
thus, i will get the other party to check on the following as well:
- Decode using base64 and UTF-8
>>

No need. You're not using that to encrypt the file.
0
 
CEHJCommented:
You might try to do a binary dump of the key at both ends and make sure you're using the same one
0
 
edisonffsAuthor Commented:
guess it's a little confusing here.
let me summarized and see if i get the idea right

if i am using encrypt(), i should check with the other party that he is decoding using Base64 and UTF-8

if i am using encryptFile(), there's no need to check for the character decoding.

So if i am using encryptFile(), what should the receiving party ensure?
0
 
objectsCommented:
try the following if it the file encryption you are having a problem with

http://www.exampledepot.com/egs/javax.crypto/DesFile.html?l=rel

let me know how it goes

0
 
CEHJCommented:
All correct.

>>So if i am using encryptFile(), what should the receiving party ensure?

No harm in taking the md5 sum first at both ends to make sure they got exactly what you sent
0
 
CEHJCommented:
>>what should the receiving party ensure?

Oh and of course what i said a minute ago - that they are using the exact same key as you are
0
 
edisonffsAuthor Commented:
objects:
I will try that out

CEHJ:
So i just need to ensure that the other party is using PBEWithMD5AndDES as well?
0
 
objectsCommented:
yes it goes without saying that both sides need to be using the same encryption method and key/pass phrase :)

0
 
edisonffsAuthor Commented:
objects:

The example you've given me earlier (http://www.exampledepot.com/egs/javax.crypto/DesFile.html?l=rel) , the SecretKey object seems to be "auto generated", but my application's requirement is  to use passphrase method to encrypt file stream.

there's a another link to your example (http://www.exampledepot.com/egs/javax.crypto/PassKey.html?l=rel). this is the one which i have been using all along, and doesn't seem to be working.

Possible to advice me on how to integrate both methods (which i think should be the solution to the problem) ?
0
 
objectsCommented:
you didn't answer my earlier question regards how it is getting decrypted at the other end
Also can you decrypt the file once it is encrypted

0
 
edisonffsAuthor Commented:
objects:

the other end replied that they are decrypting in DES Cipher Block Chaining (CBC) Mode
not sure if this is what you are looking for...

are you referring to the file which i encrypt using my orignal DESEncrypter class (which i posted)?
Yes, i was able to encrypt and decrypt with that
0
 
CEHJCommented:
edisonffs, this is very confusing - please clarify

>>Somehow the other party (using some other classes/program) was unable to decrypt the encrypted file i sent to him.

>>
are you referring to the file which i encrypt using my orignal DESEncrypter class (which i posted)?
Yes, i was able to encrypt and decrypt with that
>>
0
 
objectsCommented:
> are you referring to the file which i encrypt using my orignal DESEncrypter class (which i posted)?

yes

> the other end replied that they are decrypting in DES Cipher Block Chaining (CBC) Mode

you appear to be using the wrong algorithm, try instead using "PBEWithMD5AndDES/CBC/PKCS5Padding"

0
 
edisonffsAuthor Commented:
CEHJ

>>Somehow the other party (using some other classes/program) was unable to decrypt the encrypted file i sent to him.

The other party have their own software to perform decryption. They were unable to decrypt the file which i sent them.

>> are you referring to the file which i encrypt using my orignal DESEncrypter class (which i posted)?
Yes, i was able to encrypt and decrypt with that

Not really sure what objects meant.
If i were to perform encryption/decryption locally using the DESEncrypter class which i posted, i will have no problems with it.
0
 
edisonffsAuthor Commented:
objects:

may i know where should i change it in my DESEncrypter class to use "PBEWithMD5AndDES/CBC/PKCS5Padding"?
0
 
objectsCommented:
>             SecretKey key = SecretKeyFactory.getInstance(
                "PBEWithMD5AndDES").generateSecret(keySpec);

there

0
 
edisonffsAuthor Commented:
objects:

I tried and i get the following exception:

java.lang.NullPointerException
      at javax.crypto.CipherOutputStream.write(DashoA12275)
      at DesEncrypter.encryptFile(DesEncrypter.java:110)
      at TestDES.main(TestDES.java:32)
0
 
objectsCommented:
sorry, my bad. should be:

SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);
ecipher = Cipher.getInstance("PBEWithMD5AndDES/CBC/PKCS5Padding");
dcipher = Cipher.getInstance("PBEWithMD5AndDES/CBC/PKCS5Padding");


0
 
edisonffsAuthor Commented:
objects:

The programs compiles perfectly...

But here's another bomb from the other party.
The padding scheme they are using is called "OneAndZeroes"

And they are actually using a Perl script to do encryption/decryption (pls see attached)

May i know how to amend my class in that case?


#!/usr/bin/perl -w
use strict;
require Crypt::CBC;
require Crypt::DES;
my $algorithm = 'Crypt::DES';
# Usage: filecrypt [e|d] [key] [blocksize] [infile] [outfile]
if(scalar(@ARGV) != 5)
{
  print("Usage: $0 [e|d] [key] [blocksize] [infile] [outfile]\n");
  print("\t e         encrypt infile\n");
  print("\t d         decrypt infile\n");
  print("\t key       cryption key, 8 characters\n");
  print("\t blocksize blocksize filling\n");
  print("\t infile    input file to encrypt/decrypt\n");
  print("\t outfile   output file\n");
  exit 1;
}
 
my $crypt     = $ARGV[0];
my $key       = $ARGV[1];
my $blocksize = $ARGV[2];
my $infile    = $ARGV[3];
my $outfile   = $ARGV[4];
# Create the cipher
my $cipher = Crypt::CBC->new({'key'            => $key,
			      'cipher'         => $algorithm,
			      'iv'             => '',
			      'regenerate_key' => 0,
			      'padding'        => 'oneandzeroes',
			      'prepend_iv'     => 0
			      });
my $input = '';
my $output = '';
$| = 1;
# Read the in file
print("Reading input file...");
open (IN, $infile) or die("Error: No such file: $infile\n");
binmode IN unless $infile =~ /\.txt$/;
$input = do { local $/, <IN> };
close IN;
print("done.\n");
if ( "$crypt" eq "e" )
{
    print("Encrypting data...");
    # Padd to blocksize
    #
    my $paddsize = $blocksize - (length($input) % $blocksize);
    $input = $input . "\0" x $paddsize;
	
    # Encrypt data
    #
    $output = $cipher->encrypt($input);
}
elsif ( "$crypt" eq "d" )
{
    print("Decrypting data...");
    # Decrypt data
    #
    $output = $cipher->decrypt($input);
    print("done.\n");
    
    # Remove padding
    #
    print("Removing padding...");
    $output =~ s/\0+$//g;
}
else
{
    print("Invalid parameter\n");
    exit 1;
}
print("done.\n");
# write to out file
print("Writing output to disk...");
open (OUT, ">$outfile") or die
    ("Error: Unable writing to output file!\n");
binmode OUT unless $outfile =~ /\.txt$/;
print (OUT $output);
close (OUT);
print("done.\n");
print("Finished.\n");

Open in new window

0
 
CEHJCommented:
>>The padding scheme they are using is called "OneAndZeroes"

That's what they say they are going to use, but they don't actually.

The blocksize is chosen as a command line parameter - what do they choose?
0
 
CEHJCommented:
It looks like they're attempting to do the padding whereas the library itself should be doing the padding. If the padding is specified at all (unnecessary) it should be 'standard' as that's the one supported by Java afaik
0
 
edisonffsAuthor Commented:
CEHJ:

they are using blocksize of 64
0
 
CEHJCommented:
OK. I would suggest they parameterize and change/interfere with that Perl library function as little as possible and accept the defaults wherever possible. With any luck, you should be OK then
0
 
edisonffsAuthor Commented:
thanks for the effort guys.

i've decided to install Perl on my Solaris machine and came up with a servlet to call the Perl script (provided by the other party) to do the DES encryption

It's a bad design i know ... ..>.<
0
 
CEHJCommented:
:-)

Well as long as you don't use that Perl script in its present state ...
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

  • 11
  • 10
  • 9
Tackle projects and never again get stuck behind a technical roadblock.
Join Now