Sobre o algoritmo TEA

07 March, 2005

O algoritmo TEA foi criado por David Wheeler e Roger Needham no laboratório de computação da Universidade de Cambridge, Inglaterra, em novembro de 1994. A idéia principal dos autores foi criar um algoritmo seguro que, ao mesmo tempo, fosse fácil de ser implementado nas mais diversas linguagens de programação, pequeno e por isto facilmente guardado de memória pelos programadores, de execução rápida e que consumisse poucos recursos das máquinas. Parece que conseguiram… Também é importante frisar que este algoritmo não é patenteado (domínio público).

Este texto trata apenas da primeira versão do TEA, um algoritmo do tipo Feistel que faz uso de operações de vários grupos algébricos – XOR, ADD e SHIFT. Esta é uma forma muito engenhosa de obter as propriedades de difusão e confusão, os dois componentes essenciais da segurança da cifra, sem a necessidade de usar P-boxes (caixas de permutação para gerar difusão) ou S-boxes (caixas de substituição para gerar confusão).

O TEA cifra blocos de 64 bits de dados usando uma chave de 128 bits. Parece ser bastante resistente à criptoanálise diferencial e adquire uma difusão completa (quando a diferença de um bit no texto claro causa aproximadamente 32 bits de diferença no texto cifrado) após seis ciclos. Por ser muito curto e simples, a velocidade de processamento impressiona.

De acordo com os autores, este algoritmo pode substituir o DES com vantagens. Além disso, apesar de ter 32 ciclos (64 etapas Feistel) e apesar da velocidade de processamento não ser o principal objetivo, o TEA é três vezes mais rápido que o melhor software de implementação de DES com 16 etapas. Todos os modos de uso do DES também são aplicáveis ao TEA. O número de ciclos pode variar ou até fazer parte da chave. Os autores também sugerem que a segurança pode ser aumentada quando se aumenta o número de iterações.

De acordo com o Prof. Simon Shepher, da Universidade de Bradford, Inglaterra, a segurança do TEA é muito boa, salientando que, até o momento (fevereiro de 2006), não se obteve sucesso com nenhum tipo de criptoanálise. Acredita-se que o TEA seja tão seguro quanto o algoritmo IDEA, projetado por Massey e Xuenjia Lai. Usa a mesma técnica de grupos algébricos misturados, mas é muito mais simples e, por isto mesmo, muito mais rápido. Além disso é de domínio público, enquanto que o IDEA foi patenteado pela Ascom-Tech AG na Suíça. Parece que o professor é um fã de carteirinha do TEA. Louva seu tamanho diminuto, sua velocidade, sua segurança e ressalta que “também é um ótimo gerador de números randômicos que pode ser usado em simulações Monte Carlo e afins”.

abaixo um exemplo do algaritmo em PHP:

 


class crypto{

var $keyPhrase = "";
var $input = "";
var $output = "";

function encryption_keyer($txt, $encrypt_key) {
$ctr = 0;
$tmp = "";
$txt_len = strlen($txt);

for ($i = 0; $i < $txt_len; $i++) {
if ($ctr == strlen($encrypt_key)) $ctr = 0;
$tmp .= substr($txt, $i, 1) ^ substr($encrypt_key, $ctr, 1);
$ctr++;
}

return $tmp;
}

function encrypt_string() {
$txt = $this->input;
$key = $this->keyPhrase;

srand((double)microtime()*1000000);
$encrypt_key = md5(rand(0,32000));
$ctr = 0;
$tmp = "";
$txt_len = strlen($txt);

for ($i=0; $i < $txt_len; $i++) {
if ($ctr == strlen($encrypt_key)) $ctr = 0;
$tmp.= substr($encrypt_key, $ctr, 1) . (substr($txt, $i, 1) ^ substr($encrypt_key, $ctr, 1));
$ctr++;
}

$hash = $this->encryption_keyer($tmp, $key);
$hashLen = strlen($hash);
$hexa = "";

for ($j=0; $j < $hashLen; $j++) {
$tmpH = base_convert((ord(substr($hash, $j, 1))), 10, 16);
$hexa .= (strlen($tmpH) < 2) ? "0$tmpH" : "$tmpH";
}

$this->output = $hexa;
}

function decrypt_string() {
$txt = $this->input;
$key = $this->keyPhrase;

$hexaLen = strlen($txt);
$hash = "";

for ($j = 0; $j < $hexaLen; $j++) {
$tmpHex = substr($txt, $j, 2);
$tempOrd = base_convert($tmpHex, 16, 10);
$hash .= chr($tempOrd);
$j++;
}

$hashd = $this->encryption_keyer($hash, $key);

$tmp = "";
$txt_len = strlen($hashd);

for ($i = 0; $i < $txt_len; $i++) {
$md5 = substr($hashd, $i, 1);
$i++;
$tmp .= (substr($hashd, $i, 1) ^ $md5);
}

$this->output = $tmp;
}
}

