3

I'm build an application with a client/server infrastructure and would like to implement an authentication mechanism using the public/private key method.

Let's assume that a client owns the private key and the server only has the public key. During authentication the client signs a message with the private key, sends it to the server where it's validated with the public key. If validation succeeds the client is authenticated.

Here's some JUnit test code where I made myself familiar with the concepts:

@Test
public void testSignature() throws Exception {
    final String message = "Hello world is a stupid message to be signed";

    final KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();

    final Signature privSig = Signature.getInstance("SHA1withRSA");

    privSig.initSign(keyPair.getPrivate());
    privSig.update(message.getBytes());

    byte[] signature = privSig.sign();

    final Signature pubSig = Signature.getInstance("SHA1withRSA");

    pubSig.initVerify(keyPair.getPublic());
    pubSig.update(message.getBytes());

    assertTrue(pubSig.verify(signature));
}

Of course in order for this to work both server and clients must be in possession of the plain message (digest).

Now my question is: What is a good message (digest) to be used for the signature? For example can this be a static, hardcoded string (which is used for all clients) or would this impose some kind of security issue on this concept? If a static string is bad would it be a good idea to negotiate some random string before authentication? This random string could be used as a "session" key for example and invalidated after some time.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
Sven Jacobs
  • 6,278
  • 5
  • 33
  • 39
  • 2
    Is there a reason that you don't want to use a standard SSL/TLS handshake using client certificates? – stinkymatt Apr 23 '12 at 21:26
  • No reason. I'm evaluating different options right now. However I also want to use the private keys for encryption. Clients with same keys (same user) should be able to send/receive encrypted messages without the server being able to decode them. – Sven Jacobs Apr 23 '12 at 21:44
  • If you don't mind pulling in the kitchen sink, you could try using SOAP which supports intermediaries (such as your server appears to be), and allows message-level authentication and encryption. http://www.ibm.com/developerworks/webservices/library/ws-soapbase/ – artbristol Apr 24 '12 at 07:40
  • I am still in the process of understanding how signing works. Can somebody please explain to me how I don't see any "Certificates" here? From what I read, you need to sign a message using a certificate and private key (certificate required to verify the sender). Is "Signature" (byte[]) the certificate here? – Ravindranath Akila Mar 25 '14 at 06:09

1 Answers1

3

The static String would be bad since its susceptible to a repeat attack (The signed string would be the same every time).

Although, you seem to be reinventing what has been done before. Using certificates is the trusted way. See this example for more info on it: Java HTTPS client certificate authentication

If you want to implement it yourself you'll probably need to read up on how SSL works and mimic that. Any other solution is likely to have some flaws in it, unless it was very bespoke (e.g. your client would keep a list of 1000's of shared static strings which it never reused, and the server had that same list and kept track of what had been used. or alternatively, keep track of a shared number which increments, as suggested in the comments below.)

Community
  • 1
  • 1
Bruce Lowe
  • 6,063
  • 1
  • 36
  • 47
  • The simple variant to get around the replay issue is to just use a large number that increments each time authentication happens. Then client/server only need to keep the last one used. – TJD Apr 23 '12 at 22:01
  • I'm usually trying to not reinvent the wheel :) Client/server communicate over a HTTP REST API. Server is going to be a WAR file which will be deployed to an application server. So I can't assume that HTTPS is enabled for the application server since it's out of my control. What do you recommend? – Sven Jacobs Apr 24 '12 at 05:29
  • That is true TJD. That would be a pretty simple idea instead of lots if strings. – Bruce Lowe Apr 24 '12 at 06:45
  • How would a shared number work with multiple clients? But I think I have an idea: Every clients gets a unique ID assigned by the server during creation. So the UUID is known to the client and server. Couldn't I just use this UUID as the message for digest authentication? – Sven Jacobs Apr 24 '12 at 07:38
  • each client may have an ID e.g. "Client1" and have a number e.g. 1. The server needs to store Client1 -> 1, Client2 -> 1 etc. When Client 1 authenticates with the server it says, I'm Client1 and I'm authenticating now, it uses the number 1. Server then gets the message knows that 1 is meant to be sent. Once authentication is successful it bumps client 1's number up so now Client1 -> 2, Client2 -> 1. Client 1 needs to bump its internal number up too so it knows next time to send 2. And so on. That's the basic principal, what you start with could be random but must be known on both sides – Bruce Lowe Apr 24 '12 at 10:59