aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/de/pixart
diff options
context:
space:
mode:
authorChristian Schneppe <christian@pix-art.de>2018-10-01 11:04:59 +0200
committerChristian Schneppe <christian@pix-art.de>2018-10-01 11:04:59 +0200
commit4a8df17311f2e937840f71b3c1590bbe06fe2393 (patch)
tree25a1d72f1dc3b7fa45235d00172cad5f1e0916f3 /src/main/java/de/pixart
parente1738faaddf2ae3a10ed14b8356db3f46053d303 (diff)
Fix auth when upgrading from SCRAM-SHA-1 to -256
Diffstat (limited to 'src/main/java/de/pixart')
-rw-r--r--src/main/java/de/pixart/messenger/crypto/sasl/ScramMechanism.java104
1 files changed, 52 insertions, 52 deletions
diff --git a/src/main/java/de/pixart/messenger/crypto/sasl/ScramMechanism.java b/src/main/java/de/pixart/messenger/crypto/sasl/ScramMechanism.java
index 046b68fda..a7a063409 100644
--- a/src/main/java/de/pixart/messenger/crypto/sasl/ScramMechanism.java
+++ b/src/main/java/de/pixart/messenger/crypto/sasl/ScramMechanism.java
@@ -22,28 +22,16 @@ import de.pixart.messenger.xml.TagWriter;
abstract class ScramMechanism extends SaslMechanism {
// 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 String clientFirstMessageBare;
- private final String clientNonce;
- private byte[] serverSignature = null;
- static HMac HMAC;
- static Digest DIGEST;
private static final byte[] CLIENT_KEY_BYTES = "Client Key".getBytes();
private static final byte[] SERVER_KEY_BYTES = "Server Key".getBytes();
-
- private static class KeyPair {
- final byte[] clientKey;
- final byte[] serverKey;
-
- KeyPair(final byte[] clientKey, final byte[] serverKey) {
- this.clientKey = clientKey;
- this.serverKey = serverKey;
- }
- }
+ private static final LruCache<String, KeyPair> CACHE;
+ static HMac HMAC;
+ static Digest DIGEST;
static {
CACHE = new LruCache<String, KeyPair>(10) {
protected KeyPair create(final String k) {
- // Map keys are "bytesToHex(JID),bytesToHex(password),bytesToHex(salt),iterations".
+ // Map keys are "bytesToHex(JID),bytesToHex(password),bytesToHex(salt),iterations,SASL-Mechanism".
// Changing any of these values forces a cache miss. `CryptoHelper.bytesToHex()'
// is applied to prevent commas in the strings breaking things.
final String[] kparts = k.split(",", 4);
@@ -62,9 +50,10 @@ abstract class ScramMechanism extends SaslMechanism {
};
}
- private static final LruCache<String, KeyPair> CACHE;
-
+ private final String clientNonce;
protected State state = State.INITIAL;
+ private String clientFirstMessageBare;
+ private byte[] serverSignature = null;
ScramMechanism(final TagWriter tagWriter, final Account account, final SecureRandom rng) {
super(tagWriter, account, rng);
@@ -74,6 +63,41 @@ abstract class ScramMechanism extends SaslMechanism {
clientFirstMessageBare = "";
}
+ private static synchronized byte[] hmac(final byte[] key, final byte[] input)
+ throws InvalidKeyException {
+ HMAC.init(new KeyParameter(key));
+ HMAC.update(input, 0, input.length);
+ final byte[] out = new byte[HMAC.getMacSize()];
+ HMAC.doFinal(out, 0);
+ return out;
+ }
+
+ public static synchronized byte[] digest(byte[] bytes) {
+ DIGEST.reset();
+ DIGEST.update(bytes, 0, bytes.length);
+ final byte[] out = new byte[DIGEST.getDigestSize()];
+ DIGEST.doFinal(out, 0);
+ return out;
+ }
+
+ /*
+ * Hi() is, essentially, PBKDF2 [RFC2898] with HMAC() as the
+ * pseudorandom function (PRF) and with dkLen == output length of
+ * HMAC() == output length of H().
+ */
+ private static synchronized byte[] hi(final byte[] key, final byte[] salt, final int iterations)
+ throws InvalidKeyException {
+ byte[] u = hmac(key, CryptoHelper.concatenateByteArrays(salt, CryptoHelper.ONE));
+ byte[] out = u.clone();
+ for (int i = 1; i < iterations; i++) {
+ u = hmac(key, u);
+ for (int j = 0; j < u.length; j++) {
+ out[j] ^= u[j];
+ }
+ }
+ return out;
+ }
+
@Override
public String getClientFirstMessage() {
if (clientFirstMessageBare.isEmpty() && state == State.INITIAL) {
@@ -120,7 +144,7 @@ abstract class ScramMechanism extends SaslMechanism {
nonce = token.substring(2);
break;
case 'm':
- /*
+ /*
* RFC 5802:
* m: This attribute is reserved for future extensibility. In this
* version of SCRAM, its presence in a client or a server message
@@ -147,12 +171,13 @@ abstract class ScramMechanism extends SaslMechanism {
final byte[] authMessage = (clientFirstMessageBare + ',' + new String(serverFirstMessage) + ','
+ clientFinalMessageWithoutProof).getBytes();
- // Map keys are "bytesToHex(JID),bytesToHex(password),bytesToHex(salt),iterations".
+ // Map keys are "bytesToHex(JID),bytesToHex(password),bytesToHex(salt),iterations,SASL-Mechanism".
final KeyPair keys = CACHE.get(
CryptoHelper.bytesToHex(account.getJid().asBareJid().toString().getBytes()) + ","
+ CryptoHelper.bytesToHex(account.getPassword().getBytes()) + ","
+ CryptoHelper.bytesToHex(salt.getBytes()) + ","
+ String.valueOf(iterationCount)
+ + getMechanism()
);
if (keys == null) {
throw new AuthenticationException("Invalid keys generated");
@@ -188,7 +213,7 @@ abstract class ScramMechanism extends SaslMechanism {
}
state = State.VALID_SERVER_RESPONSE;
return "";
- } catch(Exception e) {
+ } catch (Exception e) {
throw new AuthenticationException("Server final message does not match calculated final message");
}
default:
@@ -196,38 +221,13 @@ abstract class ScramMechanism extends SaslMechanism {
}
}
- private static synchronized byte[] hmac(final byte[] key, final byte[] input)
- throws InvalidKeyException {
- HMAC.init(new KeyParameter(key));
- HMAC.update(input, 0, input.length);
- final byte[] out = new byte[HMAC.getMacSize()];
- HMAC.doFinal(out, 0);
- return out;
- }
-
- public static synchronized byte[] digest(byte[] bytes) {
- DIGEST.reset();
- DIGEST.update(bytes, 0, bytes.length);
- final byte[] out = new byte[DIGEST.getDigestSize()];
- DIGEST.doFinal(out, 0);
- return out;
- }
+ private static class KeyPair {
+ final byte[] clientKey;
+ final byte[] serverKey;
- /*
- * Hi() is, essentially, PBKDF2 [RFC2898] with HMAC() as the
- * pseudorandom function (PRF) and with dkLen == output length of
- * HMAC() == output length of H().
- */
- private static synchronized byte[] hi(final byte[] key, final byte[] salt, final int iterations)
- throws InvalidKeyException {
- byte[] u = hmac(key, CryptoHelper.concatenateByteArrays(salt, CryptoHelper.ONE));
- byte[] out = u.clone();
- for (int i = 1; i < iterations; i++) {
- u = hmac(key, u);
- for (int j = 0; j < u.length; j++) {
- out[j] ^= u[j];
- }
+ KeyPair(final byte[] clientKey, final byte[] serverKey) {
+ this.clientKey = clientKey;
+ this.serverKey = serverKey;
}
- return out;
}
} \ No newline at end of file