Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #38259 > unrolled thread

Re: Why is Java 7 converting the Password toCharArray instead of Byte in it's PBKDF2 function?

Started by"Karl.Frank" <Karl.Frank@Freecx.co.uk>
First post2018-05-15 23:37 +0200
Last post2018-06-20 00:03 +0200
Articles 10 — 4 participants

Back to article view | Back to comp.lang.java.programmer

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: Why is Java 7 converting the Password toCharArray instead of Byte in it's PBKDF2 function? "Karl.Frank" <Karl.Frank@Freecx.co.uk> - 2018-05-15 23:37 +0200
    Re: Why is Java 7 converting the Password toCharArray instead of Byte in it's PBKDF2 function? "Karl.Frank" <Karl.Frank@Freecx.co.uk> - 2018-05-16 15:58 +0200
    Re: Why is Java 7 converting the Password toCharArray instead of Byte in it's PBKDF2 function? Robert Klemme <shortcutter@googlemail.com> - 2018-06-18 18:41 +0200
      Re: Why is Java 7 converting the Password toCharArray instead of Byte in it's PBKDF2 function? "Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid> - 2018-06-18 13:33 -0700
      Re: Why is Java 7 converting the Password toCharArray instead of Byte in it's PBKDF2 function? "Karl.Frank" <Karl.Frank@Freecx.co.uk> - 2018-06-19 12:54 +0200
        Re: Why is Java 7 converting the Password toCharArray instead of Byte in it's PBKDF2 function? Lothar Kimmeringer <news201705@kimmeringer.de> - 2018-06-19 22:18 +0200
          Re: Why is Java 7 converting the Password toCharArray instead of Byte in it's PBKDF2 function? Robert Klemme <shortcutter@googlemail.com> - 2018-06-19 23:20 +0200
          Re: Why is Java 7 converting the Password toCharArray instead of Byte in it's PBKDF2 function? "Karl.Frank" <Karl.Frank@Freecx.co.uk> - 2018-06-19 23:23 +0200
        Re: Why is Java 7 converting the Password toCharArray instead of Byte in it's PBKDF2 function? Robert Klemme <shortcutter@googlemail.com> - 2018-06-19 23:15 +0200
          Re: Why is Java 7 converting the Password toCharArray instead of Byte in it's PBKDF2 function? "Karl.Frank" <Karl.Frank@Freecx.co.uk> - 2018-06-20 00:03 +0200

#38259 — Re: Why is Java 7 converting the Password toCharArray instead of Byte in it's PBKDF2 function?

From"Karl.Frank" <Karl.Frank@Freecx.co.uk>
Date2018-05-15 23:37 +0200
SubjectRe: Why is Java 7 converting the Password toCharArray instead of Byte in it's PBKDF2 function?
Message-ID<pdfjv8$e8s$1@news.albasani.net>
Holy moley! It's a buggy Java Library I'm currently using!!

###

echo $LANG
en_US.UTF-8

echo -n '¥' | xxd -g1
0000000: c2 a5

###

java version "1.6.0_17"
Java(TM) SE Runtime Environment (build 1.6.0_17-b04-248-9M3125)
Java HotSpot(TM) 64-Bit Server VM (build 14.3-b01-101, mixed mode)

