Estendibilità della crittografia di base in ASP.NET Core

Avviso

I tipi che implementano una delle interfacce seguenti devono essere thread-safe per più chiamanti.

IAuthenticatedEncryptor

L'interfaccia IAuthenticatedEncryptor è il blocco predefinito di base del sottosistema di crittografia. In genere è presente un IAuthenticatedEncryptor per chiave e l'istanza di IAuthenticatedEncryptor esegue il wrapping di tutti i materiali della chiave crittografica e le informazioni algoritmiche necessarie per eseguire operazioni di crittografia.

Come suggerisce il nome, il tipo è responsabile della fornitura di servizi di crittografia e decrittografia autenticati. Espone le due API seguenti.

  • Decrypt(ArraySegment<byte> ciphertext, ArraySegment<byte> additionalAuthenticatedData) : byte[]

  • Encrypt(ArraySegment<byte> plaintext, ArraySegment<byte> additionalAuthenticatedData) : byte[]

Il metodo Encrypt restituisce un BLOB che include il testo non crittografato crittografato e un tag di autenticazione. Il tag di autenticazione deve includere i dati autenticati aggiuntivi (AAD), anche se l'AAD stesso non deve essere recuperabile dal payload finale. Il metodo Decrypt convalida il tag di autenticazione e restituisce il payload decifrato. Tutti gli errori (ad eccezione di ArgumentNullException e simili) devono essere omogeneizzati a CryptographicException.

Nota

L'istanza di IAuthenticatedEncryptor stessa non deve effettivamente contenere il materiale della chiave. Ad esempio, l'implementazione potrebbe delegare a un modulo di protezione hardware per tutte le operazioni.

Come creare un IAuthenticatedEncryptor

L'interfaccia IAuthenticatedEncryptorFactory rappresenta un tipo che sa come creare un'istanza IAuthenticatedEncryptor . L'API è la seguente.

  • CreateEncryptorInstance(IKey key) : IAuthenticatedEncryptor

Per qualsiasi istanza IKey specificata, tutti i crittografi autenticati creati dal relativo metodo CreateEncryptorInstance devono essere considerati equivalenti, come nell'esempio di codice seguente.

// we have an IAuthenticatedEncryptorFactory instance and an IKey instance
IAuthenticatedEncryptorFactory factory = ...;
IKey key = ...;

// get an encryptor instance and perform an authenticated encryption operation
ArraySegment<byte> plaintext = new ArraySegment<byte>(Encoding.UTF8.GetBytes("plaintext"));
ArraySegment<byte> aad = new ArraySegment<byte>(Encoding.UTF8.GetBytes("AAD"));
var encryptor1 = factory.CreateEncryptorInstance(key);
byte[] ciphertext = encryptor1.Encrypt(plaintext, aad);

// get another encryptor instance and perform an authenticated decryption operation
var encryptor2 = factory.CreateEncryptorInstance(key);
byte[] roundTripped = encryptor2.Decrypt(new ArraySegment<byte>(ciphertext), aad);


// the 'roundTripped' and 'plaintext' buffers should be equivalent

IAuthenticatedEncryptorDescriptor (solo ASP.NET Core 2.x)

L'interfaccia IAuthenticatedEncryptorDescriptor rappresenta un tipo che sa come esportare se stesso in XML. L'API è la seguente.

  • ExportToXml(): XmlSerializedDescriptorInfo

Serializzazione XML

La differenza principale tra IAuthenticatedEncryptor e IAuthenticatedEncryptorDescriptor è che il descrittore sa come creare il encryptor e fornirlo con argomenti validi. Si consideri un IAuthenticatedEncryptor la cui implementazione si basa su SymmetricAlgorithm e KeyedHashAlgorithm. Il processo del crittografatore consiste nell'utilizzare questi tipi, ma non sa necessariamente da dove provengono questi tipi, quindi non può effettivamente scrivere una descrizione corretta di come ricrearsi se stessa se l'applicazione viene riavviata. Il descrittore funge da livello superiore a questo. Poiché il descrittore sa come creare l'istanza del encryptor (ad esempio, come creare gli algoritmi necessari), può serializzare tale conoscenza in formato XML in modo che l'istanza del encryptor possa essere ricreata dopo la reimpostazione di un'applicazione.

