private void send_client_DH_inner_data(long retry_id) { byte[] b_data = new byte[256]; Common.random.nextBytes(b_data); BigInteger b = new BigInteger(1, b_data); BigInteger g_b = g.modPow(b, dh_prime); Common.logError( "g_b length: " + g_b.toByteArray().length + " -> " + Common.toBytes(g_b).length); BigInteger akey = g_a.modPow(b, dh_prime); Common.logError("auth_key: " + akey.toString()); setAuthKey(Common.toBytes(akey)); // gen data (client_DH_inner_data) TL.Object data_obj = TL.newObject("client_DH_inner_data", cl_nonce, sv_nonce, retry_id, g_b); byte[] data = data_obj.serialize(); byte[] hash = Common.getSHA1(data); byte[] data_with_hash = new byte[(hash.length + data.length + 15) / 16 * 16]; System.arraycopy(hash, 0, data_with_hash, 0, hash.length); System.arraycopy(data, 0, data_with_hash, hash.length, data.length); // send set_client_DH_params TL.Object req_obj = TL.newObject("set_client_DH_params", cl_nonce, sv_nonce, aes.IGE(data_with_hash, true)); send(req_obj, false, false); }
public void setAuthKey(byte[] value) { if (value == null || value.length == 0) { auth_key = new byte[0]; auth_key_aux_hash = auth_key_id = 0; return; } auth_key = value; dcState.set("auth_key", auth_key); byte[] auth_hash = Common.getSHA1(auth_key); auth_key_aux_hash = Common.toLong(Common.ASUB(auth_hash, 0, 8)); auth_key_id = Common.toLong(Common.ASUB(auth_hash, 12, 8)); }
private void TL_ResPQ(TL.Object obj) { sv_nonce = obj.getBytes("server_nonce"); BigInteger pq = new BigInteger(1, obj.getBytes("pq")); TL.Vector v_fp = obj.getVector("server_public_key_fingerprints"); fp = v_fp.getLong(0); Common.logError("pq: " + pq.toString()); // prime factorization for pq BigInteger q = Common.rho(pq); BigInteger p = pq.divide(q); if (p.compareTo(q) > 0) { BigInteger t = p; p = q; q = t; } SecureRandom rnd = new SecureRandom(); new_nonce = new byte[32]; rnd.nextBytes(new_nonce); // generate encrypted_data TL.Object data_obj = TL.newObject("p_q_inner_data", pq, p, q, cl_nonce, sv_nonce, new_nonce); byte[] data = data_obj.serialize(); byte[] hash = Common.getSHA1(data); byte[] data_with_hash = new byte[255]; System.arraycopy(hash, 0, data_with_hash, 0, hash.length); System.arraycopy(data, 0, data_with_hash, hash.length, data.length); GEN_random_bytes(data_with_hash, data.length + hash.length, 255); byte[] encrypted_data = Common.RSA(RSA_MODULUS, RSA_EXPONENT, data_with_hash); // req_DH_params TL.Object req_obj = TL.newObject("req_DH_params", cl_nonce, sv_nonce, p, q, fp, encrypted_data); send(req_obj, false, false); }
public synchronized boolean sendMessage(Message msg) { if (msg == null) return false; if (!connected || (msg.encrypted && (auth_key == null || auth_key.length == 0)) || bad_seq) { Common.logError("add to queue " + connected + " " + msg.encrypted); TLMessageQueue.add(msg); return false; } ByteBuffer b = null; Common.logInfo("message send: " + msg.obj.name + ":" + msg.obj.type); byte[] msg_data = msg.obj.serialize(); /* if (msg_data.length > 255) { Common.logError("compress..."); byte[] data = Common.gzipDeflate(msg_data); // TODO: compress message data if (data.length < msg_data.length && data.length > 32) msg_data = TL.newObject("gzip_packed", data).serialize(); } */ if (msg.encrypted) { long message_id = GEN_message_id(); TLMessage.put(message_id, msg); int size_real = 32 + msg_data.length; int size_padding = (size_real + 15) / 16 * 16; ByteBuffer p = BufferAlloc(size_padding); p.putLong(server_salt); p.putLong(session); p.putLong(message_id); if (msg.accept) seqno++; p.putInt(seqno); if (msg.accept) seqno++; p.putInt(msg_data.length); p.put(msg_data); byte[] data = p.array(); GEN_random_bytes(data, p.position(), data.length); // encrypt data byte[] msg_key = Common.ASUB(Common.getSHA1(Common.ASUB(data, 0, size_real)), 4, 16); synchronized (aes) { aes.prepare(true, msg_key, auth_key); data = aes.IGE(data, true); } // write encrypted packet b = BufferAlloc(24 + data.length); b.putLong(auth_key_id); b.put(msg_key); b.put(data); } else { b = BufferAlloc(20 + msg_data.length); b.putLong(0); b.putLong(GEN_message_id()); b.putInt(msg_data.length); b.put(msg_data); } try { synchronized (transport) { transport.send(b.array()); return true; } } catch (Exception e) { return false; } }