Criptografia e fraude eleitoral no WhatsApp

Algumas pessoas acreditam que a criptografia de ponta a ponta do WhatsApp seja a culpada pelo aplicativo de mensagens ser uma terra sem leis pela qual está sendo manipulada a eleição no Brasil. Casey Newton, no The Verge, opinou que um aplicativo de mensagens deve ter ou criptografia segura ou mecanismos de compartilhamento que permitam que coisas viralizem, mas não as duas coisas.

A explicação pode parecer razoável à primeira vista, afinal a segurança do WhatsApp garante que nem mesmo o Facebook possa ler o conteúdo das mensagens que trocamos no aplicativo.

As questões com a criptografia de ponta a ponta não são exatamente novas. Em julho de 2016, uma juíza bloqueou o acesso de todo o país ao WhatsApp argumentando que “se as decisões judiciais não podem ser efetivamente cumpridas, o serviço não poderá ser mais prestado, sob pena de privilegiar inúmeros indivíduos que se utilizam impunemente do aplicativo WhatsApp para prática de crimes diversos”.

Vale voltar um pouco na história para lembrar que o WhatsApp implementou criptografia de ponta a ponta depois dos vazamentos de Edward Snowden, que mostraram que agências de inteligência americanas coletam comunicações realizadas em todo o mundo com fins comerciais e políticos. Tais vazamentos aumentaram o debate público sobre vigilância e privacidade na rede, debate que se aprofunda à medida que novos problemas aparecem, como fake news e agências de inteligência estrangeiras influenciando eleições, sequestros digitais como o que comprometeu o funcionamento do sistema de saúde britânico e ciberataques como o que atingiu fortemente os computadores da Ucrânia.

É preciso compreender que abrir brechas de segurança num aplicativo usado por mais de 1 bilhão de pessoas coloca a segurança de todos nós em risco. Para além de comprometer a privacidade das comunicações que fazemos pelo aplicativo (de mensagens entre amigos a senhas, números de cartão, fotos, localizações) e permitir que se use o conteúdo das nossas comunicações para vender propaganda, um aplicativo sem criptografia ajuda os poderosos que controlam a infra-estrutura de Internet a controlar nações inteiras e nunca é positivo para os ativistas. Como escreveu Julian Assange na época em que foram divulgados os documentos de Snowden: “A criptografia pode proteger não somente as liberdades civis e direitos dos indivíduos, mas a soberania e independência de países inteiros, solidariedade entre grupos com causas comuns e projetos de emancipação global.”

Pelo acúmulo que temos nos debates sobre a Internet e o ativismo digital, os que lutamos contra o imperialismo e defendemos Edward Snowden devemos defender a criptografia de ponta a ponta sem tergiversar.

A questão então é como impedir fraude nas eleições e a disseminação de desinformação num ambiente que não se consegue monitorar.

Um grupo de pesquisadores fez um interessante estudo sobre a disseminação de notícias falsas em grupos públicos e sugere três ideias que teriam que ser implementadas pelo próprio WhatsApp: restringir o número de contatos/grupos para os quais uma mensagem pode ser encaminhada de uma vez só de 20 para 5 (como foi feito na Índia), diminuir o número máximo de contatos em listas de transmissão (atualmente 256) e diminuir o número máximo de pessoas em grupos criados nos próximos dias (até o dia da eleição).

Essas ideias são, a meu ver, pouco efetivas e prejudiciais ao ativismo. A extrema-direita no Brasil constrói sua rede há anos e já possui muitos milhares de grupos, enquanto quem está criando novos grupos neste momento é justamente quem busca resistir ao bolsonarismo. Além disso, quem encaminha mensagens de forma manual ou por listas de transmissão, sem usar robôs, são as pessoas comuns e não as grandes máquinas. Parece que é a viralização entre pessoas comuns (que compartilham mensagens nos seus grupos de família, amigos, igreja, trabalho) que essas ideias querem combater. São sugestões que podem contribuir para diminuir o alcance de fake news (e também true news) nos próximos dias (ainda que dificilmente poderiam ser implementadas nesse tempo), mas não atacam o centro do problema.

