using CipherInputStream

J

jimgardener

hi
i was trying to encrypt and decrypt a string using CipherOutputStream
and CipherInputStream as below.I wanted to write the encrypted string
to a file "encfile.enc" using CipherOutputStream and then read back
the decrypted version from that file using CipherInputStream

String plaintext="war starts tomorrow at 19 hours";
byte[] plainbytes=plaintext.getBytes("UTF-8");

KeyGenerator kg=KeyGenerator.getInstance("DES");
SecretKey skey=kg.generateKey();
byte[] deskey= skey.getEncoded();
SecretKeySpec spec=new SecretKeySpec(deskey,"DES");
Cipher cip=Cipher.getInstance("DES/ECB/PKCS5Padding");
cip.init(Cipher.ENCRYPT_MODE, spec);

CipherOutputStream cipout=new CipherOutputStream(new

FileOutputStream("encfile.enc"),cip);
cipout.write(plainbytes);
cipout.flush();

//now i init the cipher for decryption and use CipherInputStream
cip.init(Cipher.DECRYPT_MODE, spec);
CipherInputStream cipin=new CipherInputStream(new
FileInputStream("encfile.enc"),cip);
byte[] decryptedbytes=new byte[plainbytes.length];
cipin.read(decryptedbytes);
String decryptedtext=new String(decryptedbytes);
System.out.println("plain>>\n"+plaintext);
System.out.println("decrypted>>\n"+decryptedtext);


the result i get is
plain>>
war starts tomorrow at 19 hours
decrypted>>
war starts tomor
Here, after the 16 characters i am getting 'square like' characters.Am
i doing something wrong here?why doesn't the CipherInputStream read/
decrypt the full string?
 
R

Roedy Green

the result i get is
plain>>
war starts tomorrow at 19 hours
decrypted>>
war starts tomor

I think your problem is you are using flush rather than close. Have a
look at my code at http://mindprod.com/jgloss/jce.html#CIPHER

Mine has the same problem, but I lose only ONE character. I think
there is a bug in Sun's code. I'd like it if a few people could look
at my SSCCE to verify the bug before I report. I would hate to have
egg on my beard because this loss of the last character is some sort
of feature.
 
A

Arne Vajhøj

jimgardener said:
i was trying to encrypt and decrypt a string using CipherOutputStream
and CipherInputStream as below.I wanted to write the encrypted string
to a file "encfile.enc" using CipherOutputStream and then read back
the decrypted version from that file using CipherInputStream

String plaintext="war starts tomorrow at 19 hours";
byte[] plainbytes=plaintext.getBytes("UTF-8");

KeyGenerator kg=KeyGenerator.getInstance("DES");
SecretKey skey=kg.generateKey();
byte[] deskey= skey.getEncoded();
SecretKeySpec spec=new SecretKeySpec(deskey,"DES");
Cipher cip=Cipher.getInstance("DES/ECB/PKCS5Padding");

See rossums comments about DES.
cip.init(Cipher.ENCRYPT_MODE, spec);

CipherOutputStream cipout=new CipherOutputStream(new

FileOutputStream("encfile.enc"),cip);
cipout.write(plainbytes);
cipout.flush();

As several others has pointed out use:

cipout.close();
//now i init the cipher for decryption and use CipherInputStream
cip.init(Cipher.DECRYPT_MODE, spec);
CipherInputStream cipin=new CipherInputStream(new
FileInputStream("encfile.enc"),cip);
byte[] decryptedbytes=new byte[plainbytes.length];
cipin.read(decryptedbytes);

It works if you replace the line above with:

int n = 0;
while(n < plainbytes.length) {
n += cipin.read(decryptedbytes, n, decryptedbytes.length - n);
}
String decryptedtext=new String(decryptedbytes);
System.out.println("plain>>\n"+plaintext);
System.out.println("decrypted>>\n"+decryptedtext);

the result i get is
plain>>
war starts tomorrow at 19 hours
decrypted>>
war starts tomor
Here, after the 16 characters i am getting 'square like' characters.Am
i doing something wrong here?why doesn't the CipherInputStream read/
decrypt the full string?

