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 #