summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTarun Gupta <tarun1995gupta@gmail.com>2015-07-22 22:21:20 (GMT)
committerNick Hudson <nick.hudson@isode.com>2015-08-03 14:06:04 (GMT)
commitaf3bb03053b9d83f4d38b31d66b292792206a327 (patch)
tree0e5826f6b1fbb638d899ee6aadca902a7c2fdb18
parent32ef37b9059e21de19209a9a1ab4ef2564051918 (diff)
downloadstroke-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
-rw-r--r--src/com/isode/stroke/client/Client.java5
-rw-r--r--src/com/isode/stroke/client/ClientSession.java10
-rw-r--r--src/com/isode/stroke/client/CoreClient.java4
-rw-r--r--src/com/isode/stroke/examples/ConnectDisconnect.java3
-rw-r--r--src/com/isode/stroke/examples/gui/StrokeGUI.java2
-rw-r--r--src/com/isode/stroke/sasl/ClientAuthenticator.java8
-rw-r--r--src/com/isode/stroke/sasl/DIGESTMD5ClientAuthenticator.java115
-rw-r--r--src/com/isode/stroke/sasl/DIGESTMD5Properties.java146
-rw-r--r--src/com/isode/stroke/sasl/EXTERNALClientAuthenticator.java38
-rw-r--r--src/com/isode/stroke/sasl/PLAINMessage.java75
-rw-r--r--src/com/isode/stroke/sasl/SCRAMSHA1ClientAuthenticator.java40
-rw-r--r--src/com/isode/stroke/stringcodecs/PBKDF2.java8
-rw-r--r--test/com/isode/stroke/pubsub/Client.java2
-rw-r--r--test/com/isode/stroke/pubsub/TestMain.java5
-rw-r--r--test/com/isode/stroke/sasl/DIGESTMD5ClientAuthenticatorTest.java72
-rw-r--r--test/com/isode/stroke/sasl/DIGESTMD5PropertiesTest.java60
-rw-r--r--test/com/isode/stroke/sasl/PLAINClientAuthenticatorTest.java43
-rw-r--r--test/com/isode/stroke/sasl/PLAINMessageTest.java69
-rw-r--r--test/com/isode/stroke/sasl/SCRAMSHA1ClientAuthenticatorTest.java107
19 files changed, 732 insertions, 80 deletions
diff --git a/src/com/isode/stroke/client/Client.java b/src/com/isode/stroke/client/Client.java
index 6938225..1d137c5 100644
--- a/src/com/isode/stroke/client/Client.java
+++ b/src/com/isode/stroke/client/Client.java
@@ -28,6 +28,7 @@ import com.isode.stroke.roster.XMPPRosterController;
import com.isode.stroke.roster.XMPPRosterImpl;
import com.isode.stroke.signals.Signal1;
import com.isode.stroke.vcards.VCardManager;
+import com.isode.stroke.base.SafeByteArray;
/**
* Provides the core functionality for writing XMPP client software.
@@ -76,7 +77,7 @@ public class Client extends CoreClient {
* @param networkFactories An implementation of network interaction, must
* not be null.
*/
- public Client(final JID jid, final String password, final NetworkFactories networkFactories, Storages storages) {
+ public Client(final JID jid, final SafeByteArray password, final NetworkFactories networkFactories, Storages storages) {
super(jid, password, networkFactories);
this.storages = storages;
@@ -111,7 +112,7 @@ public class Client extends CoreClient {
pubSubManager = new PubSubManagerImpl(getStanzaChannel(), getIQRouter());
}
- public Client(final JID jid, final String password, final NetworkFactories networkFactories) {
+ public Client(final JID jid, final SafeByteArray password, final NetworkFactories networkFactories) {
this(jid, password, networkFactories, null);
}
diff --git a/src/com/isode/stroke/client/ClientSession.java b/src/com/isode/stroke/client/ClientSession.java
index 7654630..fe9481d 100644
--- a/src/com/isode/stroke/client/ClientSession.java
+++ b/src/com/isode/stroke/client/ClientSession.java
@@ -50,6 +50,10 @@ import com.isode.stroke.tls.Certificate;
import com.isode.stroke.tls.CertificateTrustChecker;
import com.isode.stroke.tls.CertificateVerificationError;
import com.isode.stroke.tls.ServerIdentityVerifier;
+import com.isode.stroke.idn.IDNConverter;
+import com.isode.stroke.idn.ICUConverter;
+import com.isode.stroke.crypto.CryptoProvider;
+import com.isode.stroke.crypto.JavaCryptoProvider;
import java.util.List;
import java.util.UUID;
@@ -84,6 +88,8 @@ public class ClientSession {
private StanzaAckResponder stanzaAckResponder_;
private com.isode.stroke.base.Error error_;
private CertificateTrustChecker certificateTrustChecker;
+ private IDNConverter idnConverter = new ICUConverter(); //TOPORT: Accomodated later in Constructor.
+ private CryptoProvider crypto = new JavaCryptoProvider(); //TOPORT: Accomodated later in Constructor.
public enum State {
@@ -354,7 +360,7 @@ public class ClientSession {
stream.writeElement(new AuthRequest("EXTERNAL",new SafeByteArray()));
}
else if (streamFeatures.hasAuthenticationMechanism("SCRAM-SHA-1") || streamFeatures.hasAuthenticationMechanism("SCRAM-SHA-1-PLUS")) {
- final SCRAMSHA1ClientAuthenticator scramAuthenticator = new SCRAMSHA1ClientAuthenticator(UUID.randomUUID().toString(), streamFeatures.hasAuthenticationMechanism("SCRAM-SHA-1-PLUS"));
+ final SCRAMSHA1ClientAuthenticator scramAuthenticator = new SCRAMSHA1ClientAuthenticator(UUID.randomUUID().toString(), streamFeatures.hasAuthenticationMechanism("SCRAM-SHA-1-PLUS"), idnConverter, crypto);
if (stream.isTLSEncrypted()) {
scramAuthenticator.setTLSChannelBindingData(stream.getTLSFinishMessage());
}
@@ -508,7 +514,7 @@ public class ClientSession {
return true;
}
- public void sendCredentials(final String password) {
+ public void sendCredentials(final SafeByteArray password) {
if (!checkState(State.WaitingForCredentials)) {
throw new IllegalStateException("Asking for credentials when we shouldn't be asked.");
}
diff --git a/src/com/isode/stroke/client/CoreClient.java b/src/com/isode/stroke/client/CoreClient.java
index efefa1c..39229a3 100644
--- a/src/com/isode/stroke/client/CoreClient.java
+++ b/src/com/isode/stroke/client/CoreClient.java
@@ -80,7 +80,7 @@ public class CoreClient {
*/
public final Signal1<Stanza> onStanzaAcked = new Signal1<Stanza>();
private JID jid_;
- private String password_;
+ private SafeByteArray password_;
private ClientSessionStanzaChannel stanzaChannel_;
private IQRouter iqRouter_;
private Connector connector_;
@@ -117,7 +117,7 @@ public class CoreClient {
* @param networkFactories An implementation of network interaction, must
* not be null.
*/
- public CoreClient(final JID jid, final String password, final NetworkFactories networkFactories) {
+ public CoreClient(final JID jid, final SafeByteArray password, final NetworkFactories networkFactories) {
jid_ = jid;
password_ = password;
disconnectRequested_ = false;
diff --git a/src/com/isode/stroke/examples/ConnectDisconnect.java b/src/com/isode/stroke/examples/ConnectDisconnect.java
index 6b4cbc4..12b3c27 100644
--- a/src/com/isode/stroke/examples/ConnectDisconnect.java
+++ b/src/com/isode/stroke/examples/ConnectDisconnect.java
@@ -13,6 +13,7 @@ import com.isode.stroke.jid.JID;
import com.isode.stroke.network.JavaNetworkFactories;
import com.isode.stroke.signals.Slot;
import com.isode.stroke.signals.Slot1;
+import com.isode.stroke.base.SafeByteArray;
/**
* Simple example.
@@ -66,7 +67,7 @@ public class ConnectDisconnect {
public void go(String args[]) {
jid = new JID(args[0]);
- String password = args[1];
+ SafeByteArray password = new SafeByteArray(args[1]);
DummyEventLoop eventLoop = new DummyEventLoop();
JavaNetworkFactories factories = new JavaNetworkFactories(eventLoop);
diff --git a/src/com/isode/stroke/examples/gui/StrokeGUI.java b/src/com/isode/stroke/examples/gui/StrokeGUI.java
index 6fc07de..5d0c1ca 100644
--- a/src/com/isode/stroke/examples/gui/StrokeGUI.java
+++ b/src/com/isode/stroke/examples/gui/StrokeGUI.java
@@ -158,7 +158,7 @@ public class StrokeGUI extends javax.swing.JFrame {
}
};
- client_ = new CoreClient(JID.fromString(loginJID_.getText()), loginPassword_.getText(), new JavaNetworkFactories(eventLoop));
+ client_ = new CoreClient(JID.fromString(loginJID_.getText()), new SafeByteArray(loginPassword_.getText()), new JavaNetworkFactories(eventLoop));
System.out.println("Connecting");
try {
client_.connect(new ClientOptions());
diff --git a/src/com/isode/stroke/sasl/ClientAuthenticator.java b/src/com/isode/stroke/sasl/ClientAuthenticator.java
index 2dc3756..450ef1b 100644
--- a/src/com/isode/stroke/sasl/ClientAuthenticator.java
+++ b/src/com/isode/stroke/sasl/ClientAuthenticator.java
@@ -21,11 +21,11 @@ public abstract class ClientAuthenticator {
return name;
}
- public void setCredentials(String authcid, String password) {
+ public void setCredentials(String authcid, SafeByteArray password) {
setCredentials(authcid, password, "");
}
- public void setCredentials(String authcid, String password, String authzid) {
+ public void setCredentials(String authcid, SafeByteArray password, String authzid) {
this.authcid = authcid;
this.password = password;
this.authzid = authzid;
@@ -43,11 +43,11 @@ public abstract class ClientAuthenticator {
return authzid;
}
- public String getPassword() {
+ public SafeByteArray getPassword() {
return password;
}
private String name;
private String authcid;
- private String password;
+ private SafeByteArray password;
private String authzid;
}
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
diff --git a/src/com/isode/stroke/sasl/DIGESTMD5Properties.java b/src/com/isode/stroke/sasl/DIGESTMD5Properties.java
new file mode 100644
index 0000000..0bc6a8d
--- /dev/null
+++ b/src/com/isode/stroke/sasl/DIGESTMD5Properties.java
@@ -0,0 +1,146 @@
+/*
+ * 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.base.SafeByteArray;
+import com.isode.stroke.base.ByteArray;
+import java.util.TreeMap;
+import java.util.Map;
+import java.util.Vector;
+
+public class DIGESTMD5Properties {
+
+ // Swiften uses std::multimap, but this is not required, so a TreeMap is used here.
+ private TreeMap<String, ByteArray> properties = new TreeMap<String, ByteArray>();
+
+ static boolean insideQuotes(final ByteArray v) {
+ if (v.isEmpty()) {
+ return false;
+ }
+ else if (v.getSize() == 1) {
+ return v.getData()[0] == '"';
+ }
+ else if (v.getData()[0] == '"') {
+ return v.getData()[v.getSize() - 1] != '"';
+ }
+ else {
+ return false;
+ }
+ }
+
+ static ByteArray stripQuotes(final ByteArray v) {
+ String s = new String(v.getData()); // possibly with a charset
+ int size = v.getSize();
+ int i = 0;
+ if(s.charAt(0) == '"') {
+ i++;
+ size--;
+ }
+ if(s.charAt(v.getSize() - 1) == '"') {
+ size--;
+ }
+ String data = s.substring(i, size+1);
+ return new ByteArray(data);
+ }
+
+ public DIGESTMD5Properties() {
+
+ }
+
+ public String getValue(final String key) {
+ if (properties.containsKey(key)) {
+ return properties.get(key).toString();
+ }
+ else {
+ return null;
+ }
+ }
+
+ public void setValue(final String key, final String value) {
+ if(!(properties.containsKey(key))) {
+ properties.put(key, new ByteArray(value));
+ }
+ }
+
+ public ByteArray serialize() {
+ ByteArray result = new ByteArray();
+ for(Map.Entry<String, ByteArray> entry : properties.entrySet()) {
+ if(entry.getKey() != properties.firstKey()) {
+ result.append((byte)(','));
+ }
+ result.append(new ByteArray(entry.getKey()));
+ result.append((byte)('='));
+ if (isQuoted(entry.getKey())) {
+ result.append(new ByteArray("\""));
+ result.append(entry.getValue()); //It does not iterate over all values possible for this key. So no need for MultiMap. Also serialize test also indicates the same.
+ result.append(new ByteArray("\""));
+ }
+ else {
+ result.append(entry.getValue());
+ }
+ }
+ return result;
+ }
+
+ public static DIGESTMD5Properties parse(final ByteArray data) {
+ DIGESTMD5Properties result = new DIGESTMD5Properties();
+ boolean inKey = true;
+ ByteArray currentKey = new ByteArray();
+ ByteArray currentValue = new ByteArray();
+ byte[] byteArrayData = data.getData();
+ for (int i = 0; i < data.getSize(); ++i) {
+ char c = (char)(byteArrayData[i]);
+ if (inKey) {
+ if (c == '=') {
+ inKey = false;
+ }
+ else {
+ currentKey.append((byte)(c));
+ }
+ }
+ else {
+ if (c == ',' && !insideQuotes(currentValue)) {
+ String key = currentKey.toString();
+ if (isQuoted(key)) {
+ result.setValue(key, stripQuotes(currentValue).toString());
+ }
+ else {
+ result.setValue(key, currentValue.toString());
+ }
+ inKey = true;
+ currentKey = new ByteArray();
+ currentValue = new ByteArray();
+ }
+ else {
+ currentValue.append((byte)(c));
+ }
+ }
+ }
+
+ if (!currentKey.isEmpty()) {
+ String key = currentKey.toString();
+ if (isQuoted(key)) {
+ result.setValue(key, stripQuotes(currentValue).toString());
+ }
+ else {
+ result.setValue(key, currentValue.toString());
+ }
+ }
+
+ return result;
+ }
+
+ private static boolean isQuoted(final String p) {
+ return p.equals("authzid") || p.equals("cnonce") || p.equals("digest-uri") || p.equals("nonce") || p.equals("realm") || p.equals("username");
+ }
+}
diff --git a/src/com/isode/stroke/sasl/EXTERNALClientAuthenticator.java b/src/com/isode/stroke/sasl/EXTERNALClientAuthenticator.java
new file mode 100644
index 0000000..9cd78d7
--- /dev/null
+++ b/src/com/isode/stroke/sasl/EXTERNALClientAuthenticator.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012-2015 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.base.SafeByteArray;
+import com.isode.stroke.base.ByteArray;
+
+public class EXTERNALClientAuthenticator extends ClientAuthenticator {
+
+ private boolean finished;
+
+ public EXTERNALClientAuthenticator() {
+ super("EXTERNAL");
+ this.finished = false;
+ }
+
+ public SafeByteArray getResponse() {
+ return null;
+ }
+
+ public boolean setChallenge(final ByteArray byteArray) {
+ if (finished) {
+ return false;
+ }
+ finished = true;
+ return true;
+ }
+} \ No newline at end of file
diff --git a/src/com/isode/stroke/sasl/PLAINMessage.java b/src/com/isode/stroke/sasl/PLAINMessage.java
new file mode 100644
index 0000000..5c1fe8b
--- /dev/null
+++ b/src/com/isode/stroke/sasl/PLAINMessage.java
@@ -0,0 +1,75 @@
+/*
+ * 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.base.SafeByteArray;
+import com.isode.stroke.base.ByteArray;
+
+public class PLAINMessage {
+
+ private String authcid = "";
+ private String authzid = "";
+ private SafeByteArray password = new SafeByteArray();
+
+ public PLAINMessage(final String authcid, final SafeByteArray password) {
+ this(authcid, password, "");
+ }
+
+ public PLAINMessage(final String authcid, final SafeByteArray password, final String authzid) {
+ this.authcid = authcid;
+ this.password = password;
+ this.authzid = authzid;
+ }
+
+ public PLAINMessage(final SafeByteArray value) {
+ int i = 0;
+ byte[] byteArrayValue = value.getData();
+ while (i < value.getSize() && byteArrayValue[i] != ((byte)0)) {
+ authzid += (char)(byteArrayValue[i]);
+ ++i;
+ }
+ if (i == value.getSize()) {
+ return;
+ }
+ ++i;
+ while (i < value.getSize() && byteArrayValue[i] != ((byte)0)) {
+ authcid += (char)(byteArrayValue[i]);
+ ++i;
+ }
+ if (i == value.getSize()) {
+ authcid = "";
+ return;
+ }
+ ++i;
+ while (i < value.getSize()) {
+ password.append(byteArrayValue[i]);
+ ++i;
+ }
+ }
+
+ public SafeByteArray getValue() {
+ return new SafeByteArray().append(authzid).append((byte)0).append(authcid).append((byte)0).append(password);
+ }
+
+ public String getAuthenticationID() {
+ return authcid;
+ }
+
+ public SafeByteArray getPassword() {
+ return password;
+ }
+
+ public String getAuthorizationID() {
+ return authzid;
+ }
+} \ No newline at end of file
diff --git a/src/com/isode/stroke/sasl/SCRAMSHA1ClientAuthenticator.java b/src/com/isode/stroke/sasl/SCRAMSHA1ClientAuthenticator.java
index 29a37aa..9797e24 100644
--- a/src/com/isode/stroke/sasl/SCRAMSHA1ClientAuthenticator.java
+++ b/src/com/isode/stroke/sasl/SCRAMSHA1ClientAuthenticator.java
@@ -10,10 +10,13 @@ package com.isode.stroke.sasl;
import com.isode.stroke.base.ByteArray;
import com.isode.stroke.base.SafeByteArray;
+import com.ibm.icu.text.StringPrepParseException;
import com.isode.stroke.stringcodecs.Base64;
import com.isode.stroke.stringcodecs.HMACSHA1;
import com.isode.stroke.stringcodecs.PBKDF2;
import com.isode.stroke.stringcodecs.SHA1;
+import com.isode.stroke.idn.IDNConverter;
+import com.isode.stroke.crypto.CryptoProvider;
import java.text.Normalizer;
import java.text.Normalizer.Form;
import java.util.HashMap;
@@ -35,14 +38,13 @@ public class SCRAMSHA1ClientAuthenticator extends ClientAuthenticator {
return result;
}
- public SCRAMSHA1ClientAuthenticator(String nonce) {
- this(nonce, false);
- }
- public SCRAMSHA1ClientAuthenticator(String nonce, boolean useChannelBinding) {
+ public SCRAMSHA1ClientAuthenticator(String nonce, boolean useChannelBinding, IDNConverter idnConverter, CryptoProvider crypto) {
super(useChannelBinding ? "SCRAM-SHA-1-PLUS" : "SCRAM-SHA-1");
step = Step.Initial;
clientnonce = nonce;
this.useChannelBinding = useChannelBinding;
+ this.idnConverter = idnConverter;
+ this.crypto = crypto;
}
public void setTLSChannelBindingData(ByteArray channelBindingData) {
@@ -53,9 +55,9 @@ public class SCRAMSHA1ClientAuthenticator extends ClientAuthenticator {
if (step.equals(Step.Initial)) {
return new SafeByteArray(getGS2Header().append(getInitialBareClientMessage()));
} else if (step.equals(Step.Proof)) {
- ByteArray clientKey = HMACSHA1.getResult(saltedPassword, new ByteArray("Client Key"));
- ByteArray storedKey = SHA1.getHash(clientKey);
- ByteArray clientSignature = HMACSHA1.getResult(storedKey, authMessage);
+ ByteArray clientKey = crypto.getHMACSHA1(saltedPassword, new ByteArray("Client Key"));
+ ByteArray storedKey = crypto.getSHA1Hash(clientKey);
+ ByteArray clientSignature = crypto.getHMACSHA1(new SafeByteArray(storedKey), authMessage);
ByteArray clientProof = clientKey;
byte[] clientProofData = clientProof.getData();
for (int i = 0; i < clientProofData.length; ++i) {
@@ -104,16 +106,21 @@ public class SCRAMSHA1ClientAuthenticator extends ClientAuthenticator {
return false;
}
+ //Not Sure, why this here.
ByteArray channelBindData = new ByteArray();
if (useChannelBinding && tlsChannelBindingData != null) {
channelBindData = tlsChannelBindingData;
}
// Compute all the values needed for the server signature
- saltedPassword = PBKDF2.encode(new ByteArray(SASLPrep(getPassword())), salt, iterations);
+ try {
+ saltedPassword = PBKDF2.encode(idnConverter.getStringPrepared(getPassword(), IDNConverter.StringPrepProfile.SASLPrep), salt, iterations, crypto);
+ } catch (StringPrepParseException e) {
+
+ }
authMessage = getInitialBareClientMessage().append(",").append(initialServerMessage).append(",").append(getFinalMessageWithoutProof());
- ByteArray serverKey = HMACSHA1.getResult(saltedPassword, new ByteArray("Server Key"));
- serverSignature = HMACSHA1.getResult(serverKey, authMessage);
+ ByteArray serverKey = crypto.getHMACSHA1(saltedPassword, new ByteArray("Server Key"));
+ serverSignature = crypto.getHMACSHA1(serverKey, authMessage);
step = Step.Proof;
return true;
@@ -126,10 +133,6 @@ public class SCRAMSHA1ClientAuthenticator extends ClientAuthenticator {
}
}
- private String SASLPrep(String source) {
- return Normalizer.normalize(source, Form.NFKC); /* FIXME: Implement real SASLPrep */
- }
-
private Map<Character, String> parseMap(String s) {
HashMap<Character, String> result = new HashMap<Character, String>();
if (s.length() > 0) {
@@ -157,7 +160,12 @@ public class SCRAMSHA1ClientAuthenticator extends ClientAuthenticator {
}
private ByteArray getInitialBareClientMessage() {
- String authenticationID = SASLPrep(getAuthenticationID());
+ String authenticationID = "";
+ try {
+ authenticationID = idnConverter.getStringPrepared(getAuthenticationID(), IDNConverter.StringPrepProfile.SASLPrep);
+ } catch (StringPrepParseException e) {
+
+ }
return new ByteArray("n=" + escape(authenticationID) + ",r=" + clientnonce);
}
@@ -198,4 +206,6 @@ public class SCRAMSHA1ClientAuthenticator extends ClientAuthenticator {
private ByteArray serverSignature = new ByteArray();
private boolean useChannelBinding;
private ByteArray tlsChannelBindingData;
+ private IDNConverter idnConverter;
+ private CryptoProvider crypto;
}
diff --git a/src/com/isode/stroke/stringcodecs/PBKDF2.java b/src/com/isode/stroke/stringcodecs/PBKDF2.java
index 1392d2f..6147ee4 100644
--- a/src/com/isode/stroke/stringcodecs/PBKDF2.java
+++ b/src/com/isode/stroke/stringcodecs/PBKDF2.java
@@ -9,16 +9,18 @@
package com.isode.stroke.stringcodecs;
import com.isode.stroke.base.ByteArray;
+import com.isode.stroke.base.SafeByteArray;
+import com.isode.stroke.crypto.CryptoProvider;
public class PBKDF2 {
- public static ByteArray encode(ByteArray password, ByteArray salt, int iterations) {
- ByteArray u = HMACSHA1.getResult(password, ByteArray.plus(salt, new ByteArray("\0\0\0\1")));
+ public static ByteArray encode(SafeByteArray password, ByteArray salt, int iterations, CryptoProvider crypto) {
+ ByteArray u = crypto.getHMACSHA1(password, ByteArray.plus(salt, new ByteArray("\0\0\0\1")));
ByteArray result = new ByteArray(u);
byte[] resultData = result.getData();
int i = 1;
while (i < iterations) {
- u = HMACSHA1.getResult(password, u);
+ u = crypto.getHMACSHA1(password, u);
for (int j = 0; j < u.getSize(); ++j) {
resultData[j] ^= u.getData()[j];
}
diff --git a/test/com/isode/stroke/pubsub/Client.java b/test/com/isode/stroke/pubsub/Client.java
index c68ba96..5a0059d 100644
--- a/test/com/isode/stroke/pubsub/Client.java
+++ b/test/com/isode/stroke/pubsub/Client.java
@@ -22,7 +22,7 @@ public class Client {
static boolean debugInfo = false;
static boolean debugInfoXml = false;
- public Client(String name, JID jid, String password, JavaNetworkFactories networkFactories, final Slot connectCallback) {
+ public Client(String name, JID jid, SafeByteArray password, JavaNetworkFactories networkFactories, final Slot connectCallback) {
name_ = name;
connecting_ = true;
connected_ = false;
diff --git a/test/com/isode/stroke/pubsub/TestMain.java b/test/com/isode/stroke/pubsub/TestMain.java
index 2088898..40b46e0 100644
--- a/test/com/isode/stroke/pubsub/TestMain.java
+++ b/test/com/isode/stroke/pubsub/TestMain.java
@@ -40,15 +40,16 @@ import com.isode.stroke.jid.JID;
import com.isode.stroke.network.JavaNetworkFactories;
import com.isode.stroke.signals.Slot;
import com.isode.stroke.signals.Slot2;
+import com.isode.stroke.base.SafeByteArray;
public class TestMain {
/* begin test parameters */
static String _server = "stan.isode.net";
static String _pubJID = "test1@stan.isode.net";
- static String _pubPass = "password";
+ static SafeByteArray _pubPass = new SafeByteArray("password");
static String _subJID = "test2@stan.isode.net";
- static String _subPass = "password";
+ static SafeByteArray _subPass = new SafeByteArray("password");
static String _pubSubDomain = "pubsub.stan.isode.net";
static String _pubSubNode = "testnode";
/* end test parameters */
diff --git a/test/com/isode/stroke/sasl/DIGESTMD5ClientAuthenticatorTest.java b/test/com/isode/stroke/sasl/DIGESTMD5ClientAuthenticatorTest.java
new file mode 100644
index 0000000..92c8b7c
--- /dev/null
+++ b/test/com/isode/stroke/sasl/DIGESTMD5ClientAuthenticatorTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.junit.Before;
+import com.isode.stroke.sasl.DIGESTMD5ClientAuthenticator;
+import com.isode.stroke.base.ByteArray;
+import com.isode.stroke.base.SafeByteArray;
+import com.isode.stroke.crypto.CryptoProvider;
+import com.isode.stroke.crypto.JavaCryptoProvider;
+
+public class DIGESTMD5ClientAuthenticatorTest {
+
+ private CryptoProvider crypto;
+
+ @Before
+ public void setUp() {
+ crypto = new JavaCryptoProvider();
+ }
+
+ @Test
+ public void testGetInitialResponse() {
+ DIGESTMD5ClientAuthenticator testling = new DIGESTMD5ClientAuthenticator("xmpp.example.com", "abcdefgh", crypto);
+
+ assertNull(testling.getResponse());
+ }
+
+ @Test
+ public void testGetResponse() {
+ DIGESTMD5ClientAuthenticator testling = new DIGESTMD5ClientAuthenticator("xmpp.example.com", "abcdefgh", crypto);
+
+ testling.setCredentials("user", new SafeByteArray("pass"), "");
+ testling.setChallenge(new ByteArray(
+ "realm=\"example.com\","
+ + "nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\","
+ + "qop=auth,charset=utf-8,algorithm=md5-sess"));
+
+ SafeByteArray response = testling.getResponse();
+
+ assertEquals(new SafeByteArray("charset=utf-8,cnonce=\"abcdefgh\",digest-uri=\"xmpp/xmpp.example.com\",nc=00000001,nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\",qop=auth,realm=\"example.com\",response=088891c800ecff1b842159ad6459104a,username=\"user\""), response);
+ }
+
+ @Test
+ public void testGetResponse_WithAuthorizationID() {
+ DIGESTMD5ClientAuthenticator testling = new DIGESTMD5ClientAuthenticator("xmpp.example.com", "abcdefgh", crypto);
+
+ testling.setCredentials("user", new SafeByteArray("pass"), "myauthzid");
+ testling.setChallenge(new ByteArray(
+ "realm=\"example.com\","
+ + "nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\","
+ + "qop=auth,charset=utf-8,algorithm=md5-sess"));
+
+ SafeByteArray response = testling.getResponse();
+
+ assertEquals(new SafeByteArray("authzid=\"myauthzid\",charset=utf-8,cnonce=\"abcdefgh\",digest-uri=\"xmpp/xmpp.example.com\",nc=00000001,nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\",qop=auth,realm=\"example.com\",response=4293834432b6e7889a2dee7e8fe7dd06,username=\"user\""), response);
+ }
+}
diff --git a/test/com/isode/stroke/sasl/DIGESTMD5PropertiesTest.java b/test/com/isode/stroke/sasl/DIGESTMD5PropertiesTest.java
new file mode 100644
index 0000000..1288b2f
--- /dev/null
+++ b/test/com/isode/stroke/sasl/DIGESTMD5PropertiesTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2010 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.junit.Before;
+import com.isode.stroke.sasl.DIGESTMD5Properties;
+import com.isode.stroke.base.ByteArray;
+
+public class DIGESTMD5PropertiesTest {
+
+ @Test
+ public void testParse() {
+ DIGESTMD5Properties properties = DIGESTMD5Properties.parse(new ByteArray(
+ "realm=\"myrealm1\",realm=\"myrealm2\",nonce=\"mynonce\","
+ + "algorithm=md5-sess,charset=utf-8"));
+
+ assertNotNull(properties.getValue("realm"));
+ assertEquals(("myrealm1"), properties.getValue("realm"));
+ assertNotNull(properties.getValue("nonce"));
+ assertEquals(("mynonce"), properties.getValue("nonce"));
+ assertNotNull(properties.getValue("algorithm"));
+ assertEquals(("md5-sess"), properties.getValue("algorithm"));
+ assertNotNull(properties.getValue("charset"));
+ assertEquals(("utf-8"), properties.getValue("charset"));
+ }
+
+ @Test
+ public void testSerialize() {
+ DIGESTMD5Properties properties = new DIGESTMD5Properties();
+ properties.setValue("authzid", "myauthzid");
+ properties.setValue("charset", "utf-8");
+ properties.setValue("cnonce", "mycnonce");
+ properties.setValue("digest-uri", "mydigesturi");
+ properties.setValue("nc", "1");
+ properties.setValue("nonce", "mynonce");
+ properties.setValue("qop", "auth");
+ properties.setValue("realm", "myrealm");
+ properties.setValue("response", "myresponse");
+ properties.setValue("username", "myuser");
+
+ ByteArray result = properties.serialize();
+ ByteArray expected = new ByteArray("authzid=\"myauthzid\",charset=utf-8,cnonce=\"mycnonce\",digest-uri=\"mydigesturi\",nc=1,nonce=\"mynonce\",qop=auth,realm=\"myrealm\",response=myresponse,username=\"myuser\"");
+ assertEquals(expected.toString(), result.toString());
+ }
+} \ No newline at end of file
diff --git a/test/com/isode/stroke/sasl/PLAINClientAuthenticatorTest.java b/test/com/isode/stroke/sasl/PLAINClientAuthenticatorTest.java
new file mode 100644
index 0000000..2f9170b
--- /dev/null
+++ b/test/com/isode/stroke/sasl/PLAINClientAuthenticatorTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.junit.Before;
+import com.isode.stroke.sasl.PLAINClientAuthenticator;
+import com.isode.stroke.base.SafeByteArray;
+
+public class PLAINClientAuthenticatorTest {
+
+ @Test
+ public void testGetResponse_WithoutAuthzID() {
+ PLAINClientAuthenticator testling = new PLAINClientAuthenticator();
+
+ testling.setCredentials("user", new SafeByteArray("pass"));
+
+ assertEquals(testling.getResponse(), new SafeByteArray("\0user\0pass"));
+ }
+
+ @Test
+ public void testGetResponse_WithAuthzID() {
+ PLAINClientAuthenticator testling = new PLAINClientAuthenticator();
+
+ testling.setCredentials("user", new SafeByteArray("pass"), "authz");
+
+ assertEquals(testling.getResponse(), new SafeByteArray("authz\0user\0pass"));
+ }
+} \ No newline at end of file
diff --git a/test/com/isode/stroke/sasl/PLAINMessageTest.java b/test/com/isode/stroke/sasl/PLAINMessageTest.java
new file mode 100644
index 0000000..de7f5ee
--- /dev/null
+++ b/test/com/isode/stroke/sasl/PLAINMessageTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2010 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.junit.Before;
+import com.isode.stroke.sasl.PLAINMessage;
+import com.isode.stroke.base.SafeByteArray;
+
+public class PLAINMessageTest {
+
+ @Test
+ public void testGetValue_WithoutAuthzID() {
+ PLAINMessage message = new PLAINMessage("user", new SafeByteArray("pass"));
+ assertEquals(message.getValue(), new SafeByteArray("\0user\0pass"));
+ }
+
+ @Test
+ public void testGetValue_WithAuthzID() {
+ PLAINMessage message = new PLAINMessage("user", new SafeByteArray("pass"), "authz");
+ assertEquals(message.getValue(), new SafeByteArray("authz\0user\0pass"));
+ }
+
+ @Test
+ public void testConstructor_WithoutAuthzID() {
+ PLAINMessage message = new PLAINMessage(new SafeByteArray("\0user\0pass"));
+
+ assertEquals((""), message.getAuthorizationID());
+ assertEquals(("user"), message.getAuthenticationID());
+ assertEquals(new SafeByteArray("pass"), message.getPassword());
+ }
+
+ @Test
+ public void testConstructor_WithAuthzID() {
+ PLAINMessage message = new PLAINMessage(new SafeByteArray("authz\0user\0pass"));
+
+ assertEquals(("authz"), message.getAuthorizationID());
+ assertEquals(("user"), message.getAuthenticationID());
+ assertEquals(new SafeByteArray("pass"), message.getPassword());
+ }
+
+ @Test
+ public void testConstructor_NoAuthcid() {
+ PLAINMessage message = new PLAINMessage(new SafeByteArray("authzid"));
+
+ assertEquals((""), message.getAuthenticationID());
+ }
+
+ @Test
+ public void testConstructor_NoPassword() {
+ PLAINMessage message = new PLAINMessage(new SafeByteArray("authzid\0authcid"));
+
+ assertEquals((""), message.getAuthenticationID());
+ }
+}
diff --git a/test/com/isode/stroke/sasl/SCRAMSHA1ClientAuthenticatorTest.java b/test/com/isode/stroke/sasl/SCRAMSHA1ClientAuthenticatorTest.java
index 7217d8d..9969ebd 100644
--- a/test/com/isode/stroke/sasl/SCRAMSHA1ClientAuthenticatorTest.java
+++ b/test/com/isode/stroke/sasl/SCRAMSHA1ClientAuthenticatorTest.java
@@ -14,6 +14,10 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
+import com.isode.stroke.idn.IDNConverter;
+import com.isode.stroke.idn.ICUConverter;
+import com.isode.stroke.crypto.CryptoProvider;
+import com.isode.stroke.crypto.JavaCryptoProvider;
/**
*
@@ -21,107 +25,116 @@ import static org.junit.Assert.*;
*/
public class SCRAMSHA1ClientAuthenticatorTest {
+ private IDNConverter idnConverter;
+ private CryptoProvider crypto;
+
+ @Before
+ public void setUp() {
+ idnConverter = new ICUConverter();
+ crypto = new JavaCryptoProvider();
+ }
+
@Test
public void testGetInitialResponse() {
- SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefghABCDEFGH");
- testling.setCredentials("user", "pass", "");
+ SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefghABCDEFGH", false, idnConverter, crypto);
+ testling.setCredentials("user", new SafeByteArray("pass"), "");
SafeByteArray response = testling.getResponse();
- assertEquals(new ByteArray("n,,n=user,r=abcdefghABCDEFGH"), response);
+ assertEquals(new SafeByteArray("n,,n=user,r=abcdefghABCDEFGH"), response);
}
@Test
public void testGetInitialResponse_UsernameHasSpecialChars() {
- SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefghABCDEFGH");
- testling.setCredentials(",us=,er=", "pass", "");
+ SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefghABCDEFGH", false, idnConverter, crypto);
+ testling.setCredentials(",us=,er=", new SafeByteArray("pass"), "");
SafeByteArray response = testling.getResponse();
- assertEquals(new ByteArray("n,,n==2Cus=3D=2Cer=3D,r=abcdefghABCDEFGH"), response);
+ assertEquals(new SafeByteArray("n,,n==2Cus=3D=2Cer=3D,r=abcdefghABCDEFGH"), response);
}
@Test
public void testGetInitialResponse_WithAuthorizationID() {
- SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefghABCDEFGH");
- testling.setCredentials("user", "pass", "auth");
+ SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefghABCDEFGH", false, idnConverter, crypto);
+ testling.setCredentials("user", new SafeByteArray("pass"), "auth");
SafeByteArray response = testling.getResponse();
- assertEquals(new ByteArray("n,a=auth,n=user,r=abcdefghABCDEFGH"), response);
+ assertEquals(new SafeByteArray("n,a=auth,n=user,r=abcdefghABCDEFGH"), response);
}
@Test
public void testGetInitialResponse_WithAuthorizationIDWithSpecialChars() {
- SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefghABCDEFGH");
- testling.setCredentials("user", "pass", "a=u,th");
+ SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefghABCDEFGH", false, idnConverter, crypto);
+ testling.setCredentials("user", new SafeByteArray("pass"), "a=u,th");
SafeByteArray response = testling.getResponse();
- assertEquals(new ByteArray("n,a=a=3Du=2Cth,n=user,r=abcdefghABCDEFGH"), response);
+ assertEquals(new SafeByteArray("n,a=a=3Du=2Cth,n=user,r=abcdefghABCDEFGH"), response);
}
@Test
public void testGetInitialResponse_WithoutChannelBindingWithTLSChannelBindingData() {
- SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefghABCDEFGH", false);
+ SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefghABCDEFGH", false, idnConverter, crypto);
testling.setTLSChannelBindingData(new ByteArray("xyza"));
- testling.setCredentials("user", "pass", "");
+ testling.setCredentials("user", new SafeByteArray("pass"), "");
SafeByteArray response = testling.getResponse();
- assertEquals(new ByteArray("y,,n=user,r=abcdefghABCDEFGH"), response);
+ assertEquals(new SafeByteArray("y,,n=user,r=abcdefghABCDEFGH"), response);
}
@Test
public void testGetInitialResponse_WithChannelBindingWithTLSChannelBindingData() {
- SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefghABCDEFGH", true);
+ SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefghABCDEFGH", true, idnConverter, crypto);
testling.setTLSChannelBindingData(new ByteArray("xyza"));
- testling.setCredentials("user", "pass", "");
+ testling.setCredentials("user", new SafeByteArray("pass"), "");
SafeByteArray response = testling.getResponse();
- assertEquals(new ByteArray("p=tls-unique,,n=user,r=abcdefghABCDEFGH"), response);
+ assertEquals(new SafeByteArray("p=tls-unique,,n=user,r=abcdefghABCDEFGH"), response);
}
@Test
public void testGetFinalResponse() {
- SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh");
- testling.setCredentials("user", "pass", "");
+ SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh", false, idnConverter, crypto);
+ testling.setCredentials("user", new SafeByteArray("pass"), "");
assertTrue(testling.setChallenge(new ByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096")));
SafeByteArray response = testling.getResponse();
- assertEquals(new ByteArray("c=biws,r=abcdefghABCDEFGH,p=CZbjGDpIteIJwQNBgO0P8pKkMGY="), response);
+ assertEquals(new SafeByteArray("c=biws,r=abcdefghABCDEFGH,p=CZbjGDpIteIJwQNBgO0P8pKkMGY="), response);
}
@Test
public void testGetFinalResponse_WithoutChannelBindingWithTLSChannelBindingData() {
- SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh", false);
- testling.setCredentials("user", "pass", "");
+ SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh", false, idnConverter, crypto);
+ testling.setCredentials("user", new SafeByteArray("pass"), "");
testling.setTLSChannelBindingData(new ByteArray("xyza"));
testling.setChallenge(new ByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096"));
SafeByteArray response = testling.getResponse();
- assertEquals(new ByteArray("c=eSws,r=abcdefghABCDEFGH,p=JNpsiFEcxZvNZ1+FFBBqrYvYxMk="), response);
+ assertEquals(new SafeByteArray("c=eSws,r=abcdefghABCDEFGH,p=JNpsiFEcxZvNZ1+FFBBqrYvYxMk="), response);
}
@Test
public void testGetFinalResponse_WithChannelBindingWithTLSChannelBindingData() {
- SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh", true);
- testling.setCredentials("user", "pass", "");
+ SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh", true, idnConverter, crypto);
+ testling.setCredentials("user", new SafeByteArray("pass"), "");
testling.setTLSChannelBindingData(new ByteArray("xyza"));
testling.setChallenge(new ByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096"));
SafeByteArray response = testling.getResponse();
- assertEquals(new ByteArray("c=cD10bHMtdW5pcXVlLCx4eXph,r=abcdefghABCDEFGH,p=i6Rghite81P1ype8XxaVAa5l7v0="), response);
+ assertEquals(new SafeByteArray("c=cD10bHMtdW5pcXVlLCx4eXph,r=abcdefghABCDEFGH,p=i6Rghite81P1ype8XxaVAa5l7v0="), response);
}
@Test
public void testSetFinalChallenge() {
- SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh");
- testling.setCredentials("user", "pass", "");
+ SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh", false, idnConverter, crypto);
+ testling.setCredentials("user", new SafeByteArray("pass"), "");
testling.setChallenge(new ByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096"));
boolean result = testling.setChallenge(new ByteArray("v=Dd+Q20knZs9jeeK0pi1Mx1Se+yo="));
@@ -131,8 +144,8 @@ public class SCRAMSHA1ClientAuthenticatorTest {
@Test
public void testSetChallenge() {
- SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh");
- testling.setCredentials("user", "pass", "");
+ SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh", false, idnConverter, crypto);
+ testling.setCredentials("user", new SafeByteArray("pass"), "");
boolean result = testling.setChallenge(new ByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096"));
@@ -141,8 +154,8 @@ public class SCRAMSHA1ClientAuthenticatorTest {
@Test
public void testSetChallenge_InvalidClientNonce() {
- SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh");
- testling.setCredentials("user", "pass", "");
+ SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh", false, idnConverter, crypto);
+ testling.setCredentials("user", new SafeByteArray("pass"), "");
boolean result = testling.setChallenge(new ByteArray("r=abcdefgiABCDEFGH,s=MTIzNDU2NzgK,i=4096"));
@@ -151,8 +164,8 @@ public class SCRAMSHA1ClientAuthenticatorTest {
@Test
public void testSetChallenge_OnlyClientNonce() {
- SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh");
- testling.setCredentials("user", "pass", "");
+ SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh", false, idnConverter, crypto);
+ testling.setCredentials("user", new SafeByteArray("pass"), "");
boolean result = testling.setChallenge(new ByteArray("r=abcdefgh,s=MTIzNDU2NzgK,i=4096"));
@@ -161,8 +174,8 @@ public class SCRAMSHA1ClientAuthenticatorTest {
@Test
public void testSetChallenge_InvalidIterations() {
- SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh");
- testling.setCredentials("user", "pass", "");
+ SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh", false, idnConverter, crypto);
+ testling.setCredentials("user", new SafeByteArray("pass"), "");
boolean result = testling.setChallenge(new ByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=bla"));
@@ -171,8 +184,8 @@ public class SCRAMSHA1ClientAuthenticatorTest {
@Test
public void testSetChallenge_MissingIterations() {
- SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh");
- testling.setCredentials("user", "pass", "");
+ SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh", false, idnConverter, crypto);
+ testling.setCredentials("user", new SafeByteArray("pass"), "");
boolean result = testling.setChallenge(new ByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK"));
@@ -181,8 +194,8 @@ public class SCRAMSHA1ClientAuthenticatorTest {
@Test
public void testSetChallenge_ZeroIterations() {
- SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh");
- testling.setCredentials("user", "pass", "");
+ SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh", false, idnConverter, crypto);
+ testling.setCredentials("user", new SafeByteArray("pass"), "");
boolean result = testling.setChallenge(new ByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=0"));
@@ -191,8 +204,8 @@ public class SCRAMSHA1ClientAuthenticatorTest {
@Test
public void testSetChallenge_NegativeIterations() {
- SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh");
- testling.setCredentials("user", "pass", "");
+ SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh", false, idnConverter, crypto);
+ testling.setCredentials("user", new SafeByteArray("pass"), "");
boolean result = testling.setChallenge(new ByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=-1"));
@@ -201,8 +214,8 @@ public class SCRAMSHA1ClientAuthenticatorTest {
@Test
public void testSetFinalChallenge_InvalidChallenge() {
- SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh");
- testling.setCredentials("user", "pass", "");
+ SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh", false, idnConverter, crypto);
+ testling.setCredentials("user", new SafeByteArray("pass"), "");
testling.setChallenge(new ByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096"));
boolean result = testling.setChallenge(new ByteArray("v=e26kI69ICb6zosapLLxrER/631A="));
@@ -211,8 +224,8 @@ public class SCRAMSHA1ClientAuthenticatorTest {
@Test
public void testGetResponseAfterFinalChallenge() {
- SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh");
- testling.setCredentials("user", "pass", "");
+ SCRAMSHA1ClientAuthenticator testling = new SCRAMSHA1ClientAuthenticator("abcdefgh", false, idnConverter, crypto);
+ testling.setCredentials("user", new SafeByteArray("pass"), "");
testling.setChallenge(new ByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096"));
testling.setChallenge(new ByteArray("v=Dd+Q20knZs9jeeK0pi1Mx1Se+yo="));