plain>>
war starts tomorrow at 19 hours
decrypted>>
war starts tomorrow at 19 hours

Arne
 
A

Arne Vajhøj

Roedy said:
I think your problem is you are using flush rather than close. Have a
look at my code at http://mindprod.com/jgloss/jce.html#CIPHER

Mine has the same problem, but I lose only ONE character. I think
there is a bug in Sun's code. I'd like it if a few people could look
at my SSCCE to verify the bug before I report. I would hate to have
egg on my beard because this loss of the last character is some sort
of feature.

It is a bug in your code.

Replace:

final int reconstitutedBytesRead = cin.read( reconstitutedBytes );

with:

int reconstitutedBytesRead = 0;
int n;
while((n = cin.read( reconstitutedBytes,
reconstitutedBytesRead, bytesToRead - reconstitutedBytesRead )) > 0) {
reconstitutedBytesRead += n;
}

and it should work.

Arne
 
R

Roedy Green

int reconstitutedBytesRead = 0;
int n;
while((n = cin.read( reconstitutedBytes,
reconstitutedBytesRead, bytesToRead - reconstitutedBytesRead )) > 0) {
reconstitutedBytesRead += n;
}

I suspected as much. I woke up to post my hypothesis that the problem
was that CypherInputStream was behaving like a socket, not giving you
the full number of bytes you requested all at once.

However the problem is you know how many encrypted bytes you have but
not how big the reconstituted message will be. So your patch won't
work.

I have some ideas how to fix it:

1. use a buffered stream and trust it will hide the jerkiness.

2. encode the length of the message in bytes on the front of the
message, decrypt it, then use to do decide how many bytes to read.

3. keep reading until you get 0 bytes or an EOF back.

I am feeling under the weather so I don't have the energy just now to
check them out.

(3) has the disadvantage it does not solve the problem for multiple
messages per file.
 
R

Roedy Green

I suspected as much. I woke up to post my hypothesis that the problem
was that CypherInputStream was behaving like a socket, not giving you
the full number of bytes you requested all at once.

However the problem is you know how many encrypted bytes you have but
not how big the reconstituted message will be. So your patch won't
work.

I have some ideas how to fix it:

1. use a buffered stream and trust it will hide the jerkiness.

2. encode the length of the message in bytes on the front of the
message, decrypt it, then use to do decide how many bytes to read.

3. keep reading until you get 0 bytes or an EOF back.

I am feeling under the weather so I don't have the energy just now to
check them out.

(3) has the disadvantage it does not solve the problem for multiple
messages per file.

I corrected the code. It is posted at
http://mindprod.com/jgloss/jce.html#CIPHER

My solution was to prepend the message with a 2-byte length before
encryption. The length is encrypted too.

That way I know the precise number of bytes to read. When I do that
the socket-like jerkiness goes away, but I put in chunk-reading code
just the same that reads until it gets the bytes expected.

I also flipped it over to AES/CBC which required providing some salt
bits.
 
A

Arne Vajhøj

Roedy said:
I suspected as much. I woke up to post my hypothesis that the problem
was that CypherInputStream was behaving like a socket, not giving you
the full number of bytes you requested all at once.

However the problem is you know how many encrypted bytes you have but
not how big the reconstituted message will be. So your patch won't
work.

My patch work perfectly to the problem you posted.

And the while loop reading until you do not get any bytes
will always work.

If you do not know the size of data then bytesToRead will just
be the size of the buffer (instead of the total size) and you will
need to process the buffer when it is full.
I have some ideas how to fix it:

1. use a buffered stream and trust it will hide the jerkiness.

That will not solve the problem.
2. encode the length of the message in bytes on the front of the
message, decrypt it, then use to do decide how many bytes to read.

That will work. But it is not necessary.
3. keep reading until you get 0 bytes or an EOF back.

That is what I suggested.

Arne
 

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

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,744
Latest member
CortneyMcK

Latest Threads

Top