echo -n "Lsda[¥~§#€]" | java -jar pbkdf2_stdin.jar "Salt" 4096 16 sha-1
Password   : Lsda[¥~§#€]
Password   : 4c7364615bc2a57ec2a723e282ac5d
Salt       : 53616c74
PBKDF2     : aba223d6679ad1e8101c01bf860f788b
PBKDF2_java: 461f05924a7945a652bcabb30d87fad3

###

java -version
openjdk version "1.7.0-u80-unofficial"
OpenJDK Runtime Environment (build 1.7.0-u80-unofficial-b32)
OpenJDK 64-Bit Server VM (build 24.80-b11, mixed mode)

echo -n "Lsda[¥~§#€]" | java -jar pbkdf2_stdin.jar "Salt" 4096 16 sha-1
Password   : Lsda[¥~§#€]
Password   : 4c7364615bc2a57ec2a723e282ac5d
Salt       : 53616c74
PBKDF2     : aba223d6679ad1e8101c01bf860f788b
PBKDF2_java: aba223d6679ad1e8101c01bf860f788b

###

java -version
java version "1.6.0_41"
OpenJDK Runtime Environment (IcedTea6 1.13.13) (rhel-1.13.13.1.el6_8-x86_64)
OpenJDK 64-Bit Server VM (build 23.41-b41, mixed mode)

echo -n "Lsda[¥~§#€]" | java -jar pbkdf2_stdin.jar "Salt" 4096 16 sha-1
Password   : Lsda[¥~§#€]
Password   : 4c7364615bc2a57ec2a723e282ac5d
Salt       : 53616c74
PBKDF2     : aba223d6679ad1e8101c01bf860f788b
PBKDF2_java: aba223d6679ad1e8101c01bf860f788b

###

openjdk version "1.8.0_171"
OpenJDK Runtime Environment (build 1.8.0_171-b10)
OpenJDK 64-Bit Server VM (build 25.171-b10, mixed mode)

echo -n "Lsda[¥~§#€]" | java -jar pbkdf2_stdin.jar "Salt" 4096 16 sha-1
Password   : Lsda[¥~§#€]
Password   : 4c7364615bc2a57ec2a723e282ac5d
Salt       : 53616c74
PBKDF2     : aba223d6679ad1e8101c01bf860f788b
PBKDF2_java: aba223d6679ad1e8101c01bf860f788b


So my own implementation works correctly - what a relieve!


-- 
cHNiMUBACG0HAAAAAAAAAAAAAABIZVbDdKVM0w1kM9vxQHw+bkLxsY/Z0czY0uv8/Ks6WULxJVua
zjvpoYvtEwDVhP7RGTCBVlzZ+VBWPHg5rqmKWvtzsuVmMSDxAIS6Db6YhtzT+RStzoG9ForBcG8k
G97Q3Jml/aBun8Kyf+XOBHpl5gNW4YqhiM0=

[toc] | [next] | [standalone]


#38260

From"Karl.Frank" <Karl.Frank@Freecx.co.uk>
Date2018-05-16 15:58 +0200
Message-ID<pdhddp$ij$1@news.albasani.net>
In reply to#38259
On 15.05.18 23:37, Karl.Frank wrote:
> Holy moley! It's a buggy Java Library I'm currently using!!
>
> ###
>
> echo $LANG
> en_US.UTF-8
>
> echo -n '¥' | xxd -g1
> 0000000: c2 a5
>
> ###
>
> java version "1.6.0_17"
> Java(TM) SE Runtime Environment (build 1.6.0_17-b04-248-9M3125)
> Java HotSpot(TM) 64-Bit Server VM (build 14.3-b01-101, mixed mode)
>
> echo -n "Lsda[¥~§#€]" | java -jar pbkdf2_stdin.jar "Salt" 4096 16 sha-1
> Password : Lsda[¥~§#€]
> Password : 4c7364615bc2a57ec2a723e282ac5d
> Salt : 53616c74
> PBKDF2 : aba223d6679ad1e8101c01bf860f788b
> PBKDF2_java: 461f05924a7945a652bcabb30d87fad3
>

For God sake, all files encrypted by the application based on the buggy
Java version have a wrong encryption and MAC key now. So I can't
simply update the old application as expected. I can't believe how such
a Java version could ever being published at all!

A conclusion might be implementing all crypto primitives needed by a
certain program from scratch and run intense vector and other useful
tests in order to avoid such a mess in the future by any potential buggy
Java update.

I'm really pissed. :-(


-- 
cHNiMUBACG0HAAAAAAAAAAAAAABIZVbDdKVM0w1kM9vxQHw+bkLxsY/Z0czY0uv8/Ks6WULxJVua
zjvpoYvtEwDVhP7RGTCBVlzZ+VBWPHg5rqmKWvtzsuVmMSDxAIS6Db6YhtzT+RStzoG9ForBcG8k
G97Q3Jml/aBun8Kyf+XOBHpl5gNW4YqhiM0=

[toc] | [prev] | [next] | [standalone]


#38388

FromRobert Klemme <shortcutter@googlemail.com>
Date2018-06-18 18:41 +0200
Message-ID<foq5mlF5sm0U1@mid.individual.net>
In reply to#38259
On 15.05.2018 23:37, Karl.Frank wrote:
> Holy moley! It's a buggy Java Library I'm currently using!!

You are converting a byte array to a String without explicit mention of 
the encoding.  Maybe the way Java picks up the default encoding has 
changed between versions.  Anyway, this is an unsafe practice.

Also, you are reading only once, there is the chance that there is still 
data in the pipe which you will miss.  Even worse, depending on how data 
is written to stdin you might even get different results.  This might 
not be an issue for your test program, but could be if you use this code 
in production.

Btw. I find your habit of using names beginning with an uppercase letter 
for variables confusing.  Conventionally these are reserved for classes 
and interfaces.

> So my own implementation works correctly - what a relieve!

There are cases where wrong code emits correct results - and this 
surfaces only later, when the input or some other environmental factor 
changes.

Regards

	robert


-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

[toc] | [prev] | [next] | [standalone]


#38389

From"Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid>
Date2018-06-18 13:33 -0700
Message-ID<pg94u2$o2q$1@dont-email.me>
In reply to#38388
On 6/18/2018 9:41 AM, Robert Klemme wrote:
> On 15.05.2018 23:37, Karl.Frank wrote:
>> Holy moley! It's a buggy Java Library I'm currently using!!
> 
> You are converting a byte array to a String without explicit mention of 
> the encoding.  Maybe the way Java picks up the default encoding has 
> changed between versions.  Anyway, this is an unsafe practice.
[...]

Yup. For instance, I had to alter my Python test vector to use 
bytearrays without default encoding in order for it go get in perfect 
sync with a C analog.

https://groups.google.com/forum/#!original/sci.crypt/2K33_4GjkVs/Ws6bWE-aAQAJ
(read all for context...)

The C code:

https://pastebin.com/raw/feUnA3kP

The Python Test vector:

https://pastebin.com/raw/NAnsBJAZ

Notice the following code in the Python version:
___________________________________
if (M == False):
     U = bytearray([P_byte, C_I_P]);
     H.update(U);
else:
     U = bytearray([C_I_P, P_byte]);
     H.update(U);
___________________________________

Here is the equivalent C code in the ct_crypt_round function:
___________________________________
if (M == 0)
{
     unsigned char update[2] = {
         P_byte, C_byte
     };

     hmac_sha256_update(&H, update, 2);
}

else
{
     unsigned char update[2] = {
         C_byte, P_byte
     };

     hmac_sha256_update(&H, update, 2);
}
___________________________________


Now, there is a way to get a different result in the Python test 
vector... Use the default encoding! Afaict, it can change on different 
impls. Example:
___________________________________
if (M == False):
     H.update(P.bytes[I_P].encode());
     H.update(chr(C_I_P).encode());
else:
     H.update(chr(C_I_P).encode());
     H.update(P.bytes[I_P].encode());
___________________________________

NO! This is unsafe. I need to correct my code in my paper:

http://funwithfractals.atspace.cc/ct_cipher/

that uses the .encode() function to the one that uses bytearrays. Damn 
it.. Sorry!

I had a weary feeling about using default encoding, but finally verified 
it when I worked on getting the C version and Python test vector in 
perfect sync. Please keep in mind that one needs to define 
PYTHON_TEST_VECTOR in my C code to sync it up with the Python test vector.

[toc] | [prev] | [next] | [standalone]


#38390

From"Karl.Frank" <Karl.Frank@Freecx.co.uk>
Date2018-06-19 12:54 +0200
Message-ID<pgandc$d8a$1@news.albasani.net>
In reply to#38388
On 18.06.18 18:41, Robert Klemme wrote:
> On 15.05.2018 23:37, Karl.Frank wrote:
>> Holy moley! It's a buggy Java Library I'm currently using!!
>
> You are converting a byte array to a String without explicit mention of
> the encoding. Maybe the way Java picks up the default encoding has
> changed between versions. Anyway, this is an unsafe practice.
>
Robert, probably that might be the case.

In regards of cryptography I always tend to stay on the byte level. This
way my own implementation of HMAC and PBKDF2 has no need to bother with
string encoding when reading in from stdin or files. Curiously Java's
PBKDF2 expect a string or char array rather than a byte array and
therefore I need the extra conversion. Actually from now on my own
functions will be used instead.

It might be a different matter if the user type in password and/or salt
in some GUI. In this case however I would define the kind of strings
accepted and later convert them into byte arrays before processing them
further.


> Also, you are reading only once, there is the chance that there is still
> data in the pipe which you will miss. Even worse, depending on how data
> is written to stdin you might even get different results. This might not
> be an issue for your test program, but could be if you use this code in
> production.
>
Well, yes I read only once from stdin and store the result in a byte
array. How do you suppose to read twice?

The amount of byte to read is exactly defined by

   int BuffSize = System.in.available();
   byte[] pwByte = new byte[BuffSize];
   System.in.read(pwByte, 0, BuffSize);

How would the program read more byte than necessary?

As data on stdin is always byte and all my programs read in byte and
never ever strings in my opinion it doesn't matter how these byte are
written and piped by any previous instance or program.


> Btw. I find your habit of using names beginning with an uppercase letter
> for variables confusing. Conventionally these are reserved for classes
> and interfaces.
>
Yeah, it's old habit. Manly because I do not program much in Java
actually. What I do is translating my important crypto functions for
example into Java or Python in order to check that they will produce the
exact same results and comply with given test vectors.


>> So my own implementation works correctly - what a relieve!
>
> There are cases where wrong code emits correct results - and this
> surfaces only later, when the input or some other environmental factor
> changes.
>
That's one reason why I tend to run large and extensive tests before my
program go into a production environment. Until today I've never
experienced any real problem. Even in this case I'd implement my own
HMAC and PBKDF2 and therefore found the "buggy" Java lib. Sadly the
developer of the original program some years ago didn't check that and
now everyone is baffled that we can't decrypt old files with the
correctly working PBKDF2 implementation.


> Regards
>
> robert
>
>
Cheers,
Karl



-- 
cHNiMUBACG0HAAAAAAAAAAAAAABIZVbDdKVM0w1kM9vxQHw+bkLxsY/Z0czY0uv8/Ks6WULxJVua
zjvpoYvtEwDVhP7RGTCBVlzZ+VBWPHg5rqmKWvtzsuVmMSDxAIS6Db6YhtzT+RStzoG9ForBcG8k
G97Q3Jml/aBun8Kyf+XOBHpl5gNW4YqhiM0=

[toc] | [prev] | [next] | [standalone]


#38392

FromLothar Kimmeringer <news201705@kimmeringer.de>
Date2018-06-19 22:18 +0200
Message-ID<dlr1lb3za2zh.dlg@kimmeringer.de>
In reply to#38390
Karl.Frank wrote:

> The amount of byte to read is exactly defined by
> 
>    int BuffSize = System.in.available();
>    byte[] pwByte = new byte[BuffSize];
>    System.in.read(pwByte, 0, BuffSize);
> 
> How would the program read more byte than necessary?

InputStream.available only returns the number of bytes that
can be read without blocking. Dependent on how the data ends
up there there still might be data left to read that you
missed because of that.

What you're doing here is a common programming error.


Cheers, Lothar
-- 
Lothar Kimmeringer                E-Mail: spamfang@kimmeringer.de
               PGP-encrypted mails preferred (Key-ID: 0x8BC3CD81)

Always remember: The answer is forty-two, there can only be wrong
                 questions!

[toc] | [prev] | [next] | [standalone]


#38394

FromRobert Klemme <shortcutter@googlemail.com>
Date2018-06-19 23:20 +0200
Message-ID<fotac7Foc74U2@mid.individual.net>
In reply to#38392
On 19.06.2018 22:18, Lothar Kimmeringer wrote:
> Karl.Frank wrote:
> 
>> The amount of byte to read is exactly defined by
>>
>>     int BuffSize = System.in.available();
>>     byte[] pwByte = new byte[BuffSize];
>>     System.in.read(pwByte, 0, BuffSize);
>>
>> How would the program read more byte than necessary?
> 
> InputStream.available only returns the number of bytes that
> can be read without blocking.

It returns an _estimate_ of that number.  A conforming implementation is 
even allowed to sometimes or always return 0.  And in fact this is what 
InputStream's own implementation does.

> Dependent on how the data ends
> up there there still might be data left to read that you
> missed because of that.
> 
> What you're doing here is a common programming error.

I hope not, but may be.

Cheers

	robert

-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

[toc] | [prev] | [next] | [standalone]


#38395

From"Karl.Frank" <Karl.Frank@Freecx.co.uk>
Date2018-06-19 23:23 +0200
Message-ID<pgbs7u$iff$1@news.albasani.net>
In reply to#38392
On 19.06.18 22:18, Lothar Kimmeringer wrote:
> Karl.Frank wrote:
>
>> The amount of byte to read is exactly defined by
>>
>>     int BuffSize = System.in.available();
>>     byte[] pwByte = new byte[BuffSize];
>>     System.in.read(pwByte, 0, BuffSize);
>>
>> How would the program read more byte than necessary?
>
> InputStream.available only returns the number of bytes that
> can be read without blocking. Dependent on how the data ends
> up there there still might be data left to read that you
> missed because of that.
>
> What you're doing here is a common programming error.
>
>
> Cheers, Lothar

Well, well, well. The posted listing is just a short test program in
order to figure out why the results of the Java function were wrong.
It clearly does not expext a huge file being passed over by stdin.

Obviously in a program that need to handle large scale data one would
read in the data byte in chunks and process them subsequently like in
this short snipped


---------------------------------------8<----------

   int BuffSize = 8192;

   byte[] inByte  = new byte[BuffSize];
   byte[] outByte = new byte[BuffSize];

   int inB, outB, bufferRead;

   System.in.flush();
   System.out.flush();

   while ((bufferRead = System.in.read(inByte, 0, BuffSize)) != -1) {
     for (int i=0; i<bufferRead; i++){
       /*
         do something useful here
         for example XOR the byte

         inB  = (int)inByte[i];
         outB = (inB ^ *some CSPRNG byte output*) & 0xff;
         outByte[i] = (byte)outB;

         or similar...
       */
     }
     System.out.write(outByte, 0, bufferRead);
   }

   System.in.flush();
   System.out.flush();

   System.in.close();
   System.out.close();

--------------------------------------->8----------

So nothing to be worried about in regards of any unprocessed data left ;-)

Cheers,
Karl


-- 
cHNiMUBACG0HAAAAAAAAAAAAAABIZVbDdKVM0w1kM9vxQHw+bkLxsY/Z0czY0uv8/Ks6WULxJVua
zjvpoYvtEwDVhP7RGTCBVlzZ+VBWPHg5rqmKWvtzsuVmMSDxAIS6Db6YhtzT+RStzoG9ForBcG8k
G97Q3Jml/aBun8Kyf+XOBHpl5gNW4YqhiM0=

[toc] | [prev] | [next] | [standalone]


#38393

FromRobert Klemme <shortcutter@googlemail.com>
Date2018-06-19 23:15 +0200
Message-ID<fota35Foc74U1@mid.individual.net>
In reply to#38390
On 19.06.2018 12:54, Karl.Frank wrote:
> On 18.06.18 18:41, Robert Klemme wrote:
>> On 15.05.2018 23:37, Karl.Frank wrote:
>>> Holy moley! It's a buggy Java Library I'm currently using!!
>>
>> You are converting a byte array to a String without explicit mention of
>> the encoding. Maybe the way Java picks up the default encoding has
>> changed between versions. Anyway, this is an unsafe practice.
>>
> Robert, probably that might be the case.

It is, it is.

> In regards of cryptography I always tend to stay on the byte level. This
> way my own implementation of HMAC and PBKDF2 has no need to bother with
> string encoding when reading in from stdin or files. Curiously Java's
> PBKDF2 expect a string or char array rather than a byte array and
> therefore I need the extra conversion. Actually from now on my own
> functions will be used instead.

The point is not your usage of byte array nor your need for a 
conversion.  The point is that your conversion is unsafe because the 
default encoding is used implicitly instead of making your choice of 
encoding explicit.  There are various factors that might influence the 
JVM's choice of default encoding and they might not be the same as 
govern the encoding of the user input (what you send via echo).  This is 
a source of errors and the bad thing is it might actually work in one 
environment - but not in others.  Such bugs can go unnoticed for a long 
time before they hit you.  And then you're left with wrongly encoded 
data which can be very painful.

> It might be a different matter if the user type in password and/or salt
> in some GUI. In this case however I would define the kind of strings
> accepted and later convert them into byte arrays before processing them
> further.

Graphical inputs usually emit String, char[] or CharSequence so you can 
be sure the input is properly encoded (modulo some issues) and you can 
pick whatever encoding you want for the transformation into bytes.

>> Also, you are reading only once, there is the chance that there is still
>> data in the pipe which you will miss. Even worse, depending on how data
>> is written to stdin you might even get different results. This might not
>> be an issue for your test program, but could be if you use this code in
>> production.
>>
> Well, yes I read only once from stdin and store the result in a byte
> array. How do you suppose to read twice?
> 
> The amount of byte to read is exactly defined by
> 
>    int BuffSize = System.in.available();
>    byte[] pwByte = new byte[BuffSize];
>    System.in.read(pwByte, 0, BuffSize);
> 
> How would the program read more byte than necessary?

Please read carefully: I wrote it might read _less_ bytes.  You should 
really read the JavaDocs of InputStream#available().  For example it is 
perfectly legal for an implementation to always return 0 yet still yield 
data via read().  Basically, available() is quite useless most of the 
time if you want to read the complete input anyway.

> As data on stdin is always byte and all my programs read in byte and
> never ever strings in my opinion it doesn't matter how these byte are
> written and piped by any previous instance or program.

Again, the point is a different one: your reading does not ensure you 
get the complete input.  For this you need a loop that reads until EOF. 
Using just a single read() is not sufficient as an implementation is 
free to choose how many bytes to return for a single read().

There is no way you can get away without a loop.

final byte[] buffer = new byte[1024];
final ByteArrayOutputStream out = new ByteArrayOutputStream();

for (int len; (len = in.read(buffer)) != -1;) {
     out.write(buffer, 0, len);
}

byte[] data = out.toByteArray();

There are other more elegant variants depending on which libs you use 
and on which Java version you are.

>>> So my own implementation works correctly - what a relieve!
>>
>> There are cases where wrong code emits correct results - and this
>> surfaces only later, when the input or some other environmental factor
>> changes.
>>
> That's one reason why I tend to run large and extensive tests before my
> program go into a production environment. Until today I've never
> experienced any real problem. Even in this case I'd implement my own
> HMAC and PBKDF2 and therefore found the "buggy" Java lib. Sadly the
> developer of the original program some years ago didn't check that and
> now everyone is baffled that we can't decrypt old files with the
> correctly working PBKDF2 implementation.

I am not convinced you have identified a "'buggy' Java lib".

Kind regards

	robert

-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

[toc] | [prev] | [next] | [standalone]


#38396

From"Karl.Frank" <Karl.Frank@Freecx.co.uk>
Date2018-06-20 00:03 +0200
Message-ID<pgbujt$eef$1@news.albasani.net>
In reply to#38393
On 19.06.18 23:15, Robert Klemme wrote:
> On 19.06.2018 12:54, Karl.Frank wrote:
>> On 18.06.18 18:41, Robert Klemme wrote:
>>> On 15.05.2018 23:37, Karl.Frank wrote:
>>>> Holy moley! It's a buggy Java Library I'm currently using!!
>>>
>>> You are converting a byte array to a String without explicit mention of
>>> the encoding. Maybe the way Java picks up the default encoding has
>>> changed between versions. Anyway, this is an unsafe practice.
>>>
>> Robert, probably that might be the case.
>
> It is, it is.
>
>> In regards of cryptography I always tend to stay on the byte level. This
>> way my own implementation of HMAC and PBKDF2 has no need to bother with
>> string encoding when reading in from stdin or files. Curiously Java's
>> PBKDF2 expect a string or char array rather than a byte array and
>> therefore I need the extra conversion. Actually from now on my own
>> functions will be used instead.
>
> The point is not your usage of byte array nor your need for a
> conversion. The point is that your conversion is unsafe because the
> default encoding is used implicitly instead of making your choice of
> encoding explicit. There are various factors that might influence the
> JVM's choice of default encoding and they might not be the same as
> govern the encoding of the user input (what you send via echo). This is
> a source of errors and the bad thing is it might actually work in one
> environment - but not in others. Such bugs can go unnoticed for a long
> time before they hit you. And then you're left with wrongly encoded data
> which can be very painful.
>
Whatever comes in from stdin has to be handled and converted by the
piping program as the reading program normally does expect byte - so is
my understanding and experience in the past with C, Python and other
languages.

In fact my test program get the byte properly from stdin because they
are converted by the piping program - in case of the example by "echo".

Due to the fact that the PBKDF2 function of Java expect a string which
has to be converted to a char array for the password (but a byte array
for the salt) I need to convert the byte array first. Unclear for me
however why the mixup of char array and byte array is necessary here.
But to be honest, I'm not really keen to dig deeper because my own
implementations are working properly.


   public static String byteArrToString(byte[] byteArr) {
     String bs = new String(byteArr);

     return bs;
   }

   Password = byteArrToString(pwByte);

And here it comes:

certainly I do *not* know in advance what kind of string conversion to 
choose in the byteArrToString() function simply because I do not know 
what kind of data the piping program might pass over.

For that reason I'll *always* read in byte and never ever anything else, 
because one thing I can be sure, the piped data will be byte. So never 
ever read in data as strings or what ever else crude format they might be.


>> It might be a different matter if the user type in password and/or salt
>> in some GUI. In this case however I would define the kind of strings
>> accepted and later convert them into byte arrays before processing them
>> further.
>
> Graphical inputs usually emit String, char[] or CharSequence so you can
> be sure the input is properly encoded (modulo some issues) and you can
> pick whatever encoding you want for the transformation into bytes.
>
That's what I prefer. If I'd had to read in user typed data I define the 
encoding in the GUI forms input field.


>>> Also, you are reading only once, there is the chance that there is still
>>> data in the pipe which you will miss. Even worse, depending on how data
>>> is written to stdin you might even get different results. This might not
>>> be an issue for your test program, but could be if you use this code in
>>> production.
>>>
>> Well, yes I read only once from stdin and store the result in a byte
>> array. How do you suppose to read twice?
>>
>> The amount of byte to read is exactly defined by
>>
>>   int BuffSize = System.in.available();
>>   byte[] pwByte = new byte[BuffSize];
>>   System.in.read(pwByte, 0, BuffSize);
>>
>> How would the program read more byte than necessary?
>
> Please read carefully: I wrote it might read _less_ bytes. You should
> really read the JavaDocs of InputStream#available(). For example it is
> perfectly legal for an implementation to always return 0 yet still yield
> data via read(). Basically, available() is quite useless most of the
> time if you want to read the complete input anyway.
>
Right, missed that. Explained that in another answer in this thread
already. In case of the test program it seems fairly sufficient to use
System.in.available().


>> As data on stdin is always byte and all my programs read in byte and
>> never ever strings in my opinion it doesn't matter how these byte are
>> written and piped by any previous instance or program.
>
> Again, the point is a different one: your reading does not ensure you
> get the complete input. For this you need a loop that reads until EOF.
> Using just a single read() is not sufficient as an implementation is
> free to choose how many bytes to return for a single read().
>
> There is no way you can get away without a loop.
>
> final byte[] buffer = new byte[1024];
> final ByteArrayOutputStream out = new ByteArrayOutputStream();
>
> for (int len; (len = in.read(buffer)) != -1;) {
> out.write(buffer, 0, len);
> }
>
> byte[] data = out.toByteArray();
>
> There are other more elegant variants depending on which libs you use
> and on which Java version you are.
>
To be honest again, all these different versions and libs coming with
Java are a real pain in the ass. And exactly these incompatibilities are
the reason why I try to rely as much as possible only on the bare
minimum of Java's inherent commands and implement critical functions on
my own in pure Java.


>>>> So my own implementation works correctly - what a relieve!
>>>
>>> There are cases where wrong code emits correct results - and this
>>> surfaces only later, when the input or some other environmental factor
>>> changes.
>>>
>> That's one reason why I tend to run large and extensive tests before my
>> program go into a production environment. Until today I've never
>> experienced any real problem. Even in this case I'd implement my own
>> HMAC and PBKDF2 and therefore found the "buggy" Java lib. Sadly the
>> developer of the original program some years ago didn't check that and
>> now everyone is baffled that we can't decrypt old files with the
>> correctly working PBKDF2 implementation.
>
> I am not convinced you have identified a "'buggy' Java lib".
>
Well, I am.

> Kind regards
>
> robert
>

Cheers,
Karl


-- 
cHNiMUBACG0HAAAAAAAAAAAAAABIZVbDdKVM0w1kM9vxQHw+bkLxsY/Z0czY0uv8/Ks6WULxJVua
zjvpoYvtEwDVhP7RGTCBVlzZ+VBWPHg5rqmKWvtzsuVmMSDxAIS6Db6YhtzT+RStzoG9ForBcG8k
G97Q3Jml/aBun8Kyf+XOBHpl5gNW4YqhiM0=

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.java.programmer


csiph-web