A SaferNet sugere que se insiram mecanismos de fact checking dentro do aplicativo e que se avise ao usuário quando um conteúdo é falso por meio do uso de um hash para identificar arquivos de mídia. Essa ideia pode ser efetiva para o futuro, mas é necessário pensar com cuidado nas implicações que teria na segurança da criptografia. Ainda que se chegue à conclusão de que ela não compromete a nossa segurança, exige bastante cuidado e engenharia para ser implementada: seriam necessárias mudanças profundas tanto do lado do cliente (atualização de todos os aplicativos nos celulares de todas as pessoas) como do lado do servidor do WhatsApp. É impossível realizá-la nos menos de 7 dias que faltam até as eleições e não serve para fazer algum tipo de investigação retroativa.

Nesse conjunto de medidas paliativas, penso em outras duas que podem ser tomadas por empresas no Brasil e que também podem ajudar. A primeira é cumprir o princípio da neutralidade da rede, dessa forma evitando que sejam vendidos planos de Internet que privilegiam o tráfego do WhatsApp sobre os outros. Atualmente, o acesso a Internet de muitos brasileiros é limitado: se você só tem acesso gratuito ao WhatsApp e não a outros sites, é difícil verificar as informações que você recebe. A segunda depende da imprensa tradicional que tanto critica a proliferação de desinformação: elas deveriam retirar de seus sites os mecanismos de paywall que impedem as pessoas de ler o conteúdo das notícias e dessa forma colaboram para um ambiente no qual se lê apenas os títulos.

Para atacar o coração do problema, porém, minha opinião é que a reportagem de capa da Folha do dia 18/10 dá o caminho: é necessário denunciar e investigar profundamente as empresas que financiam, via caixa 2, o disparo de mensagens via WhatsApp, assim como as empresas que fazem esses disparos. A justiça deveria ir atrás do rastro do dinheiro e dos envolvidos nesse tipo de operação ilegal, como fizeram jornalistas da BBC para escrever uma brilhante reportagem que mostra o funcionamento de algumas dessas empresas. É preciso investigar para descobrir, combater e punir quem financia, quem cria e quem dispara as notícias falsas.

Para ajudar nessa investigação é bom lembrar que, embora o conteúdo de mensagens trocadas no WhatsApp seja protegido por criptografia de ponta a ponta, os metadados do sistema não são. Ou seja, é possível exigir do Facebook e ir atrás dos endereços de IP que usaram determinados números de telefone que comprovadamente espalham fake news, assim como saber quantas mensagens tais números enviaram, quando, para que números e que grupos, quantas pessoas tem nesses grupos etc. A polícia e a justiça brasileira sabem disso, por isso colocar a culpa em algum aspecto técnico da plataforma parece cortina de fumaça. Deveríamos responsabilizar as instituições brasileiras por resguardar a democracia no nosso país e não o Mark Zuckerberg, embora ele tenha afirmado no início do ano que faria tudo que fosse necessário para garantir a integridade das eleições no Brasil.

Investigar num ambiente com mensagens criptografadas sem dúvidas dá mais trabalho do que se toda a rede fosse completamente transparente e todas as nossas comunicações estivessem permanentemente violadas, mas é possível e necessário.

Publicado originalmente na Revista Movimento.

Novo cálculo eleitoral e algoritmos para distribuir vagas de eleições proporcionais

Um exercício matemático e computacional sobre os métodos usados para alocar vagas nas eleições proporcionais do Brasil. Estava refletindo sobre isso uns dias atrás e estou colocando aqui para sistematizar, compartilhar e saber o que outras pessoas acham. A epígrafe é: O quociente eleitoral está morto; vida longa à menor sobra!