$k = new crypto();
$k->keyPhrase = "pedrofilho";
$k->input = "Jesus Voltara";
$k->encrypt_string();
$dest = $k->output;

echo "texto *Jesus Voltara* com criptografia TEA com *pedrofilho* como senha:\n\n" .$dest;

$w = new crypto();
$w->keyPhrase = "pedrofilho";
$w->input = $dest;
$w->decrypt_string();
$dest = $w->output;

echo "\n\n" .$dest;

o mais legal desse algoritmo é a velocidade.

Identificador Universal Original (UUID)

07 March, 2005

Um identificador universal original (UUID) é um padrão do identificador usado na construção do software, criado pela fundação de software aberto (OSF) como parte do Distributed Computing Environment (DCE).

A intenção de UUIDs é permitir sistemas distribuídos de identificar excepcionalmente a informação sem coordenação central significativa.

Assim, qualquer um pode criar um UUID e usá-lo para identificar algo com confiança razoável que o identificador que esta sendo usado nunca irar se repetir mesmo involuntariamente por qualquer um para qualquer outra coisa. A informação etiquetada com UUIDs pode conseqüentemente mais tarde ser combinada em uma única base de dados sem precisar de resolver os conflitos conhecidos. O uso o mais difundido deste padrão está em identificadores originais de Microsoft global – (GUIDs). Outros usos significativos incluem o filesystem de ext2/ext3 do linux, as divisórias cifradas LUKS, o GNOME, os KDE, e o Mac OS X, que usam as execuções derivadas da biblioteca do uuid encontrada no pacote de e2fsprogs.

Definição:

Um UUID é (128-bit) um número 16-byte. O número de UUIDs teórica possível é conseqüentemente 216 o × 8 = 2128 = 25616 ou aproximadamente 3.4 o × 1038. Isto significa que 1 trilhão UUIDs teriam que ser criados cada nanossegundo por ligeiramente mais de 10 bilhão anos para esgotar o número de UUIDs.

Em seu formulário canônico, um UUID consiste em 32 dígitos hexadecimal indicado em 5 grupos separados por hífens, no formulário 8-4-4-4-12 para um total de 36 caráteres (32 dígitos e 4 “-”). Por exemplo:

550e8400-e29b-41d4-a716-446655440000

Um UUID pode igualmente ser usado com um identificador específico usado intencionalmente repetidamente para identificar a mesma coisa em contextos diferentes. Por exemplo, no modelo de objeto componente de Microsoft, cada componente deve executar a relação de IUnknown, que é feita criando um UUID que representa IUnknown. Em todos os casos onde quer que IUnknown seja usado, se está sendo usado por um processo que tenta alcançar a relação de IUnknown em um componente, ou por um componente que executa a relação de IUnknown, é provido sempre pelo mesmo identificador: 00000000-0000-0000-C000-000000000046.
Versão 1 (MAC address)

Conceptual, (versão 1) o esquema original da geração para UUIDs era concatenar a versão de UUID com o MAC address do computador que está gerando o UUID, e com o número dos intervalos 100-nanosegundos desde a adoção do calendário gregoriano no oeste. Na prática, o algoritmo real é mais complicado. Este esquema foi criticado que não é suficientemente “opaco”; revela a identidade do computador que gerou o UUID e o tempo em que fêz assim.
Versão 2 (segurança do DCE)

A versão 2 UUIDs é similar à versão 1 UUIDs, com o byte superior da seqüência do pulso de disparo substituída pelo identificador para “domínio local” (tipicamente de “domínio POSIX UID” ou de “domínio POSIX GID”) e os primeiros 4 bytes do timestamp substituído por POSIX UID ou GID do usuário (com “a indicação do identificador do domínio local”).
Versão 3 (mistura MD5)

