Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

Perl & Java -- Can they keep a secret?

by Flame (Deacon)
on Nov 17, 2003 at 03:17 UTC ( #307543=perlquestion: print w/replies, xml ) Need Help??
Flame has asked for the wisdom of the Perl Monks concerning the following question:

As the title implies, this question spans two languages, Perl and Java. I have a Perl server with Java clients and I need to find some means of allowing the Java client to securely broadcast a login/pass. (Ref: Ecrypting passwords for the source of a few of these ideas)

I've considered having the whole connection over SSL, but concluded it required too much effort (the server is in POE which I'm still learning about... I don't wanna fiddle with the internals before I have the externals working and well understood.)

I've considered the following also:

The client connects and the server immediately sends a random string of random length between 100 and 1000 chars to the client, which the client is expected to store.

The client then sends the login name in cleartext (to allow for lookup in a database) and the password and random_string combined and encrypted/digested.

The problem with this idea is in the fact that the JCE (Java Cryptography Extension) is highly restricted and I don't want to have to add aditional 'providers'.

The other significant problem is my unfamiliarity with digital cryptography. I have a great deal of knowledge about historical techniques, but this is a whole new ballpark. I notice that HMAC-MD5 seems to exist in both Perl and Java, but now I'm faced with the problem of not realy understanding how they work, and so being unable to understand what they really do, or what restrictions there are. For example, the docs for Digest::HMAC_MD5 state only that you pass the data and a key. The presence of the key suggests that this might be two-way encryption, something I don't think I want.

Overall, I'm open to almost any suggestion, whether it builds off of my current efforts or not.

Description of the server and goals: Persistant connection. Clients connect and log in and kinda sit around for a while. (Game server of sorts.)

Thanks, everyone!

My code doesn't have bugs, it just develops random features.


Replies are listed 'Best First'.
Re: Perl & Java -- Can they keep a secret?
by eduardo (Curate) on Nov 17, 2003 at 03:45 UTC
    Don't discount SSL. Someone has already done this work, don't work harder than you have to. Wrap stunnel around the POE server (is how I always do it) and use JSSE on the client side. I've found no easier way.

      It'll take me a bit to go through stunnel enough to understand how I would use it, but aside from that... Only the password really needs any sort of encryption. I'm concerned that what is probably already a very... inefficient system may be made worse because everything sent in and out would be encrypted.

      As to why I believe my current mechanism is inefficient... well I haven't done anything beyond Apache interaction prior to now and I'm suddenly working with sockets etc... It's not stupidity, it's just learning... heh.

      While I'm here, I might as well put up the method I'm using and ask for input. What I have is essentially a block system which works through the POE::Filter::Block using prepended lengths. (I had another variation on this before, but I like this one better.) Inside the block is a 3 digit number specifying the purpose/type of the message, followed by the message itself.

      In my opinion, it isn't a *bad* system, but it could be better... how I'm not sure yet, hence the learning part.

      Anyway, thanks for the input, if you could show me an example of how you would use stunnel it could make things much simpler, but if not, I'll probably figure it out myself.

      Edit: Refined description of block technique.

      My code doesn't have bugs, it just develops random features.


Re: Perl & Java -- Can they keep a secret?
by etcshadow (Priest) on Nov 17, 2003 at 07:50 UTC
    Do, do, do use SSL. If you actually want this communication to be secure, then any other option is just silly. Well, check that: PGP would also make sense... since you only care that the passwd be encrypted (which is a kind of odd requirement), then you can just PGP the passwd, and send the encrypted block over the connection.

    The point is: this kind of security is hard. Smart people have already put a lot of work into coming up with good, strong, portable solutions (like SSL and PGP), and you should use one of them. If you try to reinvent the wheel here, you will spend far more time and end up with something which is not secure.

    Not an editor command: Wq
      The only reason I have for not encrypting the rest of the data is that I don't feel it's necessary as nothing after the password is confidential. My biggest concern is the extra CPU time required to encrypt the trivial information.

      My code doesn't have bugs, it just develops random features.


Re: Perl & Java -- Can they keep a secret?
by sgifford (Prior) on Nov 17, 2003 at 08:48 UTC

    I think you'd want Digest::MD5 instead, which doesn't take a key.

    MD5 is a cryptographically secure one-way hash function. That means that given some bits as input, it will output some bits that could only have been generated by that input, and it won't be possible to calculate the input by looking at only the output, at least not given less than a few years to calculate.

    The scheme you've proposed is a challenge-response system. It's a fairly standard way of doing this sort of thing, and it's a secure way to do it. The disadvantage is that both sides have to know the plaintext password (as compared to, for example, the server only knowing a hash of the password, like in the /etc/passwd file). It's important to make sure that at least part of the string is truly random, and that it never repeats. You can use Math::TrulyRandom to seed rand, and combine that with the time and PID, to accomplish this:

    use Math::TrulyRandom; my $seed = truly_random_value(); srand($seed); my $randbytes = join("",map {int(rand(10))} (0..16)); my $challenge = join(".",time,$$,$randbytes);

    The way to use the scheme you propose would be to send the challenge string, then the client concatenates the string and the password and takes an MD5 hash:

    use Digest::MD5 qw(md5_base64); $digest = md5_base64($challenge.$password);
    then send this to the server. The server also knows the secret and the password, so it can do the same calculation, and make sure that the hash sent by the client is correct. Since MD5 is a cryptographically secure hash, it's safe to assume that the only way the client could have calculated this hash is by knowing the password, so they're authenticated.

    The big disadvantage of this technique is having to store the plaintext password on the server. Because of this, I nearly always use SSL instead of a challenge-response technique.

      This was originally my entire plan... essentially. The only problem was my inability to locate an equivilant to Digest::MD5 for Java that didn't involve adding other 'providers.' I assume I could look into Digest::MD5::Perl or one of those variants and adapt it to Java, but something about that seems an awful lot like reinventing the wheel.

      Thanks for confirming my faith in my original idea -- perhaps I will try implementing MD5 myself and see what happens.

      My code doesn't have bugs, it just develops random features.


        The only problem was my inability to locate an equivilant to Digest::MD5 for Java that didn't involve adding other 'providers.'

        You don't have to register a new security provider just to use MD5 Digests. Take a look at this method in the MessageDigest class pay particular attention to the "Note: the provider doesn't have to be registered." part.

Re: Perl & Java -- Can they keep a secret?
by hossman (Prior) on Nov 17, 2003 at 08:22 UTC

    If you don't want to use a tunneling protocol for all the data, at least use an established, well tested system for exchanging the passwords.

    Get yourself a Java PGP library to use in the clients, and a PGP perl module for the server. Require a private key in your servers conf file, and the corrisponding public key in your client conf files.

Re: Perl & Java -- Can they keep a secret?
by ptkdb (Monk) on Nov 17, 2003 at 13:10 UTC

    "There's a right way to do it, but it's too much work, so please provide me with an adequate excuse to do it the wrong way."


    Any time you blast a login/password into the clear, you run the risk of it being captured by someone sitting in a server room, or just sitting in another cube with a sniffer, or a freeware program that turns a PC into a sniffer(It uses a feature on most network interface cards called 'promiscuous mode').

    I believe, and anyone who knows differently please correct me if I'm wrong, that one of the features of SSL is that is uses a Secure Key Exchange algorithm. This is a mathamatical 'trick' whereby both you and your 'peer' generate two large random numbers, each transmits one of these numbers to the other, and derives a third number that's the same on both ends, but was never transmitted in the clear. This number becomes the basis for your cipher keys that you then use for the rest of your session.

    Update: Reference to a text that includes Secure Key Exchanges

    Applied Cryptography

      I'm not entirely sure how to take that top part. If you were attempting to describe me... I think I'm insulted, otherwise just confused. As to your concern about broadcasting passwords in the clear... well that's what I'm attempting to avoid. Yes the server and the user both have an unencrypted form, but I don't believe it would be so simple to break into the database and steal it.

      So, overall I'm not entirely sure what your point was, so I guess I'll just file it under an endorsement of SSL.

      My code doesn't have bugs, it just develops random features.


Re: Perl & Java -- Can they keep a secret?
by iburrell (Chaplain) on Nov 17, 2003 at 22:35 UTC
    You might want to check out Authen::SASL. It implements the SASL authentication framework. SASL allows using different authentication methods based on different needs. If Java has SASL support, this would allow you to change the authentication method in the future if needed.

    Alternatively, you could implement one of the more secure authentication methods. The best example are CRAM-MD5 and DIGEST-MD5. They are better than sending the password in the clear and much faster than SSL if you don't need to encrypt the whole connection. They basically involve the server sending a challenge, the client hashing the challenge and password together, and sending back the response.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://307543]
Approved by graff
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (6)
As of 2017-03-24 06:34 GMT
Find Nodes?
    Voting Booth?
    Should Pluto Get Its Planethood Back?

    Results (296 votes). Check out past polls.