O Código Eleitoral brasileiro determina a forma como são eleitos os candidatos a cargos proporcionais (deputados e vereadores) no seu capítulo IV. O método consiste, em resumo, em:

  1. Calcular o quociente eleitoral qq, definido como a soma do total de votos válidos (isso é, sem contar abstenções, brancos e nulos) tt dividida pela quantidade de vagas a preencher ss, arredondada para o número inteiro mais próximo. Isso é, q:=[ts]q := \left[\frac{t}{s}\right].
  2. Para cada partido ou coligação ii, calcular o quociente partidário pip_i, definido como o número de votos obtidos pelo partido ou coligação viv_i dividido (divisão inteira, ou seja, desprezada a fração) pelo quociente eleitoral qq. Isso é, pi:=viqip_i := \left\lfloor \frac{v_i}{q} \right\rfloor \forall i. Então, pip_i é a quantidade inicial de vagas atribuídas ao partido ou coligação ii.
  3. Dividir as sipis - \sum_{i} p_i vagas restantes de acordo com o Cálculo das Sobras, também conhecido como Cálculo das Médias. Tal método é definido pela repetição do seguinte processo enquanto houver vagas restantes (copiado da lei): “o número de votos válidos atribuídos a cada partido político ou coligação será dividido pelo número de lugares por eles obtidos mediante o cálculo do quociente partidário mais um, cabendo ao partido político ou à coligação que apresentar a maior média um dos lugares a preencher, desde que tenha candidato que atenda à exigência de votação nominal mínima”.

Para além desse algoritmo, vale fazer duas considerações importantes sobre o método que vão reaparecer em outros momentos deste texto:

  1. Até a eleição de 2016, os partidos ou coligações ii que não tivessem quociente partidário pi1p_i \geq 1 não participavam do Cálculo das Sobras. Tal restrição foi removida na reforma eleitoral de 2017.
  2. A partir da eleição de 2016, foi imposta uma cláusula de barreira (aprovada em 2015) que exige que candidatos tenham 10% do quociente partidário para poderem ser eleitos (a não ser no caso em que não há candidatos nessa condição). Esse fato vai ser desprezado nesse artigo. Ou seja, vamos assumir que todos os partidos ou coligações que tiverem uma vaga de acordo com o método têm também candidatos aptos a serem eleitos.

A implementação do método descrito acima em C++ (escolhi essa linguagem para usar a fila de prioridades da STL) seria como segue:

// Estrutura usada para ordenar partidos de acordo com suas sobras.
struct party {
  int index, votes, seats;
  bool operator < (const party &o) const {
    return votes / (double) (seats + 1) < o.votes / (double) (o.seats + 1);
  }
};

vector <int> codigoEleitoral(vector <int> v, int s) {
  // Pré-calculo de t, o número total de votos válidos.
  int t = 0;
  for (int i = 0; i < v.size(); i++) {
    t += v[i];
  }

  // Passo 1: calcular o quociente eleitoral.
  int q = round(t / (double) s);

  // Passo 2: calcular o quociente partidário e alocar primeiras vagas.
  priority_queue <party> Q;
  for (int i = 0; i < v.size(); i++) {
    s -= (int) (v[i] / q);
    Q.push((party) {i, v[i], v[i] / q});
  }

  // Passo 3: Cálculo das Sobras ou Médias.
  while (s--) {
    party p = Q.top();
    Q.pop();
    p.seats++;
    Q.push(p);
  }

  // Reconstrução do resultado.
  vector <int> result(Q.size(), 0);
  while (!Q.empty()) {
    party p = Q.top();
    result[p.index] = p.seats;
    Q.pop();
  }

  return result;
}

Sua complexidade é Θ((n+s)logn)\Theta((n+s) \log n), onde nn é o número de partidos ou coligações. O logaritmo vem do uso da heap implementada pela STL (priority_queue).

A partir dessas definições e desse método, gostaria de compartilhar alguns pensamentos.

Equivalência com D’Hondt

Primeiramente, é bom observar que o Método D’Hondt é exatamente o que é chamado de Cálculo das Médias no Código Eleitoral. Como descreve a Wikipedia:

O método [D’Hondt] consiste numa fórmula matemática, ou algoritmo, destinada a calcular a distribuição dos mandatos pelas listas concorrentes, em que cada mandato é sucessivamente alocado à lista cujo número total de votos dividido pelos números inteiros sucessivos, começando na unidade (isto é no número 1) seja maior. O processo de divisão prossegue até se esgotarem todos os mandatos e todas as possibilidades de aparecerem quocientes iguais aos quais ainda caiba um mandato.

A tabela abaixo, da distribuição de 8 vagas para 4 partidos, ajuda a visualizá-lo:

÷ 1 ÷ 2 ÷ 3 ÷ 4 ÷ 5 ÷ 6 ÷ 7 ÷ 8 Vagas
Partido A 100.000 50.000 33.333 25.000 20.000 16.666 14.286 12.500 4
Partido B 80.000 40.000 26.666 20.000 16.000 13.333 11.428 10.000 3
Partido C 30.000 15.000 10.000 7.500 6.000 5.000 4.286 3.750 1
Partido D 20.000 10.000 6.666 5.000 4.000 3.333 2.857 2.500 0

Mais interessante do que perceber que o Cálculo das Médias do Código Eleitoral é o Método D’Hondt, porém, é observar que o método completo brasileiro (não apenas o cálculo das médias) é equivalente matematicamente ao Método D’Hondt, isso é, os dois métodos distribuem as vagas da mesma forma.

Creio que a forma mais fácil de provar isso consista em demonstrar que um partido ou coligação tem uma vaga pelo Código Eleitoral se e somente se tem tal vaga pelo Método D’Hondt. Talvez mostrar que o D’Hondt e o Código Eleitoral decidem as ipi\sum_i p_i primeiras vagas da mesma forma? Será que não bastaria provar que o quociente eleitoral é maior ou igual ao menor número negrito na tabela do D’Hondt (conceito que chamaremos de menor sobra e definiremos melhor até o final desse artigo)? Intuitivamente isso parece não ser muito difícil, mas na prática não fiz e vou considerar que essa prova maravilhosa não cabe nas margens desse artigo.

O importante é que, aceitando esse fato, nota-se que o Código Eleitoral poderia ser simplificado deixando de lado o cálculo do quociente eleitoral e do quociente partidário, aplicando apenas o Cálculo das Sobras/Médias (ou Método D’Hondt) desde o princípio. Sua implementação poderia ser, assim, reduzida para:

vector <int> dhondt(vector <int> v, int s) {
  priority_queue <party> Q;
  for (int i = 0; i < v.size(); i++) {
    Q.push((party) {i, v[i], 0});
  }

  // Cálculo das Sobras ou Médias (D'Hondt).
  while (s--) {
    party p = Q.top();
    Q.pop();
    p.seats++;
    Q.push(p);
  }

  // Reconstrução do resultado.
  vector <int> result(Q.size(), 0);
  while (!Q.empty()) {
    party p = Q.top();
    result[p.index] = p.seats;
    Q.pop();
  }

  return result;
}

A complexidade computacional claramente seria a mesma, mas reduzir o esforço mental para entender o cálculo e também o código — evitando calcular os arredondamentos de quociente eleitoral e quociente partidário — parece bom.

A verdade é que isso nos motiva a perceber que a única utilidade do quociente eleitoral qq tem a ver com as duas considerações que fiz acima e informei que iriam aparecer em outros momentos do texto. De fato, em 2018, a única utilidade do quociente eleitoral será barrar candidatos que não tenham 10% desse quociente.

Já o quociente partidário pip_i teria importância se ainda houvesse a necessidade dos partidos ou coligações ii terem pi1p_i \geq 1 para participar do Cálculo das Médias. Sem tal mecanismo, já não serve para nada.

A menor sobra é o xis da questão

O quociente eleitoral tinha importância porque era nele que se devia mirar para eleger o primeiro candidato de um partido ou coligação. Com a mudança no Código Eleitoral, o número fundamental da eleição deixa de ser o quociente eleitoral e passa a ser a menor sobra xx, que defino como o menor número na tabela do Método D’Hondt que garante vaga.

Matematicamente, x:=minivirix := \min_i \frac{v_i}{r_i}, onde viv_i é a quantidade de votos do partido ou coligação ii e rir_i é o número de vagas alocadas ao partido ou coligação ii no final do processo.

