Pergunta

Eu tenho um aplicativo existente escrito em C++ para Windows.Este aplicativo usa o Win32 CryptoAPI para gerar uma chave de sessão TripleDES para criptografar/descriptografar dados.Estamos usando o expoente de um truque para exportar a chave da sessão como um blob, o que permite que o blob seja armazenado em algum lugar em um formato descriptografado.

A questão é como podemos usar isso em nosso aplicativo .NET (C#).A estrutura encapsula/envolve muito do que a CryptoAPI está fazendo.Parte do problema é que a CryptAPI afirma que o algoritmo TripleDES para o Provedor criptográfico aprimorado da Microsoft é de 168 bits (3 chaves de 56 bits).No entanto, a estrutura .NET afirma que suas chaves são de 192 bits (3 chaves de 64 bits).Aparentemente, os 3 bytes extras no framework .NET são para paridade?

De qualquer forma, precisamos ler a parte chave do blob e, de alguma forma, poder usá-la em nosso aplicativo .NET.Atualmente não estamos obtendo os resultados esperados ao tentar usar a chave no .NET.A descriptografia está falhando miseravelmente.Qualquer ajuda seria muito apreciada.

Atualizar:

Tenho trabalhado em maneiras de resolver isso e encontrei uma solução que postarei a tempo.No entanto, ainda apreciaríamos qualquer feedback de outras pessoas.

Foi útil?

Solução

Introdução

Finalmente estou conseguindo postar a solução.Espero que forneça alguma ajuda a outras pessoas que possam estar fazendo coisas semelhantes.Realmente não há muita referência a fazer isso em outro lugar.

Pré-requisitos

Para que muito disso faça sentido é necessário ler o expoente de um truque, que permite exportar uma chave de sessão para um blob (uma estrutura de bytes bem conhecida).Pode-se então fazer o que quiser com esse fluxo de bytes, mas ele contém a chave mais importante.

A documentação do MSDN é confusa

Neste exemplo específico, estou usando o Provedor criptográfico aprimorado da Microsoft, com o DES triplo (CALG_3DES) algoritmo.A primeira coisa que me surpreendeu foi o fato de que o comprimento da chave está listado em 168 bits, com um comprimento de bloco de 64 bits.Como o comprimento da chave pode ser 168?Três chaves de 56 bits?O que acontece com o outro byte?

Então, com essas informações, comecei a ler em outro lugar como o último byte é realmente paridade e por alguma razão o CryptoAPI remove isso.Esse é realmente o caso?Parece meio louco que eles fizessem isso, mas tudo bem.

Consumo de chave em .NET

Usando o TripleDESCryptoServiceProvider, notei que os comentários nos documentos indicavam que:

Este algoritmo suporta comprimentos de chave de 128 bits a 192 bits em incrementos de 64 bits.

Portanto, se o CryptoAPI tiver comprimentos de chave de 168, como colocarei isso no .NET, que suporta apenas múltiplos de 64?Portanto, o lado .NET da API leva em consideração a paridade, enquanto o CryptoAPI não.Como se poderia imaginar... confuso eu estava.

Com tudo isso, estou tentando descobrir como reconstruir a chave no lado .NET com as informações de paridade adequadas.É factível, mas não muito divertido...vamos deixar por isso mesmo.Depois que coloquei tudo isso no lugar, tudo acabou falhando com MAIÚSCULA F.

Ainda comigo?Ótimo, porque acabei de cair do cavalo de novo.

Lâmpadas e fogos de artifício

Veja só, enquanto estou vasculhando o MSDN em busca de cada última informação, encontro uma peça conflitante no Win32 CryptExportKey função.Baixo e eis que encontro esta informação inestimável:

Para qualquer uma das permutações de chave DES que usam PLAINTEXTKEYBLOB, apenas o tamanho total da chave, incluindo o bit de paridade, pode ser exportado.Os seguintes tamanhos de chave são suportados.

Tamanho de chave compatível com algoritmo

CALG_DES 64 bits

CALG_3DES_112 128 bits

CALG_3DES 192 bits

Portanto, ele exporta uma chave múltipla de 64 bits!Uau!Agora, para corrigir o código no lado .NET.

Ajuste no código de importação do .NET

É importante ter em mente a ordem dos bytes ao importar um fluxo de bytes que contém uma chave que foi exportada como um blob da CryptoAPI.As duas APIs não usam a mesma ordem de bytes, portanto, como @nic-forte indica que reverter a matriz de bytes é essencial antes de realmente tentar usar a chave.Fora isso, as coisas funcionam conforme o esperado.Simplesmente resolvido:

Array.Reverse( keyByteArray );

Conclusão

Espero que isso ajude alguém aí.Passei muito tempo tentando rastrear isso.Deixe algum comentário se tiver mais dúvidas e posso tentar ajudar a preencher quaisquer detalhes.

Feliz criptografia!

Outras dicas

Ok, esqueça a última resposta que não consigo ler :) Você está trabalhando com chaves 3Des e não com chaves RSA.

Trabalhei em vários códigos para compartilhar chaves entre .NET, CryptoAPI e openssl.Encontrei muitos bons exemplos de código aqui para fazer as principais conversões:

http://www.jensign.com/JavaScience/cryptoutils/index.html

Há algumas coisas do 3des em alguns desses exemplos, mas estavam relacionadas ao openssl -> .NET iirc.

Também acabei de revisar o código da chave RSA e uma coisa que percebi que estou fazendo é usar Array.Reverse() em todas as partes principais da chave RSA (D,DP,DQ,InverseQ,Modulus,P,Q) i acho que converter endian.Lembro-me de que isso não era óbvio quando abordei o problema pela primeira vez.

Espero que algo disso tenha ajudado.Boa sorte.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top