Managed blob SIMPLEBLOB não corresponde SIMPLEBLOB Unmanaged (RSA -Cryptography)
-
22-08-2019 - |
Pergunta
O blob simples que é gerado usando
CryptExportKey(hKey, hPublicKey, SIMPLEBLOB, 0, lpData, &nSize);
não coincide com aquele gerado a partir do código a seguir (note que client.key é o valor da chave de texto simples de hKey encontrado usando http://www.codeproject.com/KB/security/plaintextsessionkey.aspx )
CspParameters cspParams = new CspParameters();
cspParams.KeyContainerName = "Container Name";
cspParams.KeyNumber = (int)KeyNumber.Exchange;
cspParams.ProviderType = 1;
cspParams.ProviderName = "Microsoft Enhanced Cryptographic Provider v1.0"; cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
RSACryptoServiceProvider rsaClient = new RSACryptoServiceProvid(cspParams);
rsaClient.ImportCspBlob(File.ReadAllBytes(@"C:\client.key"));//Generate a SIMPLEBLOB session key
byte[] session = GetRC4SessionBlobFromKey(keyMaterial, rsaClient);//Encrypt a key using public key and write it in a SIMPLEBLOB format
public byte[] GetRC4SessionBlobFromKey(byte[] keyData, RSACryptoServiceProvider publicKey)
{
using(MemoryStream ms = new MemoryStream())
using(BinaryWriter w = new BinaryWriter(ms))
{
w.Write((byte) 0x01); // SIMPLEBLOB
w.Write((byte) 0x02); // Version 2
w.Write((byte) 0x00); // Reserved
w.Write(0x00006801); // ALG_ID = RC4 for the encrypted key.
w.Write(0x0000a400); // CALG_RSA_KEYX
w.Write(publicKey.Encrypt(keyData, false));
w.Flush();
return ms.ToArray();
}
}
Por que isso?
Solução
-
O código na minha originais resposta não foi correta. Você tem que reverter os bytes criptografados. Eu atualizei a resposta para corrigir esse problema.
-
O código acima está faltando um "
w.Write((byte) 0x00); // Reserved
". Não foi um erro que a minha resposta original tinha repetido essa linha. -
RSA PKCS # 1 de criptografia (que é usado dentro do SIMPLEBLOB) não é determinista. OU SEJA Você não terá o mesmo resultado, criptografando os mesmos dados duas vezes.
Assim, para resumir: Alterar o código acima para:
public byte[] GetRC4SessionBlobFromKey(byte[] keyData, RSACryptoServiceProvider publicKey)
{
using(MemoryStream ms = new MemoryStream())
using(BinaryWriter w = new BinaryWriter(ms))
{
w.Write((byte) 0x01); // SIMPLEBLOB
w.Write((byte) 0x02); // Version 2
w.Write((byte) 0x00); // Reserved
w.Write((byte) 0x00); // Reserved
w.Write(0x00006801); // ALG_ID = RC4 for the encrypted key.
w.Write(0x0000a400); // CALG_RSA_KEYX
byte[] encryptedKey = publicKey.Encrypt(key.Key);
byte[] reversedEncryptedKey = new byte[encryptedKey.Length];
for(int i=0;i<encryptedKey.Length;i++){
reversedEncryptedKey[i] = encryptedKey[encryptedKey.Length - 1 - i];
}
w.Write(reversedEncryptedKey); // encrypted key in LSB byte order
w.Flush();
return ms.ToArray();
}
}
e, em seguida, verificar se ela funciona usando CryptImportKey () para importar o SIMPLEBLOB em vez de tentar comparar o resultado com CryptExportKey ().
Outras dicas
Eu sou incapaz de editar o meu próprio quesiton e, portanto, estou colocando o conteúdo que você queria que eu anexar aqui nesta resposta, tenho de captura de tela das imagens do editor binário / janela imediata no visual studio abaixo
CryptExportKey - SIMPLEBLOB
CryptExportKey - SIMPLEBLOB http://img14.imageshack.us/img14/1926/ cryptoexportkeysimplebl.jpg
valor KeyMaterial na janela de depuração
valor Material da Chave que é guardado no arquivo usando o artigo do projeto de código
valor de chave de sessão de GetRC4SessionBlobFromKey () (valor inteiro de bytes individuais separadas por uma vírgula)
Muito obrigado por olhar para isso e por favor deixe-me saber se há qualquer outra informação que eu posso oferecer.