implement SCRAM-SHA512
This commit is contained in:
parent
2a57c92f63
commit
0e54d8a2cf
|
@ -7,6 +7,8 @@ import eu.siacs.conversations.xml.TagWriter;
|
||||||
|
|
||||||
public class Anonymous extends SaslMechanism {
|
public class Anonymous extends SaslMechanism {
|
||||||
|
|
||||||
|
public static final String MECHANISM = "ANONYMOUS";
|
||||||
|
|
||||||
public Anonymous(TagWriter tagWriter, Account account, SecureRandom rng) {
|
public Anonymous(TagWriter tagWriter, Account account, SecureRandom rng) {
|
||||||
super(tagWriter, account, rng);
|
super(tagWriter, account, rng);
|
||||||
}
|
}
|
||||||
|
@ -18,7 +20,7 @@ public class Anonymous extends SaslMechanism {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMechanism() {
|
public String getMechanism() {
|
||||||
return "ANONYMOUS";
|
return MECHANISM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -12,6 +12,9 @@ import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
import eu.siacs.conversations.xml.TagWriter;
|
import eu.siacs.conversations.xml.TagWriter;
|
||||||
|
|
||||||
public class DigestMd5 extends SaslMechanism {
|
public class DigestMd5 extends SaslMechanism {
|
||||||
|
|
||||||
|
public static final String MECHANISM = "DIGEST-MD5";
|
||||||
|
|
||||||
public DigestMd5(final TagWriter tagWriter, final Account account, final SecureRandom rng) {
|
public DigestMd5(final TagWriter tagWriter, final Account account, final SecureRandom rng) {
|
||||||
super(tagWriter, account, rng);
|
super(tagWriter, account, rng);
|
||||||
}
|
}
|
||||||
|
@ -23,7 +26,7 @@ public class DigestMd5 extends SaslMechanism {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMechanism() {
|
public String getMechanism() {
|
||||||
return "DIGEST-MD5";
|
return MECHANISM;
|
||||||
}
|
}
|
||||||
|
|
||||||
private State state = State.INITIAL;
|
private State state = State.INITIAL;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package eu.siacs.conversations.crypto.sasl;
|
package eu.siacs.conversations.crypto.sasl;
|
||||||
|
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
|
@ -8,6 +9,8 @@ import eu.siacs.conversations.xml.TagWriter;
|
||||||
|
|
||||||
public class External extends SaslMechanism {
|
public class External extends SaslMechanism {
|
||||||
|
|
||||||
|
public static final String MECHANISM = "EXTERNAL";
|
||||||
|
|
||||||
public External(TagWriter tagWriter, Account account, SecureRandom rng) {
|
public External(TagWriter tagWriter, Account account, SecureRandom rng) {
|
||||||
super(tagWriter, account, rng);
|
super(tagWriter, account, rng);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +22,7 @@ public class External extends SaslMechanism {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMechanism() {
|
public String getMechanism() {
|
||||||
return "EXTERNAL";
|
return MECHANISM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -8,6 +8,9 @@ import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.xml.TagWriter;
|
import eu.siacs.conversations.xml.TagWriter;
|
||||||
|
|
||||||
public class Plain extends SaslMechanism {
|
public class Plain extends SaslMechanism {
|
||||||
|
|
||||||
|
public static final String MECHANISM = "PLAIN";
|
||||||
|
|
||||||
public Plain(final TagWriter tagWriter, final Account account) {
|
public Plain(final TagWriter tagWriter, final Account account) {
|
||||||
super(tagWriter, account, null);
|
super(tagWriter, account, null);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +22,7 @@ public class Plain extends SaslMechanism {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMechanism() {
|
public String getMechanism() {
|
||||||
return "PLAIN";
|
return MECHANISM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -52,14 +52,17 @@ public abstract class SaslMechanism {
|
||||||
* The priority is used to pin the authentication mechanism. If authentication fails, it MAY be retried with another
|
* The priority is used to pin the authentication mechanism. If authentication fails, it MAY be retried with another
|
||||||
* mechanism of the same priority, but MUST NOT be tried with a mechanism of lower priority (to prevent downgrade
|
* mechanism of the same priority, but MUST NOT be tried with a mechanism of lower priority (to prevent downgrade
|
||||||
* attacks).
|
* attacks).
|
||||||
|
*
|
||||||
* @return An arbitrary int representing the priority
|
* @return An arbitrary int representing the priority
|
||||||
*/
|
*/
|
||||||
public abstract int getPriority();
|
public abstract int getPriority();
|
||||||
|
|
||||||
public abstract String getMechanism();
|
public abstract String getMechanism();
|
||||||
|
|
||||||
public String getClientFirstMessage() {
|
public String getClientFirstMessage() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getResponse(final String challenge) throws AuthenticationException {
|
public String getResponse(final String challenge) throws AuthenticationException {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package eu.siacs.conversations.crypto.sasl;
|
package eu.siacs.conversations.crypto.sasl;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
@ -21,7 +19,6 @@ import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.utils.CryptoHelper;
|
import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
import eu.siacs.conversations.xml.TagWriter;
|
import eu.siacs.conversations.xml.TagWriter;
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
|
|
||||||
abstract class ScramMechanism extends SaslMechanism {
|
abstract class ScramMechanism extends SaslMechanism {
|
||||||
// TODO: When channel binding (SCRAM-SHA1-PLUS) is supported in future, generalize this to indicate support and/or usage.
|
// TODO: When channel binding (SCRAM-SHA1-PLUS) is supported in future, generalize this to indicate support and/or usage.
|
||||||
private final static String GS2_HEADER = "n,,";
|
private final static String GS2_HEADER = "n,,";
|
||||||
|
|
|
@ -11,6 +11,8 @@ import eu.siacs.conversations.xml.TagWriter;
|
||||||
|
|
||||||
public class ScramSha1 extends ScramMechanism {
|
public class ScramSha1 extends ScramMechanism {
|
||||||
|
|
||||||
|
public static final String MECHANISM = "SCRAM-SHA-1";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected HMac getHMAC() {
|
protected HMac getHMAC() {
|
||||||
return new HMac(new SHA1Digest());
|
return new HMac(new SHA1Digest());
|
||||||
|
@ -32,6 +34,6 @@ public class ScramSha1 extends ScramMechanism {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMechanism() {
|
public String getMechanism() {
|
||||||
return "SCRAM-SHA-1";
|
return MECHANISM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@ import eu.siacs.conversations.xml.TagWriter;
|
||||||
|
|
||||||
public class ScramSha256 extends ScramMechanism {
|
public class ScramSha256 extends ScramMechanism {
|
||||||
|
|
||||||
|
public static final String MECHANISM = "SCRAM-SHA-256";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected HMac getHMAC() {
|
protected HMac getHMAC() {
|
||||||
return new HMac(new SHA256Digest());
|
return new HMac(new SHA256Digest());
|
||||||
|
@ -32,6 +34,6 @@ public class ScramSha256 extends ScramMechanism {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMechanism() {
|
public String getMechanism() {
|
||||||
return "SCRAM-SHA-256";
|
return MECHANISM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package eu.siacs.conversations.crypto.sasl;
|
||||||
|
|
||||||
|
import org.bouncycastle.crypto.Digest;
|
||||||
|
import org.bouncycastle.crypto.digests.SHA512Digest;
|
||||||
|
import org.bouncycastle.crypto.macs.HMac;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.entities.Account;
|
||||||
|
import eu.siacs.conversations.xml.TagWriter;
|
||||||
|
|
||||||
|
public class ScramSha512 extends ScramMechanism {
|
||||||
|
|
||||||
|
public static final String MECHANISM = "SCRAM-SHA-512";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected HMac getHMAC() {
|
||||||
|
return new HMac(new SHA512Digest());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Digest getDigest() {
|
||||||
|
return new SHA512Digest();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScramSha512(final TagWriter tagWriter, final Account account, final SecureRandom rng) {
|
||||||
|
super(tagWriter, account, rng);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPriority() {
|
||||||
|
return 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMechanism() {
|
||||||
|
return MECHANISM;
|
||||||
|
}
|
||||||
|
}
|
|
@ -64,6 +64,7 @@ import eu.siacs.conversations.crypto.sasl.Plain;
|
||||||
import eu.siacs.conversations.crypto.sasl.SaslMechanism;
|
import eu.siacs.conversations.crypto.sasl.SaslMechanism;
|
||||||
import eu.siacs.conversations.crypto.sasl.ScramSha1;
|
import eu.siacs.conversations.crypto.sasl.ScramSha1;
|
||||||
import eu.siacs.conversations.crypto.sasl.ScramSha256;
|
import eu.siacs.conversations.crypto.sasl.ScramSha256;
|
||||||
|
import eu.siacs.conversations.crypto.sasl.ScramSha512;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.entities.Message;
|
import eu.siacs.conversations.entities.Message;
|
||||||
import eu.siacs.conversations.entities.ServiceDiscoveryResult;
|
import eu.siacs.conversations.entities.ServiceDiscoveryResult;
|
||||||
|
@ -870,20 +871,21 @@ public class XmppConnection implements Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void authenticate() throws IOException {
|
private void authenticate() throws IOException {
|
||||||
final List<String> mechanisms = extractMechanisms(streamFeatures
|
final List<String> mechanisms = extractMechanisms(streamFeatures.findChild("mechanisms"));
|
||||||
.findChild("mechanisms"));
|
|
||||||
final Element auth = new Element("auth", Namespace.SASL);
|
final Element auth = new Element("auth", Namespace.SASL);
|
||||||
if (mechanisms.contains("EXTERNAL") && account.getPrivateKeyAlias() != null) {
|
if (mechanisms.contains(External.MECHANISM) && account.getPrivateKeyAlias() != null) {
|
||||||
saslMechanism = new External(tagWriter, account, mXmppConnectionService.getRNG());
|
saslMechanism = new External(tagWriter, account, mXmppConnectionService.getRNG());
|
||||||
} else if (mechanisms.contains("SCRAM-SHA-256")) {
|
} else if (mechanisms.contains(ScramSha512.MECHANISM)) {
|
||||||
|
saslMechanism = new ScramSha512(tagWriter, account, mXmppConnectionService.getRNG());
|
||||||
|
} else if (mechanisms.contains(ScramSha256.MECHANISM)) {
|
||||||
saslMechanism = new ScramSha256(tagWriter, account, mXmppConnectionService.getRNG());
|
saslMechanism = new ScramSha256(tagWriter, account, mXmppConnectionService.getRNG());
|
||||||
} else if (mechanisms.contains("SCRAM-SHA-1")) {
|
} else if (mechanisms.contains(ScramSha1.MECHANISM)) {
|
||||||
saslMechanism = new ScramSha1(tagWriter, account, mXmppConnectionService.getRNG());
|
saslMechanism = new ScramSha1(tagWriter, account, mXmppConnectionService.getRNG());
|
||||||
} else if (mechanisms.contains("PLAIN") && !account.getJid().getDomain().toEscapedString().equals("nimbuzz.com")) {
|
} else if (mechanisms.contains(Plain.MECHANISM) && !account.getJid().getDomain().toEscapedString().equals("nimbuzz.com")) {
|
||||||
saslMechanism = new Plain(tagWriter, account);
|
saslMechanism = new Plain(tagWriter, account);
|
||||||
} else if (mechanisms.contains("DIGEST-MD5")) {
|
} else if (mechanisms.contains(DigestMd5.MECHANISM)) {
|
||||||
saslMechanism = new DigestMd5(tagWriter, account, mXmppConnectionService.getRNG());
|
saslMechanism = new DigestMd5(tagWriter, account, mXmppConnectionService.getRNG());
|
||||||
} else if (mechanisms.contains("ANONYMOUS")) {
|
} else if (mechanisms.contains(Anonymous.MECHANISM)) {
|
||||||
saslMechanism = new Anonymous(tagWriter, account, mXmppConnectionService.getRNG());
|
saslMechanism = new Anonymous(tagWriter, account, mXmppConnectionService.getRNG());
|
||||||
}
|
}
|
||||||
if (saslMechanism != null) {
|
if (saslMechanism != null) {
|
||||||
|
|
Loading…
Reference in a new issue