package protocol.xmpp;
// #sijapp cond.if protocols_JABBER is "true" #
import com.ssttr.crypto.HMACSHA1;
import com.ssttr.crypto.SHA1;
import com.ssttr.crypto.MessageDigest;
import jimm.comm.StringUtils;
import jimm.comm.Util;
public class SASL_ScramSha1 {
String pass;
String cnonce;
String clientFirstMessageBare;
String lServerSignature;
HMACSHA1 hmac;
public String init(String jid, String password) {
this.pass = password;
cnonce = "jimm" + Util.nextRandInt();
clientFirstMessageBare = "n=" + Jid.getNick(jid) + ",r=" + cnonce;
System.out.println("n,," + clientFirstMessageBare);
return Util.base64encode(getBytes("n,," + clientFirstMessageBare));
}
public String response(String challenge) {
return Util.base64encode(getBytes(processServerMessage(challenge)));
}
public boolean success(String success) {
return lServerSignature.equals(success);
}
public SASL_ScramSha1() {
hmac = new HMACSHA1();
}
private void xorB(byte[] dest, byte[] source) {
int l = dest.length;
for (int i = 0; i < l; i++) {
dest[i] ^= source[i];
}
}
private String getAttribute(String[] attrs, char id) {
for (String attr : attrs) {
if (attr.charAt(0) == id) return attr.substring(2);
}
return null;
}
private String processServerMessage(String serverFirstMessage) {
String[] attrs = Util.explode(serverFirstMessage, ',');
int i = Integer.parseInt(getAttribute(attrs, 'i'));
String salt = getAttribute(attrs, 's');
String r = getAttribute(attrs, 'r');
byte[] pwd = getBytes(pass);
byte[] clientKey;
byte[] saltedPassword;
try {
byte[] bs = Util.base64decode(salt);
saltedPassword = hi(pwd, bs, i);
HMACSHA1 mac = getHMAC(saltedPassword);
byte[] ck = getBytes("Client Key");
clientKey = mac.hmac(ck);
} catch (Exception e) {
return null;
}
MessageDigest sha;
sha = new SHA1();
sha.init();
sha.update(clientKey);
sha.finish();
byte[] storedKey = sha.getDigestBits();
String clientFinalMessageWithoutProof = "c=biws,r=" + r;
String authMessage = clientFirstMessageBare + ","
+ serverFirstMessage + ","
+ clientFinalMessageWithoutProof;
byte[] clientSignature = getHMAC(storedKey).hmac(getBytes(authMessage));
byte[] clientProof = new byte[clientKey.length];
System.arraycopy(clientKey, 0, clientProof, 0, clientKey.length);
xorB(clientProof, clientSignature);
byte[] serverKey = getHMAC(saltedPassword).hmac(getBytes("Server Key"));
byte[] serverSignature = getHMAC(serverKey).hmac(getBytes(authMessage));
lServerSignature = "v=" + Util.base64encode(serverSignature);
return clientFinalMessageWithoutProof + ",p=" + Util.base64encode(clientProof);
}
private byte[] hi(byte[] str, byte[] salt, int i) {
HMACSHA1 mac = getHMAC(str);
byte[] ooo1 = {0, 0, 0, 1};
byte[] m = new byte[salt.length + 4];
System.arraycopy(salt, 0, m, 0, salt.length);
System.arraycopy(ooo1, 0, m, salt.length, 4);
byte[] U = mac.hmac(m);
byte[] dest = new byte[U.length];
System.arraycopy(U, 0, dest, 0, U.length);
i--;
while (i > 0) {
U = mac.hmac(U);
xorB(dest, U);
i--;
}
return dest;
}
private HMACSHA1 getHMAC(byte[] str) {
hmac.init(str);
return hmac;
}
private byte[] getBytes(String str) {
return StringUtils.stringToByteArrayUtf8(str);
}
}
// #sijapp cond.end #