User Tools

Site Tools


br-110-crypto


Processo de criptografia

Cada vez que um canal de informações é criado ou um dispositivo móvel é registrado, o Followzup cria um par de chaves assimétricas RSA, composta por uma chave pública e uma chave privada. A chave privada é mantida na base de dados do servidor Followzup e utilizada para ter acesso ao conteúdo das solicitações encaminhadas ao webservice.

As chaves públicas dos canais são inseridas na API no momento em que o desenvolvedor faz o download dessa API. No caso dos dispositivos móveis, a chave pública é enviada ao APP dentro de um string de resposta quando este solicita o registro inicial do dispositivo.

Com esse modelo, o desenvolvedor tem a segurança de que apenas sua aplicação estará enviando mensagens para seus assinantes, a menos que ocorra alguma falha de segurança no armazenamento da API. Da mesma forma, o usuário do dispositivo tem certeza de que ninguém estará enviando solicitações em seu nome, a menos que ocorra alguma falha de segurança no armazenamento da chave pública do dispositivo.

No caso de vazamento da chave pública, o desenvolvedor pode solicitar a criação de um novo par de chaves RSA e refazer o download da API. No caso do dispositivo, o usuário pode refazer o registro, ocasião em que recebe uma nova chave pública para seu dispositivo.

Conforme preconiza o protocolo de criptografia RSA, um string criptografado com a chave pública só pode ser decriptografado com a chave privada correspondente, e vice-versa. Com base nesse conceito, cada requisitante (canal de informações e dispositivos móveis), mantém consigo a sua chave pública, e a base de dados do Followzup (followzup.com), mantém as chaves privadas dos pares correspondentes. Em função da carga de CPU demandada pelo algoritmo RSA, esse protocolo é indicado para criptografar strings de tamanho limitado.

Além do protocolo de criptografia RSA, o processo de comunicação com o webservice também utiliza o protocolo AES. O protocolo AES, por sua vez, é indicado para criptografar strings de tamanho grande, em função do consumo reduzido de CPU demandado por seu algoritmo. Nesse processo, a criptografia AES utiliza uma chave aleatória de 192 bits que é criada para cada solicitação enviada ao webservice. Um string criptografado com uma chave AES deve ser decriptografado com a mesma chave.

O uso conjunto dos protocolos AES e RSA compõem a base de comunicação criptografada do Followzup. A seguir, a sequência do processo de criptografia e decriptografia dos strings de solicitações e respostas do webservice, partindo do requisitante (aplicação ou dispositivo).


O Requisitante faz a solicitação:

  1. Cria um string contendo o XML de solicitação a ser encaminhada ao webservice (comando e parâmetros);

  2. cria uma chave AES aleatória de 192 bits;

  3. criptografa o string contendo o XML de solicitação com a chave AES, por meio do protocolo de criptografia AES;

  4. criptografa a chave AES com sua chave pública, por meio do protocolo de criptografia RSA.

  5. codifica o string contendo o XML de solicitação e a chave AES (ambos criptografados), para o formato BASE64.

  6. submete o POST para o webservice, contendo as variáveis ID (identificação do requisitante), KEY (chave AES criptografada) e FRAME (string XML de solicitação criptografado).

O Webservice processa a solicitação:

  1. Extrai as variáveis ID, KEY e FRAME recebidos no POST, e decodifica as variáveis KEY e FRAME, que se encontram no formato BASE64;

  2. recupera a chave privada RSA do requisitante em sua base de dados, identificado pela variável ID;

  3. decriptografa a chave AES contida na variável KEY com a chave privada correspondente, por meio do protocolo de criptografia RSA, obtendo a chave AES decriptografada;

  4. decriptografa o string do XML de solicitação contido na variável FRAME, por meio do protocolo de criptografia AES, obtendo o string do XML de solicitação decriptografado;

  5. processa a solicitação do requisitante e monta o string contendo o XML de resposta da solicitação;

  6. criptografa o string do XML de resposta da solicitação com a mesma chave AES recebida do requisitante;

  7. codifica o XML de resposta da solicitação (criptografado), para o formato BASE64;

  8. calcula o hash MD5 do XML de resposta da solicitação criptografado e codificado em BASE64;

  9. retorna para o requisitante um XML de resposta do POST contendo os campos: retcode (código de retorno da solcitação), retframe (XML de resposta da solicitação criptografado e codificado em BASE64) e retmd5 (hash MD5 do campo retframe).

O Requisitante recebe a resposta:

  1. Recebe o resultado do POST (XML de resposta do POST) e verifica o código de retorno (campo retcode);

  2. calcula o hash MD5 do campo retframe e compara o resultado com o campo retmd5;

  3. decodifica o string XML de resposta da solicitação que se encontra no formato BASE64 (campo retframe);

  4. decriptografa o string XML de resposta da solicitação com a chave AES, obtendo o resultado de sua solicitação;

  5. o conteúdo do XML de resposta da solicitação, decriptografado varia em função do comando solicitado.



Tratamento dos dados no webservice