Uso de UUIDs da versão 3 um esquema que deriva um UUID através de MD5 de um URL, um Fully Qualified Domain Name, um identificador do objeto, um distinto nome (DN um pouco usado no Directory Access Protocol ), ou em nomes em namespaces nãos especificado. A versão 3 UUIDs tem o formulário xxxxxxxx-xxxx-3xxx-xxxx-xxxxxxxxxxxx com dígitos hexadecimais x.

Para determinar a versão 3 UUID de um nome dado o UUID do namespace, por exemplo 6ba7b810-9dad-11d1-80b4-00c04fd430c8 para um domínio, é transformado a uma corda dos bytes que correspondem a seus dígitos hexadecimais, concatenada com o nome da entrada, junto com o MD5 que rende 128 partes. Seis partes são substituídas pelos valores fixos, quatro destas indicam a versão, 0011 para a versão 3. A mistura fixa é transformada finalmente de novo no formulário hexadecimal com os hífens que separam as peças relevantes em outras versões de UUID.
Versão 4 (aleatória)

Uso de UUIDs da versão 4 um esquema que confia somente em números aleatórios. Este algoritmo ajusta o número de versão assim como duas partes reservadas. Todo o restante são ajustados usando uma origem de dados aleatória ou pseudo-randonicos. A versão 4 UUIDs tem o formulário xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx com dígitos hexadecimais x e os dígitos hexadecimais 8, 9, o A, ou o B para Y, exemplo:

f47ac10b-58cc-4372-a567-0e02b2c3d479.
Versão 5 (mistura SHA-1)

Uso de UUIDs da versão 5 um esquema com hashing SHA-1, se não é a mesma idéia que em RFC 4122 da versão 3. indica que a versão 5 está referida sobre a versão 3 UUIDs baseada em nome.
Probabilidade aleatória de UUID duplicatas

UUIDs aleatória gerado como aqueles gerados pela classe de java.util.UUID tem 122 partes aleatórias. Há 128 partes completamente com as 4 partes que estão sendo usados para a versão (“UUID aleatória gerado”), e 2 partes para a variação (“Lixivie-Salz “). Com UUIDs aleatório, a possibilidade de dois que têm o mesmo valor pode ser calculada usando a teoria de probabilidade (paradoxo de aniversário).

68.719.476.736 = 236 / 0.0000000000000004 (4 × 10−16)

2.199.023.255.552 = 241 / 0.0000000000004 (4 × 10−13)

70.368.744.177.664 = 246 / 0.0000000004 (4 × 10−10)

Para por estes números na perspectiva, seu risco anual de batida por um meteorito é estimado para ser uma possibilidade em 17 bilhões, que significa que a probabilidade é aproximadamente 0.00000000006 (6 × 10−11), equivalente às probabilidades de criar alguns dez dos trilhões de UUIDs em um ano e de ter uma duplicata. Ou seja, somente depois a geração de 1 bilhão UUIDs a cada segundo pelos próximos 100 anos, a probabilidade de criar apenas uma duplicata seria aproximadamente 50%. A probabilidade de uma duplicata seria aproximadamente 50% assim cada pessoa na terra possui 600 milhões UUIDs.

Entretanto, estas probabilidades prendem somente para geradores criptograficamente seguros do número pseudo-randonicos. Estes devem ser usados para gerar os valores, se não a probabilidade das duplicatas pode ser significativamente mais elevada, desde que a dispersão estatística pode ser mais baixa.
História

O projeto inicial de DCE UUIDs foi baseado em UUIDs como definido no sistema de computação de rede, cujo o projeto por sua vez foi inspirado pelos identificadores originais (64-bit) definido e usado pervasively em Domain/OS, o sistema de exploração projetado pela Apollo Computer Inc.

abaixo codigo para gerar UUID versão 4 em PHP:

 

function uuid() {
return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand(0, 0xffff), mt_rand(0, 0xffff),
mt_rand(0, 0xffff),
mt_rand(0, 0x0fff) | 0x4000,
mt_rand(0, 0x3fff) | 0x8000,
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff));
}

echo uuid();

VPN com Mikrotik

07 March, 2005

