Criptografia 101: Emparelhamentos

CriptografiaCurvas ElípticasEmparelhamentosMatemática
F
Frank Mangone
20 de maio de 2024 · 11 min de leitura

Este é parte de uma série de artigos sobre criptografia. Se este é o primeiro artigo que você encontra, eu recomendo começar do início da série.

Já exploramos várias aplicações para curvas elípticas — alguns esquemas simples e alguns mais avançados. Também jogamos polinômios na mistura ao estudar Assinaturas de Limite. Se esticarmos os limites da criatividade, ainda podemos criar muitos protocolos baseados apenas nessas construções.

Mas isso não significa que não existam outras ferramentas por aí. E há uma muito importante que ainda precisamos apresentar: emparelhamentos (pairings).

Neste artigo, vamos definir o que eles são — mas não como computá-los. A razão para isso é que ainda não definimos a maquinaria matemática necessária para o cálculo de emparelhamentos. Isso, podemos explorar mais tarde, mas se você está interessado, este é um excelente recurso para olhar enquanto isso. E também existem muitas bibliotecas por aí que cobrem o cálculo de emparelhamentos se você quiser começar a brincar com eles depois de ler este artigo!

Emparelhamentos

Um emparelhamento, também referido como um mapa bilinear, é realmente apenas uma função, tipicamente representada com a letra ee. Ela recebe dois argumentos e produz uma única saída, assim:

e:G1×G2G3 / e(G1,G2)=G3e: \mathbb{G}_1 \times \mathbb{G}_2 \rightarrow \mathbb{G}_3 \ / \ e(G_1, G_2) = G_3

Vamos precisar de alguma notação da teoria dos conjuntos desta vez, mas nada muito louco.

Provavelmente a mais exótica (se você não teve muito contato prévio com teoria dos conjuntos) é o produto cartesiano — usado no conjunto G1×G2\mathbb{G}_1 \times \mathbb{G}_2. É apenas o conjunto de todos os elementos da forma (G1,G2)(G_1, G_2) onde G1G_1 pertence a G1\mathbb{G}_1, e G2G_2 pertence a G2\mathbb{G}_2.

No entanto, esta não é uma função qualquer. Ela tem uma propriedade importante: é linear em ambas as entradas. Isso significa que todas as seguintes são equivalentes:

e([a]G1,[b]G2)=e(G1,[b]G2)a=e(G1,G2)ab=e([b]G1,[a]G2)e([a]G_1, [b]G_2) = e(G_1, [b]G_2)^a = e(G_1, G_2)^ab = e([b]G_1, [a]G_2)

Como você pode ver, podemos fazer esse tipo de troca dos produtos (ou mais precisamente, operações de grupo). Mesmo que essa propriedade não pareça muito à primeira vista, ela é realmente muito poderosa.

Os emparelhamentos são uma espécie de liquidificador, no sentido de que não nos importamos muito com o valor particular obtido ao avaliar uma expressão de emparelhamento (exceto ao verificar algo chamado não-degeneração). Em vez disso, o que nos importa é que algumas combinações de entradas produzem o mesmo resultado, por causa da bilinearidade que mencionamos acima. Isso é o que os torna atraentes, como veremos mais adiante.

Curvas Elípticas e Emparelhamentos

Repare como as entradas vêm do produto cartesiano G1×G2\mathbb{G}_1 \times \mathbb{G}_2. É um conjunto bem particular: G1\mathbb{G}_1 e G2\mathbb{G}_2 são grupos, para ser preciso. Grupos disjuntos, na verdade — significando que eles não compartilham nenhum elemento. Formalmente, dizemos que sua interseção é vazia:

G1G2=|\mathbb{G}_1 \cap \mathbb{G}_2 = \varnothing

Além disso, G1\mathbb{G}_1 e G2\mathbb{G}_2 não são quaisquer grupos — eles devem ser adequados para o cálculo de emparelhamentos. Acontece que grupos de curvas elípticas são uma boa escolha — e uma muito boa em termos de eficiência computacional. Então é uma coincidência feliz que já tenhamos uma boa compreensão deles!

Se você verificar a literatura, há casos onde em vez de usar dois grupos disjuntos, você verá o mesmo grupo sendo usado duas vezes. Algo como G×G\mathbb{G} \times \mathbb{G}.