Para auxiliar o desenvolvimento de APIs e APPs, segue trecho da rotina de tratamento realizado pelo webservice para decriptação do XML de solicitação e encriptação do XML de resposta da solicitação. O webservice está escrito em PHP.

A decriptação da solicitação é realizada por meio da chave privada RSA armazenada na base de dados do Followzup, e que faz par com a chave pública RSA do canal ou do dispositivo. Abaixo, um par de chaves RSA para testes de comunicação, criptografia e decriptografia de dados:

//  Public RSA key (Base64)

$wpub64 = "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUExWU5qcGltUWxqczF6Qm9aNUhMcQozekFsMnR4cXE1aEFjK0E2ZVcreFE3TDRZNHZSWFBIZWdRSDV0WWJtU0FJclZiS3hGOE83VlFndWtIQmNqM1lUCmlCdzkvQ0dYbE5sekV1UkVNeHhITWZFQmNNdTdIVE1TeUJSOC80cmZvbVZZTWdoc3ZSOHVnSi82T1IzOThkZXgKV3ZiaDUxckhpWHdyOUZlcXN4Q3J3SmZvSStzMS85eVhEbUdOL2xaL1NwSjBZYjMyKytoR2J4VmtiRGZNSUNOdApPcytiTlJ2RFdiV0RjemxJK1E3SG8yZ0RrNjR3cEZuYlpNYW1mZ2VNaG5jelE2NjJhZ1g4ZEVzWTF0cHJXbFVoCkF2ejZyazFZOUNTSUpnakx2VXkvbWFlRnZzSGVJWnB1NUVhTXNZeDA3U2w0cFAxWjJxMVV6VThueHRxVTBYSjIKUlFJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==";

//  Public RSA key (Binary - module)

$wpubmodule = "d58363a62990963b35cc1a19e472eadf3025dadc6aab984073e03a796fb143b2f8638bd15cf1de8101f9b586e648022b55b2b117c3bb55082e90705c8f7613881c3dfc219794d97312e444331c4731f10170cbbb1d3312c8147cff8adfa2655832086cbd1f2e809ffa391dfdf1d7b15af6e1e75ac7897c2bf457aab310abc097e823eb35ffdc970e618dfe567f4a927461bdf6fbe8466f15646c37cc20236d3acf9b351bc359b583733948f90ec7a3680393ae30a459db64c6a67e078c86773343aeb66a05fc744b18d6da6b5a552102fcfaae4d58f424882608cbbd4cbf99a785bec1de219a6ee4468cb18c74ed2978a4fd59daad54cd4f27c6da94d1727645";

//  Public RSA key (Binary - index)

$wpubindex = "010001";

//  Private RSA key (Base64)