A menor sobra não é importante apenas para que se saiba quantos votos são necessários para eleger o primeiro candidato de um partido ou coligação (como antes era o quociente eleitoral), mas para saber quantos candidatos cada partido ou coligação vai eleger. Com efeito, é fácil ver que o número de candidatos a serem eleitos por um partido ou coligação é vix\left\lfloor\frac{v_i}{x}\right\rfloor. Isso a torna especialmente interessante, muito mais útil do que o velho quociente.

Refletir sobre a importância da menor sobra sugere um algoritmo que evita a implementação do D’Hondt e da fila de prioridades: uma simples busca binária para encontrar xx, dado que quanto menor [maior] é xx mais [menos] candidatos são eleitos.

vector <int> menorSobra(vector <int> v, int s) {
  int a = 0, b = 0;

  // Encontrando o limite superior para a busca binária.
  for (int i = 0; i < v.size(); i++) {
    b = max(b, v[i] + 1);
  }

  // Busca binária para encontrar x.
  while ((b - a) > 1) {
    int x = (a + b) / 2, y = 0;
    for (int i = 0; i < v.size(); i++) {
      y += v[i] / x;
    }
    if (y < s) {
      b = x;
    } else {
      a = x;
    }
  }

  // Construção do resultado dividindo votos de cada partido por x.
  vector <int> result(v.size(), 0);
  int x = (a + b) / 2;
  for (int i = 0; i < v.size(); i++) {
    result[i] = v[i] / x;
  }

  return result;
}

Esse algoritmo tem complexidade Θ(nlogt)\Theta(n \log t), que me parece razoável.

Por tudo isso, exceto se a sua preocupação for com a cláusula de barreira de 2015 — isso é, com fazer seu candidato atingir 10% do quociente eleitoral —, pareceria que vale esquecer o quociente eleitoral e o algoritmo do TSE, dando centralidade à menor sobra.

Do ponto de vista prático, como, porém, estimar a menor sobra antes de ter os dados de uma eleição (que ainda não tenha acontecido, por exemplo)?

Bem, sabemos que ela é limitada superiormente pelo quociente eleitoral (xqx \leq q), que é fácil de estimar já que se conhece o tamanho do colégio eleitoral, o número de vagas a serem preenchidas e dá pra chutar uma proporção de votos válidos. Ao menos, é bem mais fácil do que estimar a configuração completa do resultado de uma eleição. Então, só por isso, talvez valha, ainda, não descartar o quociente eleitoral.

523

Eu saí com um casal de alemães e aprendia sobre a política e a história deles. Ouvi sobre grupos terroristas, o NPD (um partido nazista de lá) e umas brigas políticas semelhantes às dos hooligans. Eles compreendiam e se expressavam bem em português, mas em certo momento trocaram algumas frases no seu idioma, não fiz ideia do porquê.

Então um deles me disse:

— Nós não entendemos por que os brasileiros não se revoltam, não fazem grandes manifestações em Brasília. Aqui tem muita gente passando fome, morando na favela, gente que trabalha um monte a vida inteira e não tem nada. Na Europa fazem revoluções por muito menos.

Não sabia o que responder, então disse o que me veio à mente:

— Acho que somos conformados e felizes com os nossos governos populistas e estamos mais preocupados com o carnaval e com o Campeonato Brasileiro. E, pasmem, essa nossa felicidade é até motivo de orgulho. É propaganda. Mas quem sabe um dia…

PS: A única relação do título desse post com seu conteúdo é a Lei dos Cinco (não que seja pouco). Eu usei esse título porque foi o sugerido pelo WordPress (esse é o post de ID 523 no meu banco de dados).

PPS: Today is Prickle-Prickle, the 1st day of Discord in the YOLD 3176. Feliz Estação Nova!

HOWTO: Como usar Pandora Radio no Brasil

