Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Contexto e teoria
No sistema de proteção de dados, uma "chave" significa um objeto que pode fornecer serviços de encriptação autenticados. Cada chave é identificada por um id único (um GUID), e transporta consigo informação algorítmica e material entrópico. Pretende-se que cada chave tenha entropia única, mas o sistema não pode impor isso, e também precisamos de ter em conta os programadores que possam alterar manualmente o chaveiro modificando a informação algorítmica de uma chave existente no chaveiro. Para cumprir os nossos requisitos de segurança perante estes casos, o sistema de proteção de dados tem um conceito de agilidade criptográfica, que permite usar de forma segura um único valor entrópico através de múltiplos algoritmos criptográficos.
A maioria dos sistemas que suportam agilidade criptográfica faz-no incluindo alguma informação identificativa sobre o algoritmo dentro da carga útil. O OID do algoritmo é geralmente um bom candidato para isto. No entanto, um problema que encontrámos é que existem várias formas de especificar o mesmo algoritmo: "AES" (CNG) e as classes geridas Aes, AesManaged, AesCryptoServiceProvider, AesCng e RijndaelManaged (dados parâmetros específicos) são, na verdade, a mesma coisa, e precisaríamos de manter um mapeamento de todas estas classes para o OID correto. Se um programador quisesse fornecer um algoritmo personalizado (ou até outra implementação de AES!), teria de nos dizer qual é o seu OID. Este passo extra de registo torna a configuração do sistema particularmente complicada.
Recuando, decidimos que estávamos a abordar o problema pela direção errada. Um OID diz-te qual é o algoritmo, mas na verdade não nos importamos com isso. Se precisarmos de usar um único valor entrópico de forma segura em dois algoritmos diferentes, não é necessário sabermos quais são realmente os algoritmos. O que realmente nos interessa é como eles se comportam. Qualquer algoritmo de cifra de blocos simétrico decente é também uma permutação pseudoaleatória forte (PRP): ao definir as entradas (chave, modo de encadeamento, IV, texto plano), a saída do texto cifrado será, com uma probabilidade esmagadora, distinta de qualquer outro algoritmo de cifra de blocos simétrico dadas as mesmas entradas. De forma semelhante, qualquer função hash com chave decente é também uma função pseudoaleatória forte (PRF), e, dado um conjunto de entrada fixo, a sua saída será significativamente distinta de qualquer outra função hash com chave.
Usamos este conceito de PRPs e PRFs fortes para construir um cabeçalho de contexto. Este cabeçalho de contexto atua essencialmente como uma impressão digital estável sobre os algoritmos usados em qualquer operação e fornece a agilidade criptográfica necessária ao sistema de proteção de dados. Este cabeçalho é reproduzível e é usado posteriormente como parte do processo de derivação de subchaves. Existem duas formas diferentes de construir o cabeçalho de contexto, dependendo dos modos de funcionamento dos algoritmos subjacentes.
Encriptação em modo CBC + autenticação HMAC
O cabeçalho de contexto consiste nos seguintes componentes:
[16 bits] O valor 00 00, que é um marcador que significa "encriptação CBC + autenticação HMAC".
[32 bits] O comprimento da chave (em bytes, big-endian) do algoritmo de cifra simétrica por blocos.
[32 bits] O tamanho do bloco (em bytes, big-endian) do algoritmo de cifra por blocos simétrico.
[32 bits] O comprimento da chave (em bytes, big-endian) do algoritmo HMAC. (Atualmente, o tamanho da chave corresponde sempre ao tamanho do digest.)
[32 bits] O tamanho do digest (em bytes, big-endian) do algoritmo HMAC.
EncCBC(K_E, IV, ""), que é a saída do algoritmo de cifra por blocos simétrico dado um input de string vazio e onde IV é um vetor totalmente zero. A construção deK_Eé descrita abaixo.MAC(K_H, ""), é a saída do algoritmo HMAC quando a entrada é uma string vazia. A construção deK_Hé descrita abaixo.
Idealmente, poderíamos passar vetores totalmente nulos para K_E e K_H. No entanto, queremos evitar a situação em que o algoritmo subjacente verifique a existência de chaves fracas antes de realizar qualquer operação (nomeadamente DES e 3DES), o que impede o uso de um padrão simples ou repetível como um vetor totalmente zero.
Em vez disso, usamos o KDF NIST SP800-108 em Modo Contador (ver NIST SP800-108, Sec. 5.1) com uma chave, rótulo e contexto de comprimento zero e HMACSHA512 como PRF subjacente. Derivamos | K_E | + | K_H | bytes de saída e depois decompomos o resultado em K_E e K_H. Matematicamente, isto é representado da seguinte forma.
( K_E || K_H ) = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = "")
Exemplo: AES-192-CBC + HMACSHA256
Como exemplo, considere o caso em que o algoritmo de cifra por blocos simétrico é AES-192-CBC e o algoritmo de validação é HMACSHA256. O sistema geraria o cabeçalho de contexto usando os passos seguintes.
Primeiro, seja ( K_E || K_H ) = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = ""), onde | K_E | = 192 bits e | K_H | = 256 bits segundo os algoritmos especificados. Isto leva ao K_E = 5BB6..21DD e K_H = A04A..00A9 no exemplo abaixo:
5B B6 C9 83 13 78 22 1D 8E 10 73 CA CF 65 8E B0
61 62 42 71 CB 83 21 DD A0 4A 05 00 5B AB C0 A2
49 6F A5 61 E3 E2 49 87 AA 63 55 CD 74 0A DA C4
B7 92 3D BF 59 90 00 A9
Em seguida, calcule Enc_CBC (K_E, IV, "") para AES-192-CBC dado IV = 0* e K_E como mencionado acima.
result := F474B1872B3B53E4721DE19C0841DB6F
De seguida, calcule MAC(K_H, "") para HMACSHA256 dado K_H como indicado acima.
result := D4791184B996092EE1202F36E8608FA8FBD98ABDFF5402F264B1D7211536220C
Isto produz o cabeçalho de contexto completo abaixo:
00 00 00 00 00 18 00 00 00 10 00 00 00 20 00 00
00 20 F4 74 B1 87 2B 3B 53 E4 72 1D E1 9C 08 41
DB 6F D4 79 11 84 B9 96 09 2E E1 20 2F 36 E8 60
8F A8 FB D9 8A BD FF 54 02 F2 64 B1 D7 21 15 36
22 0C
Este cabeçalho de contexto é a impressão digital do par de algoritmos de encriptação autenticados (encriptação AES-192-CBC + validação HMACSHA256). Os componentes, conforme descrito acima , são:
O marcador
(00 00)O comprimento da chave de cifra por blocos
(00 00 00 18)O tamanho do bloco da cifra em blocos
(00 00 00 10)o comprimento da chave HMAC
(00 00 00 20)o tamanho do digesto HMAC
(00 00 00 20)a saída
(F4 74 - DB 6F)PRP do cifrador de blocos ea saída
(D4 79 - end)PRF do HMAC.
Observação
O cabeçalho de contexto de encriptação em modo CBC + autenticação HMAC é construído da mesma forma, independentemente de as implementações dos algoritmos serem fornecidas pelo Windows CNG ou pelos tipos geridos SymmetricAlgorithm e KeyedHashAlgorithm. Isto permite que aplicações a correr em diferentes sistemas operativos produzam de forma fiável o mesmo cabeçalho de contexto, mesmo que as implementações dos algoritmos diferam entre sistemas operativos. (Na prática, o KeyedHashAlgorithm não tem de ser um HMAC propriamente dito. Pode ser qualquer tipo de algoritmo de hash com chave.)
Exemplo: 3DES-192-CBC + HMACSHA1
Primeiro, seja ( K_E || K_H ) = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = ""), onde | K_E | = 192 bits e | K_H | = 160 bits segundo os algoritmos especificados. Isto leva ao K_E = A219..E2BB e K_H = DC4A..B464 no exemplo abaixo:
A2 19 60 2F 83 A9 13 EA B0 61 3A 39 B8 A6 7E 22
61 D9 F8 6C 10 51 E2 BB DC 4A 00 D7 03 A2 48 3E
D1 F7 5A 34 EB 28 3E D7 D4 67 B4 64
De seguida, calcule Enc_CBC (K_E, IV, "") para 3DES-192-CBC dado IV = 0* e K_E como mencionado acima.
result := ABB100F81E53E10E
De seguida, calcule MAC(K_H, "") para HMACSHA1 dado K_H como acima.
result := 76EB189B35CF03461DDF877CD9F4B1B4D63A7555
Isto produz o cabeçalho de contexto completo, que é uma impressão digital do par de algoritmos de encriptação autenticados (encriptação 3DES-192-CBC + validação HMACSHA1), mostrado abaixo:
00 00 00 00 00 18 00 00 00 08 00 00 00 14 00 00
00 14 AB B1 00 F8 1E 53 E1 0E 76 EB 18 9B 35 CF
03 46 1D DF 87 7C D9 F4 B1 B4 D6 3A 75 55
Os componentes dividem-se da seguinte forma:
O marcador
(00 00)O comprimento da chave de cifra por blocos
(00 00 00 18)O tamanho do bloco da cifra de blocos
(00 00 00 08)o comprimento da chave HMAC
(00 00 00 14)o tamanho do digesto HMAC
(00 00 00 14)a saída
(AB B1 - E1 0E)PRP do cifrador de blocos ea saída PRF
(76 EB - end)do HMAC.
Encriptação + autenticação em modo Galois/Contador
O cabeçalho de contexto consiste nos seguintes componentes:
[16 bits] O valor 00 01, que é um marcador que significa "encriptação GCM + autenticação".
[32 bits] O comprimento da chave (em bytes, big-endian) do algoritmo de cifra simétrica por blocos.
[32 bits] O tamanho do nonce (em bytes, formato big-endian) utilizado durante operações de encriptação autenticadas. (No nosso sistema, isto é fixo com o tamanho de nonce = 96 bits.)
[32 bits] O tamanho do bloco (em bytes, big-endian) do algoritmo de cifra por blocos simétrico. (Para GCM, isto é fixado no tamanho do bloco = 128 bits.)
[32 bits] O tamanho da etiqueta de autenticação (em bytes, big-endian) produzido pela função de encriptação autenticada. (Para o nosso sistema, isto é fixo no tamanho da etiqueta = 128 bits.)
[128 bits] A etiqueta de
Enc_GCM (K_E, nonce, ""), que é a saída do algoritmo de cifra por blocos simétricos dado um input de cadeia vazio e onde nonce é um vetor zero de 96 bits.
K_E é derivado usando o mesmo mecanismo que no cenário de cifragem CBC + autenticação HMAC. No entanto, uma vez que não há K_H em jogo aqui, essencialmente temos | K_H | = 0, e o algoritmo reduz-se à forma abaixo.
K_E = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = "")
Exemplo: AES-256-GCM
Primeiro, seja K_E = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = ""), onde | K_E | = 256 bits.
K_E := 22BC6F1B171C08C4AE2F27444AF8FC8B3087A90006CAEA91FDCFB47C1B8733B8
De seguida, calcule a etiqueta de autenticação de Enc_GCM (K_E, nonce, "") para AES-256-GCM dada nonce = 096 e K_E como mencionado acima.
result := E7DCCE66DF855A323A6BB7BD7A59BE45
Isto produz o cabeçalho de contexto completo abaixo:
00 01 00 00 00 20 00 00 00 0C 00 00 00 10 00 00
00 10 E7 DC CE 66 DF 85 5A 32 3A 6B B7 BD 7A 59
BE 45
Os componentes dividem-se da seguinte forma:
O marcador
(00 01)O comprimento da chave de cifra por blocos
(00 00 00 20)O tamanho do nonce
(00 00 00 0C)O tamanho do bloco da cifra de blocos
(00 00 00 10)o tamanho
(00 00 00 10)da etiqueta de autenticação ea etiqueta de autenticação de executar o cifrador de bloco
(E7 DC - end).