5

I am trying to consume a web service that uses Password Digest mode, and I have these functions in my Java application to generate a random nonce, creation date and password digest. I can't get past the Authentication Failed error, and the documentation isn't overly clear on whether they want SHA-1 or MD5, as it mentions both in passing. I've tried MD5 instead of SHA-1 and I am getting the same result. I managed to get the requests to work via a test on SoapUI, but I have no idea how that application is generating the digest / nonce. Any help is appreciated.

Here's the code I am using to generate the nonce and the password digest:

    private static SOAPMessage createSOAPRequest() throws Exception 
    {
        String password = "FakePassword";

        String nonce = generateNonce(); 
        System.out.println("Nonce = " + nonce);

        DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date today = Calendar.getInstance().getTime();
        String created = dateFormatter.format(today);
        System.out.println("Created = " + created);

        String passwordDigest = buildPasswordDigest(nonce, created, password);
        System.out.println("Password Digest = " + passwordDigest);
    }

    private static String buildPasswordDigest(String nonce, String created, String password) throws NoSuchAlgorithmException, UnsupportedEncodingException
    {
        MessageDigest sha1;
        String passwordDigest = null;

        try
        {
            sha1 = MessageDigest.getInstance("SHA-1");
            sha1.update(Base64.decodeBase64(nonce));
            sha1.update(created.getBytes("UTF-8"));
            passwordDigest = new String(Base64.encodeBase64(sha1.digest(password.getBytes("UTF-8"))));
            sha1.reset();
        }
        catch (NoSuchAlgorithmException e) 
        {
            e.printStackTrace();
        }

        return passwordDigest;
    }

    private static String generateNonce() throws NoSuchAlgorithmException, NoSuchProviderException, UnsupportedEncodingException
    {
        String dateTimeString = Long.toString(new Date().getTime());
        byte[] nonceByte = dateTimeString.getBytes();
        return Base64.encodeBase64String(nonceByte);
    }
Amy
  • 55
  • 1
  • 1
  • 4
  • Which web service is this for? – F. Stephen Q Sep 04 '15 at 14:47
  • I'm not really at liberty to say - it's confidential... I am gathering from your response here that I should enlist help from their tech team because this kind of thing is not really generic enough to get help for online. But if it was, then why is SoapUI able to do it with no issue? – Amy Sep 04 '15 at 15:33
  • I really can't say; I would talk to their techs. Just to be sure, you're intentionally double-hashing your nonce, correct? And that the nonce you're getting is in milliseconds since epoch? – F. Stephen Q Sep 04 '15 at 15:45
  • Actually no, I wasn't intentionally double hashing... I changed the code a bit - fixing the original post. It still fails to authenticate. I also made sure the date time stamp is in UTC format. – Amy Sep 04 '15 at 19:31
  • It's worth saying that I can get this to function properly with the credentials in SoapUI - however, the password digest being generated is totally different than what I get when I take the nonce value, date time stamp, and unencrypted password concatenated, then run them through an MD5 algorithm. Same for SHA-1 - totally different results. – Amy Sep 04 '15 at 19:37
  • OMG. I got it to work! OMG! This has been driving me absolutely INSANE for 4 days. I changed the sha1.update(nonce.getBytes("UTF-8")); in buildPasswordDigest to sha1.update(Base64.decodeBase64(nonce)); Post something as an answer and I'll give you credit – Amy Sep 04 '15 at 19:43
  • Fantastic! Glad you got it worked out – F. Stephen Q Sep 04 '15 at 19:47
  • You can remove the throws NoSuchAlgorithmException, NoSuchProviderException, UnsupportedEncodingException from your generateNonce method those exceptions will never be thrown – guilhebl Jun 06 '18 at 23:31
  • Worked for me as well today in an implementation of mine. – Ivo Sturm Oct 22 '20 at 14:55

1 Answers1

3

The solution was to replace the line sha1.update(nonce.getBytes("UTF-8")); with sha1.update(Base64.decodeBase64(nonce));

F. Stephen Q
  • 4,208
  • 1
  • 19
  • 42