2009-09-18 12 views
6

Sto usando DPAPI in C++ per crittografare alcuni dati che ho bisogno di memorizzare in un file. Il fatto è che ho bisogno di leggere il file da C#, quindi ho bisogno di essere in grado di:Perché ottengo risultati diversi durante la crittografia utilizzando DPAPI?

C++ cifrare, C++ decriptare (sta lavorando bene)

C# cifrare, C# decrypt (sta lavorando bene)

C++ cifrare, C# decodifica e viceversa (non funzionare)

In C# sto usando DllImport per Pinvoke metodi CryptProtectData e CryptUnprotectData, e implementarli come spiegato here. So che in C# posso usare i metodi contenuti nella classe ProtectedData ma lo sto facendo in questo modo (usando DllImport) per assicurarmi che entrambi i codici (C++ e C#) guardino e funzionino più o meno allo stesso modo.

Ora la cosa strana è che, anche se entrambi i codici sembra lo stesso ricevo uscite diverse, ad esempio per questo testo:

"plain text"

in C++ ottengo:

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

e in C# ottengo:

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 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

Come puoi vedere i primi caratteri sono gli stessi ma il resto ar e no, quindi se qualcuno ha un'idea del perché questo possa accadere, apprezzerò l'aiuto.

Grazie.

codice in 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))

codice in C#:

(si può vedere come il mio codice C# sembra here, dal momento che è identico a quello in questo esempio Microsoft)

+2

Alcuni editor esadecimali formattati come esempi di dati invece di quegli screenshot sarebbero belli. – schnaader

+0

Non riesco a distinguere gli screenshot. –

+0

@Newton: è possibile aprire il collegamento all'immagine in una scheda separata per visualizzarla meglio (in Firefox anche "Mostra grafica") – schnaader

risposta

5

E ' sarebbe di aiuto se potessi pubblicare il tuo C++ e il tuo codice C#. Forse ci sono alcune sottili differenze nei parametri o qualcosa del genere. Ad esempio, è necessario assicurarsi che il parametro pOptionalEntropy sia lo stesso (o impostarlo su NULL per verificare se questa è l'origine dell'errore). Inoltre, assicurati di provare a crittografare e decodificare sullo stesso PC:

[...] Decrittazione di solito può essere fatto solo sulla computer in cui i dati sono stati crittografati

(Fonte: MSDN)

EDIT: Alcuni commenti sul codice che avete inviato e la versione C# da MSDN (parti di seguendo):

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); 
    [...] 
} 

Ed ecco il codice C++ di nuovo per avere sia in vista:

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

I parametri non corrispondono e penso che sia la fonte delle differenze.

La prima cosa sono le bandiere. Il codice C# usa dwFlags! = 0, il tuo codice C++ usa dwFlags = 0, quindi questa è chiaramente una differenza.

Non sono sicuro dell'entropia. Se non hai passato optionalEntropy = null è una differenza, ma se è nullo, c'è un "nuovo byte [0]" e non sono sicuro di ciò che verrà creato, ma penso che dovresti almeno provarci passare IntPtr.Zero invece di entropyBlob a CryptProtectData in modo che corrisponda al codice C++.

Ultimo ma non meno importante, il codice C++ include il NUL finale che delimita la stringa C, non so come funzioni la crittografia qui utilizzata ma ci sono crittografie che ti daranno output molto diversi se un byte è diverso (o avete un altro byte come in questo caso), quindi dovreste includere o terminare NUL nel codice C# o rimuoverlo nel codice C++.

+0

Ho aggiunto un codice che spero possa essere d'aiuto. – Vic

Problemi correlati