Esses são às vezes chamados auto-emparelhamentos, e o que realmente acontece é que existe uma função f que mapeia G2\mathbb{G}_2 em G\mathbb{G} — significando que podemos transformar elementos de G2\mathbb{G}_2 em elementos de G\mathbb{G}, e apenas usar G\mathbb{G} no nosso emparelhamento.

Embora não vamos cobrir como isso é feito, tenha em mente que a definição formal de um emparelhamento requer que os grupos sejam disjuntos.

Visualização dos conjuntos em um emparelhamento
Click to zoom
Alguma função f permite mover de um lado para o outro entre os grupos G₁ e G₂.

Aplicação

Antes de chegarmos ao ponto de "por que diabos estou aprendendo isso" (assumindo que ainda não estamos lá!), acredito ser frutífero apresentar uma aplicação.

Apesar do fato de que não sabemos como computar emparelhamentos ainda, podemos entender sua utilidade porque sabemos sobre suas propriedades.

Vamos não perder tempo e ir direto ao ponto.

A Configuração

Trabalhar com grupos de curvas elípticas, ou até com inteiros módulo pp, pode te levar muito longe. Mas sabe uma coisa que nenhum deles pode fazer por você? Eles não permitem que você use sua identidade para operações criptográficas!

Bryan Cranston derrubando o microfone
Boom! Mic drop!

Identidade? Você quer dizer tipo meu nome? Parece loucura, mas pode ser feito. Alguma configuração é necessária, no entanto.

Para realizar esse tipo de façanha mágica criptográfica, vamos precisar de um ator especial, confiado por outras partes — frequentemente referido como Autoridade Confiável. Este ator será responsável pela geração de chaves privadas, então também é acuradamente (e muito descritivamente) chamado de Gerador de Chaves Privadas (PKG).

O PKG faz algumas coisas. Primeiro e mais importante, ele escolhe um segredo mestre, que é um inteiro ss. Ele também escolhe e torna públicos alguns parâmetros públicos, que vamos definir em um minuto. E finalmente, ele escolhe e torna pública uma função de hash HH, que faz hash para G1\mathbb{G}_1.

H:{0,1}G1H: \{0,1\}^* \rightarrow \mathbb{G}_1

Para obter uma chave privada, André tem que solicitá-la do PKG. E para fazer isso, ele envia a eles sua identidade hasheada. Sua identidade pode ser qualquer coisa — um nome, um endereço de email, um número de documento de identidade, qualquer coisa que identifique unicamente um indivíduo. Vamos denotar isso como IDID. Sua chave pública é então:

QA=H(IDA)G1Q_A = H(ID_A) \in \mathbb{G}_1

Ao receber esse valor, o PKG calcula sua chave privada como:

SA=[s]QAG1S_A = [s]Q_A \in \mathbb{G}_1

E a envia para André.

Todas essas comunicações são assumidas como acontecendo por um canal seguro. Em particular, a chave secreta de André não deve vazar!

Diagrama do processo de geração de chaves
Click to zoom

Nossa configuração está pronta! André tem tanto sua chave privada quanto pública. O que ele pode fazer com isso?

Encriptação Baseada em Identidade

Vamos supor que André quer encriptar uma mensagem para Bruna. Tudo que ele tem é a chave pública dela, porque ele conhece a identidade dela (IDID). E apenas fazendo o hash, ele obtém a chave pública dela:

QB=H(IDB)Q_B = H(ID_B)

Também vamos precisar de mais algumas coisas:

  • Um ponto PG2P \in \mathbb{G}_2, usado para calcular um ponto Q=[s]PQ = [s]P, também em G2\mathbb{G}_2. Como ss é apenas conhecido pela autoridade confiável, esses pontos são calculados e publicados pelo PKG — eles são os parâmetros públicos que mencionamos anteriormente, e vamos denotá-los por pp:
p=(P,Q)p = (P, Q)
  • Também precisamos de outra função de hash HH':
H:G3{0,1}nH': \mathbb{G}_3 \rightarrow \{0,1\}^n

Este esquema de encriptação usa uma estratégia similar ao Esquema de Encriptação Integrado de Curva Elíptica que vimos anteriormente na série: mascaramento. Então, para encriptar uma mensagem MM, André segue estes passos:

  • Ele escolhe um nonce aleatório, que é um inteiro kk.
  • Com ele, ele calcula U=[k]PU = [k]P. Isso será usado para mais tarde reconstruir a máscara.
  • Então, usando a chave pública de Bruna, que é apenas o hash da identidade dela, ele computa:
e(QB,Q)ke(Q_B,Q)^k
  • Ele usa esse valor para computar uma máscara, que é adicionada à mensagem:
V=MH(e(QB,Q)k)V = M \oplus H'(e(Q_B,Q)^k)

A mensagem final encriptada será a tupla (U,V)(U, V).

Lembre-se que o símbolo \oplus representa a operação XOR. E uma das propriedades dessa operação é: MAA=MM \oplus A \oplus A = M. O que isso significa é que adicionar a máscara duas vezes nos permite recuperar a mensagem original.

Como Bruna decripta? Bem, ela pode pegar UU e simplesmente recalcular a máscara. Com ela, ela re-obtém a mensagem original:

M=VH(e(SB,U))M = V \oplus H'(e(S_B,U))

Mas espere... Como as duas máscaras são iguais? Claramente, elas não parecem ser a mesma coisa... São avaliações diferentes do emparelhamento!

e(QB,Q)k=?e(SB,U)e(Q_B,Q)^k \stackrel{?}{=} e(S_B,U)
Morty suando
*pânico*

Não tema — prometo que isso faz sentido. Porque isso é precisamente onde a mágica dos emparelhamentos acontece: usando sua propriedade de bilinearidade, podemos mostrar que os dois valores são equivalentes:

e(QB,Q)k=e(QB,[s]P)k=e(QB,P)s.k=e([s]QB,[k]P)e(Q_B,Q)^k = e(Q_B, [s]P)^k = e(Q_B, P)^{s.k} = e([s]Q_B, [k]P) e(QB,Q)k=e(SB,U)e(Q_B,Q)^k = e(S_B, U)

E assim, conhecer apenas a identidade de Bruna é suficiente para André encriptar informação só para ela — impulsionado por emparelhamentos, claro!

Diagrama de encriptação usando emparelhamentos
Click to zoom
Para resumir, aqui está uma representação visual do processo

De Volta aos Emparelhamentos

Okay, agora que vimos emparelhamentos em ação, estamos totalmente motivados a entender como eles são definidos um pouco mais em profundidade. Certo? Certo?

Cena do T-Rex de Jurassic Park
Oh, eu posso ver você aí

Isso não vai demorar muito — vamos apenas dar uma olhada rápida em algumas das ideias que tornam os emparelhamentos possíveis.

Mencionamos que G1\mathbb{G}_1 e G2\mathbb{G}_2 poderiam muito bem ser grupos de curvas elípticas.

Então, apenas escolhemos duas curvas elípticas diferentes? Bem, nesse caso, teríamos que ter certeza de que os grupos são disjuntos, o que não é necessariamente fácil; e há outras preocupações em tal cenário.

E quanto a usar uma única curva elíptica? Então precisaríamos de dois subgrupos diferentes. Quando fazemos uso de um gerador de grupo, GG, o grupo gerado por ele não é necessariamente a totalidade do grupo de curva elíptica — mas poderia ser. Essa relação de inclusão é escrita como:

GE(Fq)|\langle G \rangle \subseteq E(\mathbb{F}_q)

O que significa: o grupo gerado por GG é ou um subgrupo, ou toda a curva elíptica.

Geralmente queremos que a ordem do subgrupo gerado por GG seja a maior possível, para que o problema DLP seja difícil. Isso significa que:

  • Se há outros subgrupos, eles são provavelmente pequenos.
  • Se G\langle G \rangle é a totalidade da curva elíptica, então não há outros subgrupos disponíveis.

Parece que chegamos a um dilema...

Cena de Procurando Nemo de peixes em sacos
E agora, chefe?

Expandindo a Curva

Felizmente, esta pequena crise nossa tem uma solução. Veja, nossas curvas sempre foram definidas sobre os inteiros módulo qq — mas e se pudéssemos estender os valores possíveis que usamos?

Em vez de apenas permitir que os pontos na curva elíptica assumam valores nos inteiros módulo qq:

Fq={0,1,2,3,...,q1}|\mathbb{F}_q = \{0,1,2,3,..., q-1\}

Poderíamos usar algo como os números complexos, e permitir que os pontos em EE assumam valores neste conjunto:

Fq2={a+bi:a,bFq,i2+1=0}|\mathbb{F}_{q^2} = \{a + bi : a, b \in \mathbb{F}_q, i^2 + 1 = 0 \}

Usar números complexos faz perfeito sentido: por exemplo, você pode verificar por si mesmo que o ponto (8,i)(8, i) está na seguinte curva elíptica:

E/F11:y2=x3+4E/\mathbb{F}_{11}: y^2 = x^3 + 4

Extensões de Corpo

Números complexos são apenas um exemplo de um conceito mais geral, que é extensões de corpo.

Um corpo (vamos denotá-lo FF) é apenas um conjunto com algumas operações associadas. Isso provavelmente soa familiar — é uma definição muito similar à que demos para grupos, bem no início da série.

Independente da formalidade, há um corpo muito importante com o qual devemos nos importar: os inteiros módulo qq, quando qq é um número primo.

Isso pode soar um pouco enganador. Originalmente, eu te disse que os inteiros módulo qq eram um grupo. E de fato, se usarmos uma única operação (como adição), eles se comportam como um grupo.

Mais geralmente, no entanto, eles são um corpo, pois suportam adição, subtração, multiplicação e divisão (bem, inversões modulares, na verdade!).

Uma extensão de corpo é simplesmente um conjunto KK que contém o corpo original:

FKF \subset K

Sob a condição de que o resultado de operações entre elementos de FF sempre estão em FF, mas nunca no resto de KK (o conjunto KFK {-} F).

Uma extensão de corpo muito conhecida é, claro, o conjunto dos números complexos. Os números reais atuam como FF, e operações entre números reais (adição, subtração, multiplicação e divisão) estão nos números reais (FF) também. Operações entre números complexos podem ou não resultar em números reais.

Por que isso importa? Imagine que definimos uma curva sobre os inteiros módulo qq. Obtemos um monte de pontos, que podemos denotar:

E(F)E(F)

Se estendermos o corpo base (os inteiros módulo qq), então novos pontos válidos aparecerão, enquanto preservamos os antigos. Isto é:

E(F)E(K)E(F) \subseteq E(K)

Por causa disso, novos subgrupos aparecem, e obtemos o bônus adicional de manter os subgrupos originais, que foram definidos sobre o corpo base.

E quando escolhemos uma extensão de corpo apropriada, algo incrível acontece: obtemos uma infinidade de subgrupos com a mesma ordem que G\langle G \rangle. E esses grupos acontecem de ser quase disjuntos: eles apenas compartilham o elemento identidade, O\mathcal{O}. O conjunto de todos esses subgrupos é o que é chamado de grupo de torção.

Representação do grupo de torção
Click to zoom
Grupo de 3-torção da curva E/F₁₁: y² = x³ + 4. Cada caixa azul é um subgrupo, junto com 𝒪, que é comum a todos os subgrupos — daí sua representação no centro.

Okay, vamos parar por aí. O objetivo desta seção é apenas apresentar uma ideia geral do que são as entradas de emparelhamento. No entanto, não há muito mais que possamos dizer sem fazer um mergulho mais profundo no assunto, o que é algo que excede o escopo deste artigo introdutório.

Novamente, recomendo este livro se você quiser uma explicação mais detalhada — e por sua vez, ele referencia alguns ótimos recursos mais avançados.

A ideia importante aqui é que o cálculo de emparelhamento não é trivial, de forma alguma. Se você está interessado em eu expandir este tópico mais em artigos seguintes, por favor me avise!

Resumo

Embora não tenhamos nos aventurado profundamente no território dos emparelhamentos, esta simples introdução nos permite entender o princípio de funcionamento por trás de métodos baseados em emparelhamento. Tudo depende da propriedade de bilinearidade que vimos logo no início do artigo.

A conclusão chave aqui é:

Emparelhamentos são esses tipos de liquidificadores, onde nos importamos com o resultado computado ser o mesmo para dois conjuntos diferentes de entradas

Novamente, podemos mergulhar no cálculo de emparelhamentos mais tarde. Acredito ser mais frutífero começar a ver algumas aplicações.

Por essa razão, vamos olhar para mais algumas aplicações de emparelhamentos na próxima parte da série. Te vejo lá!

Este conteúdo foi útil para você?

Apoie Frank Mangone enviando um café. Todos os lucros vão diretamente para o autor.
ETH