$wpri64 = "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2d0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktrd2dnU2xBZ0VBQW9JQkFRRFZnMk9tS1pDV096WE0KR2hua2N1cmZNQ1hhM0dxcm1FQno0RHA1YjdGRHN2aGppOUZjOGQ2QkFmbTFodVpJQWl0VnNyRVh3N3RWQ0M2UQpjRnlQZGhPSUhEMzhJWmVVMlhNUzVFUXpIRWN4OFFGd3k3c2RNeExJRkh6L2l0K2laVmd5Q0d5OUh5NkFuL281CkhmM3gxN0ZhOXVIbldzZUpmQ3YwVjZxekVLdkFsK2dqNnpYLzNKY09ZWTMrVm45S2tuUmh2ZmI3NkVadkZXUnMKTjh3Z0kyMDZ6NXMxRzhOWnRZTnpPVWo1RHNlamFBT1RyakNrV2R0a3hxWitCNHlHZHpORHJyWnFCZngwU3hqVwoybXRhVlNFQy9QcXVUVmowSklnbUNNdTlUTCtacDRXK3dkNGhtbTdrUm95eGpIVHRLWGlrL1ZuYXJWVE5UeWZHCjJwVFJjblpGQWdNQkFBRUNnZ0VBWkRHTjk1R1Z1Z243Q3RaTXhEbHhJbDhUeElxZXUvdHNjM1FMdktTL1NJZVoKckEwV3FFa1FJdlhzV2xUOWgxa05RTi9qM3NVSkNiUVhOY3lrZ3VYajhJRmdUUXJ1ZVBrNTJPbXBYMXFyeGpIVQpmVHY5aUl4SkNmOGpVVCs0QmhzTXNoM2wrVEhDdnJWVDFLM1FWMGJpZ1U5Tlh5WG9jUW9HRGxsOVR4NUptc3hTCkxDdGpWUlVTd0Fnb1d0OU5GTVVxTWJwSk1ZYmZiV3A3WEVUV2w1K1ZaRngxZEx6ZXg2anV1enE2b1piTi9SblcKMU9qcjJZdnhXNzBGQ3FFeEkray9uaXF4YjMxM2dDTXBmcDc1VFM3cGhaYmI1cEFZUWF5d3lpVkk4NjJkS0xNcQowR2UwdVNTZktYR3UrZTlxNjJ6M3NhbC82YTRJTnZoNDJXSHdrU29RQVFLQmdRRDdyUW00YndFN1ZqNERqZ3VzClAxWHdHRE11M2tZd2IzSGVOSGpDR2lIZUl1clNoZmovK3MvQlJLclhDZ2lRbHBlVWVrUE9oQllpdURMd0pLTWwKUUthWXl6eUJRVXo3NEU4WUpyb1d0UWhYK0xwS1pqTGFpd1JKTWFQT1FleU45Z0hMeFVRWDRFSWYyN3lVeU1DUApLZW1RRmR5bklJMlVMU1IvcUtMdDhZeE1SUUtCZ1FEWkxuOTRSSTM2aU1pZkczQm1YUk84dDZaTEo5YUZHMGFOCjFoNksvbGl2K1Z5dm9wMFU4VkkzOHo1RXJsNEJOZDdFeUJNR0RxK0xaTURiR0VNb3BrV0M0b0p0SlVUYkd5M2kKUmdHcVRMSTcyOXZTeUJoZlpacjB5K09COWVzeklvM2ZvdTdLT2lSSHluTmJTUysvSFhlbmNVMEFybElseGFMWApoRXcvQTRFaUFRS0JnUURGV0RrQUN1TGZZVSs5UDl1OVUraVNISmU5ejRNZ0piTVc5dlFkMTVubzhsNUpkODM1CkF2VjNhZDNBUXRqV2I0OHFXUGprYmNSaHN5Z1dEOVJ4dUpFcHpHdUVPdTBmc0JLMU1HREl2MmxzZWRleDBSTmQKTkpiR3dncmRCK3B5b28xaitDbmR3dloydnJuUHZON3BJNGRHZVM0TlNzUlpoVkJTWGF4c2dmUnVOUUtCZ1FDegpOaEpMYk01M29PMWpsV0hQcGhpR1RranpsV0VJSHpTK0Q2VE9id2xCMUpQdC9sSittSStPeWJKbFBEa242SXIxCmVGOXlUU1gvOFZqT3NodWc3R3RKa0oydGNPWjdvdGJlODRPbVFubUV1V3lRWnpydFpVdFRtdmNXSTVZOGNOUC8KYVZTQUhUQVk2Vzc5TWN3cmVTWm1UakVMVWMxSmkrZE96Y1dZN2N4ZUFRS0JnUURzUnZDZTlIS2lKUzdBWlRjbApzbUZEaFBKcFN0Z2tJM1JRZHB0ay94NUQ1QlBLa3FIN0gveFhPc0owYk8wVExHY2FOUEJRRVpKQVA5LzBiZHFGCnY1NDlaVE5RZXhOVjR5RXpDdDF0TTVZY1FaUDZZOVlQKzVtU1pVWE1qVDdRaGJkOEowa1RIellhSUx5ZkZYU0UKaFl4b2FmdzI3U0RlNFJNek43OElJTEtvZlE9PQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg==";	


A seguir, trecho do código PHP implementado pelo webservice para decriptação do XML de solicitação e encriptação do XML de resposta da solicitação:

//  Gets POST parameters

    $wid     = $_POST["id"];
    $wkey1   = $_POST["key"];
    $wframe1 = $_POST["frame"];

//  Decodes from Base64

    $wkey2   = base64_decode($wkey1);
    $wframe2 = base64_decode($wframe1);

//  Retrieves and decode private key from database

    $wpri64  = (query database...);
    $wpri    = base64_decode($wpri64);

//  Decrypts AES key using private key

    openssl_private_decrypt($wkey2,$wkey3,$wpri);

//  Decrypts XML request using AES key

    $wdecrypt = mcrypt_decrypt 
                ( MCRYPT_RIJNDAEL_128, $wkey3, $wframe2, MCRYPT_MODE_CBC, str_repeat(chr(0),16) );

//  If XML is unreadable, return decryption error (code 6102 ou 7102).

    if ( $wdecrypt == "" ) { 

        $wretcode = "x102"; 
        $wretframe = "";
        $wretmd5 = "";

    }

//  else, processes the XML request and build XML request response.

    else {  
    
        $wretcode = "0";
        
        $wresponse = "<" . '?xml version="1.0" encoding="utf-8"?' . "><followzup>...response...</followzup>";
                     
//      Encrypts and encode the XML request response using the same AES key.

        $wretframe = base64_encode
                     ( mcrypt_encrypt
                     ( MCRYPT_RIJNDAEL_128, $wkey3, $wresponse, MCRYPT_MODE_CBC, str_repeat(chr(0),16) ) );

//      Calculates MD5 hash
                     
        $wretmd5 = md5("$wretframe");
        
    }

//  Returns the XML POST, including: 
//     - Return Code (tag retcode);
//     - XML request response (tag retframe), encrypted and encoded in Base64; 
//     - MD5 hash (tag retmd5).

    header("Content-Type: application/xml; charset=utf-8;");
    echo "<" . '?xml version="1.0" encoding="utf-8"?' . ">";
    echo "<followzup>";
    echo     "<retcode>$wretcode</retcode>";
    echo     "<retframe>$wretframe</retframe>";
    echo     "<retmd5>$wretmd5</retmd5>";
    echo "</followzup>";


br-110-crypto.txt · Last modified: 2017/05/29 07:36 by admin

Page Tools