Uma Rede Particular Virtual (Virtual Private Network – VPN)é uma rede de comunicações privada normalmente utilizada por umaempresa ou um conjunto de empresas e/ou instituições, construída emcima de uma rede de comunicações pública (como por exemplo, a Internet). O tráfego de dados é levado pela rede pública utilizando protocolos padrão, não necessariamente seguros.

Criação de VPN entre matriz e filial de uma empresa usando servidores Mikrotik nas duas pontas.

Levando em consideração a seguinte estrutura:

Matriz:

* Rede Local: 192.168.0.X/24
* Ip local do Servidor: 192.168.0.1
* Ip Internet do Servidor: 201.200.200.200

Filial:

* Rede Local: 192.168.10.X/24
* Ip local do Servidor: 192.168.10.1
* Ip Internet do Servidor: 189.50.1.200

VPN:

* Faixa IPs: 10.0.0.X/24

Configurações
Partindo do ponto de que os dois servidores já estão devidamente configurados e navegando na Internet repassando a navegação para redeInterna e seus clientes via NAT, iremos configurar o Server VPN namatriz.

Antes de mais nada, devemos habilitar duas opções no menu Ip> firewall > Service Ports, clique com o botão direito eselecione enable em “GRE” e “PPTP”.

Abra o servidor Mikrotik pelo winbox, acesse o menu ppp. Naprimeira guia Interfaces clique na opção PPTP Server marque a opção enable.

Na segunda guia, “secrets”, crie um usuário para conectar ao Server pela VPN:

Usuário: teste
Senha: teste
Local address: 10.0.0.1
Remote address: 10.0.0.2

Dessa forma seu servidor estará preparado para ouvir e autenticar requisições PPTP. Ainda falta configurar as rotas nesseservidor para que as máquinas internas possam ver a outra rede e vice-versa. Vá em Ip > routes e crie as duas rotas abaixo:

Primeira Rota: 10.0.0.0/24 > gateway 192.168.0.1
Segunda Rota: 192.168.10.0/24> Gateway 10.0.0.2

A rota 10.0.0.0/24 apontando para o gateway 192.168.0.1 indicaque a rede usada pela vpn será roteada pelo ip 192.168.0.1 que é daplaca interna do servidor e a rota 192.168.10.0/24 indica que a rede interna do servidor da filial será roteada pelo ip remoto que o servidor da filial receberá quando conectar.

Configuramos o servidor da matriz, agora vamos para o servidor da Filial:

Vá em PPP, na aba Interfaces crie o usuário para se conectar conforme abaixo:

Server: 201.200.200.200
user: teste
password: teste

Clique em ok e logo o usuário já se conectará ao outro servidor, dessa forma você já poderá testar do próprio servidor Mikrotik se está pingando para o IP de alguma maquina na rede internada matriz.

Para que suas máquinas na Filial com a faixa 192.168.10.X possam acessar as máquinas da matriz você terá que criar a mesma estrutura de rotas que foi criada para na matriz só que direcionandopra sua rede interna, abaixo:

Primeira Rota: 10.0.0.0/24 > gateway 192.168.10.1
Segunda Rota: 192.168.0.0/24> Gateway 10.0.0.1

Bom pessoal, com isso estaremos com a vpn funcionando nos dois pontos caso queiram adicionar mais pontos é só seguir o mesmo raciocínio. Outra coisa, você pode também criar um usuário para acessarde qualquer máquina Windows diretamente em rede assistente para novas conexões e marcar a opção conectar-me a uma vpn.

Fazendo cache de dados MySQL com XCACHE

07 March, 2005

XCache é outro programa de cache por chave-valor onde o armazenamento é em memória como o memcached. Este recurso permite que você leve a memória uma variável e depois você pode chamar ela novamente facilmente somente usando a chave criada anteriormente.
Isso ajuda muito no controle do que realmente desejamos colocar em cache na memoria e a retornar, as funções do xcache para salvar e retornar um valor são xcache_set e xcache_get, tambem é possivel remover com xcache_unset, no exemplo do codigo abaixo a função mysql_queryCache mostra como funciona na pratica o cache de dados do MySQL, mais pode ser usado com outro banco como o SQLite ou até mesmo com arquivos de textos:

 

