diff options
author | Tarun Gupta <tarun1995gupta@gmail.com> | 2015-07-22 22:21:20 (GMT) |
---|---|---|
committer | Nick Hudson <nick.hudson@isode.com> | 2015-08-03 14:06:04 (GMT) |
commit | af3bb03053b9d83f4d38b31d66b292792206a327 (patch) | |
tree | 0e5826f6b1fbb638d899ee6aadca902a7c2fdb18 /src/com/isode/stroke/sasl/DIGESTMD5ClientAuthenticator.java | |
parent | 32ef37b9059e21de19209a9a1ab4ef2564051918 (diff) | |
download | stroke-af3bb03053b9d83f4d38b31d66b292792206a327.zip stroke-af3bb03053b9d83f4d38b31d66b292792206a327.tar.bz2 |
Make SASL equivalent with Swiften.
Adds DIGESTMD5ClientAuthenticator, DIGESTMD5Properties, ExternalClientAuthenticator, PLAINMessage.
Updates Client, ClientSession, CoreClient, ConnectDisconnect, StrokeGUI to reflect changes made in SASL.
Updates ClientAuthenticator, SCRAMSHA1ClientAuthenticator, PBKDF2.
License:
This patch is BSD-licensed, see Documentation/Licenses/BSD-simplified.txt for details.
Test-Information:
Added tests for DIGESTMD5ClientAuthenticator, DIGESTMD5Properties, PLAINClientAuthenticator, PLAINMessage.
Update test for SCRAMSHA1ClientAuthenticatorTest.
All tests pass.
Change-Id: I4fd38f922cab7e4c4548d9706f6ad3b9e1506e81
Diffstat (limited to 'src/com/isode/stroke/sasl/DIGESTMD5ClientAuthenticator.java')
-rw-r--r-- | src/com/isode/stroke/sasl/DIGESTMD5ClientAuthenticator.java | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/src/com/isode/stroke/sasl/DIGESTMD5ClientAuthenticator.java b/src/com/isode/stroke/sasl/DIGESTMD5ClientAuthenticator.java new file mode 100644 index 0000000..639c353 --- /dev/null +++ b/src/com/isode/stroke/sasl/DIGESTMD5ClientAuthenticator.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2010-2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +/* + * Copyright (c) 2015 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +package com.isode.stroke.sasl; + +import com.isode.stroke.sasl.ClientAuthenticator; +import com.isode.stroke.sasl.DIGESTMD5Properties; +import com.isode.stroke.crypto.CryptoProvider; +import com.isode.stroke.base.SafeByteArray; +import com.isode.stroke.base.ByteArray; +import com.isode.stroke.stringcodecs.Hexify; + +public class DIGESTMD5ClientAuthenticator extends ClientAuthenticator { + + private enum Step { + Initial, + Response, + Final + }; + private Step step; + private String host = ""; + private String cnonce = ""; + private CryptoProvider crypto; + private DIGESTMD5Properties challenge = new DIGESTMD5Properties(); + + public DIGESTMD5ClientAuthenticator(final String host, final String nonce, CryptoProvider crypto) { + super("DIGEST-MD5"); + this.step = Step.Initial; + this.host = host; + this.cnonce = nonce; + this.crypto = crypto; + } + + public SafeByteArray getResponse() { + if (Step.Initial.equals(step)) { + return null; + } + else if (Step.Response.equals(step)) { + String realm = ""; + if (challenge.getValue("realm") != null) { + realm = challenge.getValue("realm"); + } + String qop = "auth"; + String digestURI = "xmpp/" + host; + String nc = "00000001"; + + ByteArray A11 = crypto.getMD5Hash(new SafeByteArray().append(getAuthenticationID()).append(":").append(realm).append(":").append(getPassword())); + ByteArray A12 = new ByteArray().append(":").append(challenge.getValue("nonce")).append(":").append(cnonce); + // Compute the response value + ByteArray A1 = A11.append(A12); + if (!getAuthorizationID().isEmpty()) { + A1.append(new ByteArray(":" + getAuthenticationID())); + } + ByteArray A2 = new ByteArray("AUTHENTICATE:" + digestURI); + + String responseValue = Hexify.hexify(crypto.getMD5Hash(new ByteArray( + Hexify.hexify(crypto.getMD5Hash(A1)) + ":" + + challenge.getValue("nonce") + ":" + nc + ":" + cnonce + ":" + qop + ":" + + Hexify.hexify(crypto.getMD5Hash(A2))))); + + + DIGESTMD5Properties response = new DIGESTMD5Properties(); + response.setValue("username", getAuthenticationID()); + if (!realm.isEmpty()) { + response.setValue("realm", realm); + } + response.setValue("nonce", challenge.getValue("nonce")); + response.setValue("cnonce", cnonce); + response.setValue("nc", "00000001"); + response.setValue("qop", qop); + response.setValue("digest-uri", digestURI); + response.setValue("charset", "utf-8"); + response.setValue("response", responseValue); + if (!getAuthorizationID().isEmpty()) { + response.setValue("authzid", getAuthorizationID()); + } + return new SafeByteArray(response.serialize()); + } + else { + return null; + } + } + + public boolean setChallenge(final ByteArray challengeData) { + if (Step.Initial.equals(step)) { + if (challengeData == null) { + return false; + } + challenge = DIGESTMD5Properties.parse(challengeData); + + // Sanity checks + if (challenge.getValue("nonce") == null) { + return false; + } + if (challenge.getValue("charset") ==null || !(challenge.getValue("charset").equals("utf-8"))) { + return false; + } + step = Step.Response; + return true; + } + else { + step = Step.Final; + // TODO: Check RSPAuth + return true; + } + } +}
\ No newline at end of file |