É importante que o Tink se comporte "da mesma forma" em todas as linguagens de programação. Esse conceito não é simples, mas é essencial:
Para manter a consistência, a Tink usa testes em várias linguagens, que podem ser encontrados no repositório de várias linguagens do GitHub (em inglês). Esses testes verificam a consistência e a interoperabilidade de linguagens diferentes.
No entanto, definir a consistência não é tão simples quanto se poderia esperar. Portanto, esta página fornece nossa definição de trabalho. Basicamente, a Tink oferece dois tipos de consistência:
- Consistência da avaliação: para um determinado conjunto de chaves1, se a criação do primário for bem-sucedida em duas linguagens, elas se comportarão da mesma forma.
- Consistência de criação: a criação de um primitivo tem sucesso em um idioma se ele for compatível com todos os tipos de chaves em um conjunto de chaves, conforme documentado na nossa lista de tipos de chave com suporte.
contexto
De modo geral, a Tink fornece as seguintes APIs:
Manipulação de conjunto de chaves:o Tink fornece APIs para adicionar novas chaves a um conjunto de chaves, remover e alterar a chave primária em um conjunto.
Serialização do conjunto de chaves:o Tink fornece APIs para serializar um conjunto de chaves para uma sequência de bytes e, por outro lado, analisar um conjunto de chaves a partir de uma sequência de bytes.
Criação primitiva:o Tink fornece uma API para criar uma interface para um primitivo a partir de um conjunto de chaves. Por exemplo, para criar um objeto
Aead
com base em um conjunto de chaves em Java, o usuário chamakeysetHandle.getPrimitive(Aead.class, config)
.Uso primitivo:a interface produzida na etapa de criação primitiva fornece uma API para executar operações criptográficas.
Há duas perguntas importantes a serem feitas sobre essas APIs:
Criação: para um determinado conjunto de chaves serializado, linguagem e primitivo, é possível criar o primitivo a partir desse conjunto de chaves na linguagem?
Avaliação: como o objeto primitivo pode ser criado em alguma linguagem com base em um determinado conjunto de chaves?
É importante observar que o Tink não fornece consistência ao analisar um conjunto de chaves. Por exemplo, é possível que o Tink C++
- analisa com sucesso conjuntos de chaves que contêm as chaves CHACHA20-POLY1305, mesmo que as operações AEAD CHACHA20-POLY1305 não sejam implementadas no Tink;
- analisa com sucesso conjuntos de chaves com chaves de 1 byte, o que falha em todas as operações criptográficas.
Esses comportamentos podem mudar em versões secundárias.
Consistência da avaliação
A consistência da avaliação é mais importante do que qualquer consistência no processo de criação: se uma AEAD em Java não puder descriptografar a criptografia da AEAD em C++, os usuários terão um problema sério.
Em geral, o objetivo da Tink é ser consistente da maneira óbvia para os primitivos. Por exemplo, se um binário C++ calcular uma assinatura com public_key_sign->Sign(data)
, a chamada de verificação Java correspondente publicKeyVerify.verify(signature, data)
deverá ser bem-sucedida.
No entanto, mesmo aqui existem algumas ressalvas. Por exemplo,
o tipo de retorno de aead.Encrypt
em Java é um byte[]
.
De acordo com a Especificação da linguagem Java (JLS, na sigla em inglês) §10.7, o tamanho de uma matriz é do
tipo int
, que de acordo com §JLS 4.2.1 pode ser no máximo 2147483647. Portanto, a criptografia de uma matriz com comprimento de 2147483647 falha em Java: a criptografia tem alguma sobrecarga, o que significa que a saída seria muito longa. No entanto, em outros idiomas, a criptografia
pode ser bem-sucedida para essas entradas.
Portanto, a Tink oferece consistência de avaliação: para um determinado conjunto de chaves, se a criação do primitivo for bem-sucedida em duas linguagens, elas se comportarão da mesma forma.
A exceção é que algumas operações podem falhar em algumas circunstâncias excepcionais.
Consistência de criação
A criação de primitivos nem sempre tem êxito para todos os conjuntos de chaves. Por exemplo, o Tink não permitirá que os usuários criem uma AesSivKey se o material da chave tiver um comprimento de 128 bits.
No entanto, a Tink oferece consistência da seguinte forma: se duas linguagens forem compatíveis com um tipo de chave, o conjunto de chaves para as quais o primitivo pode ser criado coincide. Obviamente, se uma linguagem não for compatível com um tipo de chave, nenhum objeto primitivo poderá ser criado.
A consistência da criação é menos importante do que a da avaliação, e há mais exceções a essa regra do que a consistência da avaliação. Essas limitações estão documentadas na nossa lista de tipos de chave compatíveis. Por exemplo, para o tipo de chave ECIES, o Tink oferece uma escolha de qual curva elíptica usar para a concordância de chaves, mas o Java não oferece suporte a X25519. Portanto, a criação de uma chave usando X25519 em Java falha.
-
Neste documento, usamos o termo
Keyset
para denotar o objeto chamadoKeysetHandle
na maioria dos idiomas. ↩