<?php
$connTeste = mysql_pconnect("localhost", "root", "vertrigo");
mysql_select_db("pedrofilho", $connTeste);
function mysql_queryCache($consulta, $tempo = 60) {
$chave = md5($consulta);
$query = xcache_get($chave);
if ($query == false) {
$query = mysql_query($consulta);
if (is_resource($query) && (($rows = mysql_num_rows($query)) !== 0)) {
for ($i=0; $i<$rows; $i++) {
$fields = mysql_num_fields($query);
$row = mysql_fetch_array($query);
for ($j=0; $j<$fields; $j++) {
if ($i === 0) {
$columns[$j] = mysql_field_name($query, $j);
}
$cache[$i][$columns[$j]] = $row[$j];
}
}
}
xcache_set($chave, $cache, $tempo);
return $cache;
}
return $query;
}
$query_rsCliente = "SELECT nome, telefone, email FROM clientes LIMIT 250";
$rsCliente = mysql_queryCache($query_rsCliente);
?>
<html>
<head>
<title> Clientes </title>
</head>
<body>
<H2> Relatorio de clientes </H2>
<table width="100%" border="0" cellpadding="1" bgcolor="#000000">
<tr bgcolor="#FFFF99">
<td>Nome</td>
<td>Telefone</td>
<td>E-Mail</td>
</tr>
<?php if (count($rsCliente) > 0) { ?>
<?php for ($i=0; $i<count($rsCliente); $i++) { ?>
<tr bgcolor="#FFFFFF">
<td><?php echo $rsCliente[$i]['nome']; ?></td>
<td><?php echo $rsCliente[$i]['telefone']; ?></td>
<td><?php echo $rsCliente[$i]['email']; ?></td>
</tr>
<?php } ?>
<?php } ?>
</table>
</body>
</html>

Flash ActionScript 3 API para Mikrotik RouterOS

07 March, 2005

O MikroTik, além de configuração de Apoio sobre Telnet / SSH / telnet-MAC. possui um chamado RouterOS API.

Através da API que você puder ler informações, configuração definidas e até mesmo eventos. Por exemplo, a lista a todos os usuários conectados dBm WLAN.

A API é “literatura aberta” e você está convidado a criar diferentes idiomas e bibliotecas para postar em seu site. Eles já têm PHP, Ruby, Perl, Java, implementações, etc, objetivo que eu queria ser capaz de criar um aplicativo do AIR do Flash para exibir e configurar roteadores. Então, eu criei um Flash ActionScript 3 classe para isso.

Abaixo uma classe ActionScript para acesso a API do MikroTik:

 

// ApiSocket.as
// RouterOS API class
// Author: Haikon Nessjore