O projeto Pandora é uma rádio on-line que funciona como um catálogo bem categorizado de milhares de CDs e é capaz de reproduzir músicas parecidas com o tipo que você diz para ele que gosta. Ficou confuso? É assim: eu entro lá e escrevo que gosto de Chico Buarque. Aí ele me diz: vamos tocar uma música do Chico que tem suas características principais como canto em português, violão leve, etc. Responda se você gostou ou não e baseado nessa escolha tocaremos outro estilo ou continuaríamos no mesmo.

É uma idéia muito legal porque no fim você ouve apenas o que gosta, mas também descobre novas músicas (porque ele não fica repetindo artista, álbum, música, mas só as características da música ou do artista que você selecionou a princípio).

Fazia tempo que eu não usava o Pandora porque num esforço comunitário de minha família, digitalizamos algumas centenas de CDs criando uma biblioteca de 35 gb em MP3. Porém, meu desktop (Durion 1.1) que era meu servidor de música (MPD) recentemente morreu (a placa-mãe deu pau) e, cansado de ouvir as poucas músicas que tinha aqui no laptop, resolvi ver como andava o Pandora.

Porém, fui surpreendido por uma mensagem dizendo que por causa de copyright brasileiros não podem mais usar o Pandora. Isso é um problema que eles dizem estar conversando com as autoridades para resolver, mas por hora não podem aceitar IPs brasileiros, o que me levou a buscar uma solução.

A primeira coisa que pensei foi procurar um servidor de proxy nos Estados Unidos. É fácil se você entrar no Public Proxy Servers, mas a velocidade deles realmente não me agrada, ainda mais pra ouvir uma rádio on-line. Então, pesquisei um pouco e depois de algum tempo encontrei a solução: SSH tunneling (túneis de SSH?)

Eu uso SSH todo dia e nunca tinha me dado conta que ele tem uma opção super interessante que é numa dada porta criar um tunelamento que pode ser usado como servidor SOCKS (proxy). Aí você pensa: mas qual a vantagem? De qualquer jeito você terá que usar um servidor proxy e ficar com a internet mais lenta. Sim, é verdade, mas o meu servidor na Dreamhost é sem dúvidas muito mais rápido que um proxy público e eu tenho certeza que minhas informações ficam seguras. Aliás, é por segurança que a maioria das pessoas usa SSH tunneling (ex.: pessoas com laptop numa rede wireless pública)

Vamos ao prático:

$ ssh -C -D 666 -N user@host

E configure seu navegador para usar Socks (eu usei V5, mas a V4 deve funcionar também) para o endereço: 127.0.0.1 (isso mesmo, não é o host que você colocou no SSH, é a sua máquina, porque ela que criou o servidor) na porta que você especificou com o parâmetro -D (nesse caso 666)

As opções do SSH que eu utilizei no exemplo são:

  • -C: comprime entrada e saída. Nos exemplos que eu peguei vinha, acredito que seja pras transferências serem mais rápidas.
  • -D [bind:]port: porta (e um endereço opcional) pro servidor rodar
  • -N: não executa nenhum comando (ie não abre um shell)

Esta dica funciona em sistemas operacionais que tem SSH (Linux, FreeBSD e provavelmente qualquer outro Unix-like). Para usá-la no Windows, você deve usar o PuTTy.

Briga de rua

Briga

Fim da tarde… Cruzando de carro a Av. Sete de Setembro com a Rua Gil Stein Ferreira uma reunião enorme de pessoas me chamou a atenção. Cerca de 100 meninos e meninas formavam uma circunferência com uns 5 metros de raio; no centro dois moleques brigavam.

A roda gritava, empolgada. A violência estava deixando todos eles felizes, provavelmente todos eles odiavam as crianças que sairiam dali totalmente quebradas.

Em pleno centro da cidade, haviam várias pessoas passando e percebendo a tragédia: alguns continuavam seu caminho, outros paravam para observar melhor, ninguém fazia nada.

Seria hipócrita condenar o povo que não se mexia e alguns até assistiam o espetáculo. Eu e minha família, afim de não perder a hora do café, continuamos no carro a caminho de casa.

© 2005–2020 Tiago Madeira