Il descrittore può essere serializzato tramite la routine ExportToXml. Questa routine restituisce un oggetto XmlSerializedDescriptorInfo che contiene due proprietà: la rappresentazione XElement del descrittore e il type che rappresenta un oggetto IAuthenticatedEncryptorDescriptorDeserializer che può essere utilizzato per ripristinare questo descrittore in base all'oggetto XElement corrispondente.

Il descrittore serializzato può contenere informazioni riservate, ad esempio il materiale della chiave crittografica. Il sistema di protezione dei dati include il supporto predefinito per la crittografia delle informazioni prima che venga salvato in modo permanente nell'archiviazione. A tale scopo, il descrittore deve contrassegnare l'elemento che contiene informazioni riservate con il nome dell'attributo "requiresEncryption" (xmlns "<http://schemas.asp.net/2015/03/dataProtection>"), valore "true".

Suggerimento

È disponibile un'API helper per l'impostazione di questo attributo. Chiamare il metodo di estensione XElement.MarkAsRequiresEncryption() che si trova nello spazio dei nomi Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.

Possono anche verificarsi casi in cui il descrittore serializzato non contiene informazioni riservate. Considerare di nuovo il caso di una chiave crittografica archiviata in un modulo di protezione hardware. Il descrittore non può scrivere il materiale della chiave quando si serializza se stesso perché il modulo di protezione hardware non espone il materiale in formato testo non crittografato. Il descrittore potrebbe invece scrivere la versione con wrapping della chiave (se il modulo di protezione hardware consente l'esportazione in questo modo) o l'identificatore univoco del modulo di protezione hardware per la chiave.

IAuthenticatedEncryptorDescriptorDeserializer

L'interfaccia IAuthenticatedEncryptorDescriptorDeserializer rappresenta un tipo che sa deserializzare un'istanza IAuthenticatedEncryptorDescriptor da un oggetto XElement. Espone un singolo metodo:

  • ImportFromXml(elemento XElement): IAuthenticatedEncryptorDescriptor

Il metodo ImportFromXml accetta l'oggetto XElement restituito da IAuthenticatedEncryptorDescriptor.ExportToXml e crea un equivalente dell'oggetto IAuthenticatedEncryptorDescriptor originale.

I tipi che implementano IAuthenticatedEncryptorDescriptorDeserializer devono avere uno dei due costruttori pubblici seguenti:

  • .ctor(IServiceProvider)

  • .ctor()

Nota

IServiceProvider passato al costruttore può essere Null.

Factory di primo livello

La classe AlgorithmConfiguration rappresenta un tipo che sa come creare istanze di IAuthenticatedEncryptorDescriptor . Espone una singola API.

  • CreateNewDescriptor() : IAuthenticatedEncryptorDescriptor

Si pensi a AlgorithmConfiguration come factory di primo livello. La configurazione funge da modello. Esegue il wrapping delle informazioni algoritmiche, ad esempio questa configurazione produce descrittori con una chiave master AES-128-GCM, ma non è ancora associata a una chiave specifica.

Quando viene chiamato CreateNewDescriptor, il materiale di chiave aggiornato viene creato esclusivamente per questa chiamata e viene generato un nuovo IAuthenticatedEncryptorDescriptor che esegue il wrapping di questo materiale chiave e le informazioni algoritmiche necessarie per utilizzare il materiale. Il materiale chiave può essere creato nel software (e mantenuto in memoria), può essere creato e mantenuto all'interno di un modulo di protezione hardware e così via. Il punto cruciale è che due chiamate a CreateNewDescriptor non devono mai creare istanze IAuthenticatedEncryptorDescriptor equivalenti.

Il tipo AlgorithmConfiguration funge da punto di ingresso per le routine di creazione della chiave, ad esempio il rollback automatico della chiave. Per modificare l'implementazione per tutte le chiavi future, impostare la proprietà AuthenticatedEncryptorConfiguration in KeyManagementOptions.