package {

import flash.errors.*;
import flash.events.*;
import flash.utils.ByteArray;
import com.adobe.crypto.MD5;
import flash.net.Socket;

public class ApiSocket extends Socket {
static public var RECEIVED:String = "received";
static public var LOGIN:String = "loggedin";
private var cmd:String;
private var doLogin:int;
private var user:String;
private var password:String;
private var returnData:Array;
private var returnPos:int;
private var toread:int;
private var firstRe:int;
private var tag:String;
private var gotDone:Boolean;
private var gotTrap:Boolean;
private var gotFatal:Boolean;

public function ApiSocket(host:String, port:uint) {
super(host, port);
toread = 0;
doLogin = 0;
addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
}

public function login(u:String, p:String) {
doLogin = 1;
user = u;
password = p;
sendRequest("/login");
}

public function sendRequest(... outData):void {
returnData = new Array();
returnPos = 0;
firstRe = 0;
gotDone = false;
gotTrap = false;
gotFatal = false;
tag = "";
cmd = outData[0];
returnData[returnPos] = new Object();

for (var i:int = 0; i < outData.length; ++i) {
var data:ByteArray = new ByteArray();

var len:uint = outData[i].length;

if (len < 0x80)
data.writeByte(len);
else
if (len < 0x4000) {
len |= 0x8000;
data.writeByte(( len >> 8 ) & 0xff);
data.writeByte(len & 0xff);
} else
if (len < 0x200000) {
len |= 0xC00000;
data.writeByte(( len >> 16 ) & 0xff);
data.writeByte(( len >> 8 ) & 0xff);
data.writeByte(len & 0xff);
} else
if (len < 0x10000000) {
len |= 0xE0000000;
data.writeByte(( len >> 24 ) & 0xff);
data.writeByte(( len >> 16 ) & 0xff);
data.writeByte(( len >> 8 ) & 0xff);
data.writeByte( len & 0xff );
} else {
data.writeByte(0xF0);
data.writeByte(( len >> 24 ) & 0xff);
data.writeByte(( len >> 16 ) & 0xff);
data.writeByte(( len >> 8 ) & 0xff);
data.writeByte( len & 0xff );
}

writeBytes(data);
writeUTFBytes(outData[i]);
}
writeByte(0);
flush();
}

private function readResponse():void {
var len:int;

if (toread == 0) {
var len1:uint = readUnsignedByte();

if (len1 == 0) {
if (gotDone || gotTrap || gotFatal) {
if (doLogin == 1) {
if (returnData[0].ret) {
var chal:ByteArray = new ByteArray();
var md5:ByteArray = new ByteArray();

for (var i:int = 0; i < returnData[0].ret.length; i += 2) {
chal.writeByte(int("0x" + returnData[0].ret.substr(i,2)));
}

md5.writeByte(0);
md5.writeUTFBytes(password);
md5.writeBytes(chal);

doLogin++;
// Send challenge response
sendRequest("/login", "=name=" + user, "=response=00" + MD5.hashBytes(md5));
}
} else if (doLogin == 2) {
doLogin = 0;
dispatchEvent(new ApiEvent(ApiSocket.LOGIN, "", returnData, gotDone ? 'done' : (gotFatal ? 'fatal' : 'trap')));
} else {
dispatchEvent(new ApiEvent(ApiSocket.RECEIVED, tag, returnData, gotDone ? 'done' : (gotFatal ? 'fatal' : 'trap')));
}
}

if (bytesAvailable)
readResponse();
else
return;
}

if (len1 >= 0xF0) {
len = readUnsignedByte();
len = ( len << 8 ) + readUnsignedByte();
len = ( len << 8 ) + readUnsignedByte();
len = ( len << 8 ) + readUnsignedByte();
} else
if (len1 >= 0xE0) {
len = (( len1 & 15 ) << 8 ) + readUnsignedByte();
len = ( len << 8 ) + readUnsignedByte();
len = ( len << 8 ) + readUnsignedByte();
} else
if (len1 >= 0xC0) {
len = (( len1 & 31 ) << 8 ) + readUnsignedByte();
len = ( len << 8 ) + readUnsignedByte();
} else
if (len1 >= 0x80) {
len = (( len1 & 63 ) << 8 ) + readUnsignedByte();
} else
len = len1;

toread = len;
}

// Calculate how much data of the full length that is available right now
var slen:int = bytesAvailable > toread ? toread : bytesAvailable;
// Calculate how much data that has to be read later
toread = toread > bytesAvailable ? toread - bytesAvailable : 0;

// Read relevant data
var str:String = readUTFBytes(slen);

if (toread == 0) {
if (str == '!re') {
firstRe++;
if (firstRe > 1) {
returnPos++
returnData[returnPos] = new Object();
}
}
if (str == '!trap')
gotTrap = true;

if (str == '!fatal')
gotFatal = true;

if (str == '!done')
gotDone = true;

// Parse key-value pair
if (str.substr(0,1) == '=') {
var tmpPos:int = str.indexOf('=',1);
var tmpKey:String = str.substr(1,tmpPos-1);
var tmpVal:String = str.substr(tmpPos+1);
returnData[returnPos][tmpKey] = tmpVal;
}

// Reset tag
if (str.substr(0,1) == '!')
tag = "";

// Set tag
if (str.substr(0,5) == '.tag=')
tag = str.substr(5);

// Are there more packets available
if (bytesAvailable)
readResponse();
}

}

private function socketDataHandler(event:ProgressEvent):void {
readResponse();
}
}
}

// ApiEvent.as
//
// RouterOS API Event class
// Author: Håkon Nessjøen
// Date: 2. May 2009
//
package {

import flash.events.Event;

public class ApiEvent extends Event {
static public var RECEIVED:String = "received";
static public var LOGIN:String = "loggedin";

public var data:Array;
public var result:String;
public var tag:String;

public function ApiEvent(type:String, tg:String, dta:Array, res:String){
super(type);
data = dta;
result = res;
tag = tg;
}
}

}
Postagens recentes → Home ← Postagens antigas