2014-04-08 9 views
13

Ho cercato e non riesco a capire un buon approccio alla crittografia dei dati SQL con il codice Entity Framework Primo. Devo prefigurare questo con quello che sto ospitando in Azure e non ho accesso alla crittografia SQL nativa.Come crittografare i dati in Entity Framework Code Innanzitutto?

Prendendo una pagina da SecurEntity, ho completamente implementato un approccio che utilizza SaveChanges e ObjectMaterialized per gestire la crittografia/decrittografia delle entità, ma in fase di test ho trovato che questo è stato troppo inaffidabile da usare.

Ecco un esempio di alcune delle applicazione:

public override int SaveChanges() 
{ 
    var pendingEntities = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager 
     .GetObjectStateEntries(EntityState.Added | EntityState.Modified) 
     .Where(en => !en.IsRelationship).ToList(); 

    foreach (var entry in pendingEntities) //Encrypt all pending changes 
     EncryptEntity(entry.Entity); 

    int result = base.SaveChanges(); 

    foreach (var entry in pendingEntities) //Decrypt updated entities for continued use 
     DecryptEntity(entry.Entity); 

    return result; 
} 

void ObjectMaterialized(object sender, ObjectMaterializedEventArgs e) 
{ 
    DecryptEntity(e.Entity); 
} 

Ho visto altri post che cifrano manualmente/decifrare tramite proprietà secondarie, in questo modo:

public Value { get; set; } 

[NotMapped] 
public DecryptedValue 
{ 
    get { return Decrypt(this.Value); } 
    set { this.Value = Encrypt(value); } 
} 

Questo sarà sicuramente lavoro, ma trovo che questo approccio sia ... meno che ideale. Quando si utilizza questo approccio, tutti gli sviluppatori devono guadare attraverso tutte le proprietà crittografate per trovare quelli che possono usare.

La soluzione ideale sarebbe per me essere in grado di ignorare l'acquisizione/impostazione di ciascun valore al livello di accesso ai dati. C'è un modo per fare questo? In caso contrario, come posso implementare la crittografia dei dati con Entity Framework - Code First in modo che sia facile da gestire e gestire?

+3

Tenere presente che l'attuale implementazione di SecurEntity presenta un errore di sicurezza irreversibile, il che significa che la chiave generata dal certificato non viene mai utilizzata. Per una soluzione rapida e sporca, vedere https://securentity.codeplex.com/workitem/7376 –

risposta

10

Ho buone notizie. L'instabilità che stavo vivendo con l'approccio SaveChanges/ObjectMaterialized era dovuta al fatto che DetectChanges() non viene chiamato fino a quando DbContext esegue effettivamente il salvataggio.

Sono stato in grado di risolvere questo problema chiamando DetectChanges() prima di estrarre i record aggiunti/modificati dallo ObjectStateManager. Questo ha chiarito qualsiasi stranezza di stato dell'oggetto che stava causando un comportamento di crittografia inconsistente.

Il codice risultante essere:

public override int SaveChanges() 
{ 
    var contextAdapter = ((IObjectContextAdapter)this); 

    contextAdapter.ObjectContext.DetectChanges(); 

    var pendingEntities = contextAdapter.ObjectContext.ObjectStateManager 
     .GetObjectStateEntries(EntityState.Added | EntityState.Modified) 
     .Where(en => !en.IsRelationship).ToList(); 

    foreach (var entry in pendingEntities) //Encrypt all pending changes 
     EncryptEntity(entry.Entity); 

    int result = base.SaveChanges(); 

    foreach (var entry in pendingEntities) //Decrypt updated entities for continued use 
     DecryptEntity(entry.Entity); 

    return result; 
} 

EDIT - Aggiunto un DataContext campione per vedere la mia soluzione end-to-end per la crittografia tutte le entità. Nota: non è necessario utilizzare un attributo personalizzato per crittografare le proprietà. Source

+1

esiste un modo per sovrascrivere tutti i metodi GET delle proprietà per decrittografarli? Non voglio farlo in base all'oggetto, possiamo sovrascriverlo a livello globale, quindi eseguire il loop delle proprietà e decrittografare le proprietà delle stringhe? –

+0

Non sono sicuro di cosa si stia chiedendo, ma è possibile modificare le proprietà di tutti gli oggetti quando vengono salvati/recuperati in EntityFramework. Questo è esattamente ciò che fa "EncryptEntity" e "DecryptEntity" nel mio codice di esempio. Aggiungerò questi due metodi alla mia risposta come riferimento. –

+0

È possibile condividere la versione di EncryptionService? In caso contrario, potresti fornirmi delle indicazioni su come ottenere ciò? Ho provato a cercarlo ma non ho avuto molto successo su cose come dove conservare le chiavi di crittografia, ecc. –