2009-09-18 3 views
6

J'utilise DPAPI en C++ pour chiffrer certaines données que j'ai besoin de stocker dans un fichier. La chose est que je dois lire ce fichier à partir de C#, donc je dois pouvoir:Pourquoi ai-je des sorties différentes lors du cryptage avec DPAPI?

Crypter C++, C++ decrypt (fonctionne bien)

C# Crypter, C# Décrypter (fonctionne bien)

C++ Crypter, C# Décrypter et vice-versa (ne fonctionne pas)

En C# J'utilise DllImport pour Pinvoke les méthodes CryptProtectData et CryptUnprotectData, et je les mettre en œuvre comme expliqué here. Je sais qu'en C# je peux utiliser les méthodes contenues dans la classe ProtectedData mais je le fais de cette façon (en utilisant DllImport) pour m'assurer que les deux codes (C++ et C#) ressemblent et fonctionnent à peu près de la même manière.

Maintenant, la chose étrange est que même si les deux codes semble même que je reçois des sorties différentes, par exemple pour ce texte:

« texte brut »

en C++ je reçois:

01 00 00 00 D0 8C 9D DF 01 15 D1 11 8C 7A 00 C0 4F C2 97 EB 01 00 00 00 2E 6F 88 86 E6 16 9B 4F 9B BF 35 DA 9F C6 EC 12 00 00 00 00 02 00 00 00 00 00 03 66 00 00 A8 00 00 00 10 00 00 00 93 06 68 39 DB 58 FE E9 C4 1F B0 3D 7B 0A B7 48 00 00 00 00 04 80 00 00 A0 00 00 00 10 00 00 00 36 4E 84 05 0D 4A 34 15 97 DC 5B 1F 6C A4 19 D9 10 00 00 00 F5 33 9F 55 49 94 26 54 2B C8 CB 70 7B FE CE 96 14 00 00 00 C5 23 DA BA C8 23 6C 0B B3 88 69 06 00 95 29 AE 76 A7 63 E4

et en C# je reçois:

01 00 00 00 D0 8C 9D DF 01 15 D1 11 8C 7A 00 C0 4F C2 97 EB 01 00 00 00 2E 6F 88 86 E6 16 9B 4F 9B BF 35 DA 9F C6 CE 12 00 00 00 00 02 00 00 00 00 00 66 66 00 A8 00 00 00 10 00 00 00 34 C4 40 CD 91 EC 94 66 E5 E9 23 F7 9E 04 9C 83 00 00 00 00 04 80 00 00 A0 00 00 00 10 00 00 00 12 54 1E 26 72 26 0A D1 11 1D 4D EF 13 1D B2 6F 10 00 00 00 81 9D 46 37 D1 68 5D 17 B8 23 78 48 18 ED 06 ED 14 00 00 00 E4 45 07 1C 08 55 99 80 A4 59 D9 33 BC 0B 71 35 39 05 C4 BB

Comme vous pouvez voir les premiers caractères sont les mêmes mais le reste est e non, donc si quelqu'un a une idée de pourquoi cela peut se produire, j'apprécierai l'aide.

Merci.

code en C++:


value = "plain text"; 
DATA_BLOB DataIn; 
DATA_BLOB DataOut; 

BYTE *pbDataInput =(BYTE *)(char*)value.c_str(); 
DWORD cbDataInput = strlen((char *)pbDataInput)+1; 
DataIn.pbData = pbDataInput; 
DataIn.cbData = cbDataInput; 

CryptProtectData(&DataIn, NULL, NULL, NULL, NULL, 0, &DataOut))

code en C#:

(vous pouvez voir comment mon code C# semble here, puisque est identique à celui de cet exemple Microsoft)

+2

Un éditeur hexadécimal formaté comme exemple de données au lieu de ces captures d'écran serait bien. – schnaader

+0

Impossible de distinguer les captures d'écran. –

+0

@Newton: Vous pouvez ouvrir le lien vers le graphique dans un onglet séparé pour mieux le voir (dans Firefox "Show graphique" fonctionne aussi) – schnaader

Répondre

5

Il serait utile si vous pouviez poster votre C++ et votre code C#. Il y a peut-être quelques différences de paramètres subtiles ou quelque chose comme ça. Par exemple, vous devez vous assurer que le paramètre pOptionalEntropy est le même (ou le définir sur NULL pour tester s'il s'agit de la source d'erreur). Aussi, assurez-vous d'essayer de crypter et décrypter sur le même PC:

[...] Déchiffrement habituellement ne peut se faire sur l'ordinateur où les données ont été cryptées

(Source: MSDN)

EDIT: Quelques commentaires sur le code affiché et la version C# de MSDN (parties de ce qui suit):

public byte[] Encrypt(byte[] plainText, byte[] optionalEntropy) { 
    [...] 
    int bytesSize = plainText.Length; 
    plainTextBlob.pbData = Marshal.AllocHGlobal(bytesSize); 
    plainTextBlob.cbData = bytesSize; 
    Marshal.Copy(plainText, 0, plainTextBlob.pbData, bytesSize); 
    [...] 
    dwFlags = CRYPTPROTECT_LOCAL_MACHINE|CRYPTPROTECT_UI_FORBIDDEN; 
    [...] 
    if(null == optionalEntropy) 
    {//Allocate something 
    optionalEntropy = new byte[0]; // Is copied to entropyBlob later 
    } 
    [...] 
    retVal = CryptProtectData(ref plainTextBlob, "", ref entropyBlob,  
    IntPtr.Zero, ref prompt, dwFlags, 
    ref cipherTextBlob); 
    [...] 
} 

Et voici votre code C++ à nouveau avoir à la fois en vue:

[...] 
BYTE *pbDataInput =(BYTE *)(char*)value.c_str(); 
DWORD cbDataInput = strlen((char *)pbDataInput)+1; 
[...] 
CryptProtectData(&DataIn, NULL, NULL, NULL, NULL, 0, &DataOut)) 

Les paramètres ne correspondent pas et je pense que c'est la source des différences.

La première chose est les drapeaux. Le code C# utilise dwFlags! = 0, votre code C++ utilise dwFlags = 0, donc c'est clairement une différence.

Je ne suis pas sûr de l'entropie. Si vous n'avez pas passé optionalEntropy = null, c'est une différence, mais si c'est null, il y a une affectation "new byte [0]" et je ne suis pas sûr de ce que cela va créer, mais je pense que vous devriez au moins essayer pour passer IntPtr.Zero au lieu de entropyBlob à CryptProtectData pour correspondre avec le code C++. Enfin, votre code C++ inclut le NUL final qui délimite la chaîne C, je ne sais pas comment le chiffrement utilisé ici fonctionne mais il y a des chiffrements qui vous donneront des sorties très différentes si un octet est différent (ou vous avez un octet de plus comme dans ce cas), donc vous devriez soit inclure un NUL se terminant dans le code C# ou le supprimer dans le code C++.

+0

J'ai ajouté du code J'espère que cela aide. – Vic

Questions connexes