2015-01-02 17 views
5

Sto creando uno strumento per gestire le coppie di chiavi RSA su Windows poiché non esiste alcuna funzionalità integrata per questo e facciamo ampio uso delle funzionalità di crittografia RSA in. NETTO.L'importazione della chiave pubblica RSA da XML utilizzando RSACryptoServiceProvider imposta la proprietà PublicOnly su false

Lo strumento fornisce varie funzioni come l'elencazione delle coppie di chiavi RSA esistenti, la creazione di nuove chiavi, l'eliminazione di chiavi, l'esportazione di chiavi e l'importazione di chiavi da un'esportazione XML precedentemente creata (esportata utilizzando ASPNet_RegIIS.exe).

Ho tutte le funzionalità a prescindere dall'importazione solo delle chiavi pubbliche solo per le operazioni di crittografia. Quando le coppie di chiavi sono originariamente create sui server, le esportazioni pubbliche e pubbliche/private vengono eseguite su xml utilizzando aspnet_regiis.exe.

Sono ansioso di fornire l'opzione per crittografare i file di configurazione su altre macchine per impedire la distribuzione delle chiavi private a meno che non sia assolutamente necessario.

Ogni volta che si importa la chiave pubblica da un blocco XML esportato in precedenza, la proprietà PublicOnly di RSACryptoServiceProvider è impostata su false che indica che la coppia di chiavi ha una chiave pubblica e privata. Ho confermato che l'xml non contiene le informazioni sulla chiave privata, quindi il problema non si trova nel file xml.

Il problema sembra verificarsi quando si utilizza l'oggetto CspParameters e si specifica il contrassegno come CspProviderFlags.UseMachineKeyStore. Se si crea RSACryptoServiceProvider senza specificare alcun parametro Csp e quindi si importa la chiave da xml, la proprietà PublicOnly è impostata correttamente su false.

String xmlText = File.ReadAllText(filePath); 
RSACryptoServiceProvider csp = new RSACryptoServiceProvider(); 
csp.FromXmlString(xmlText); 
//csp.PublicOnly equals true; 

Tuttavia, poiché ho bisogno di dare il contenitore di chiavi un nome in modo che possa essere utilizzato in seguito per le operazioni di crittografia sono costretto ad utilizzare l'oggetto CspParameters quando si costruisce un RSACryptoServiceProvider in quanto non v'è altro modo per denominare la chiave contenitore.

String xmlText = File.ReadAllText(filePath); 
CspParameters cspParams = new CspParameters(); 
cspParams.Flags = CspProviderFlags.UseMachineKeyStore; 
cspParams.KeyContainerName = keyContainerName; 
RSACryptoServiceProvider csp = new RSACryptoServiceProvider(cspParams); 
csp.PersistKeyInCsp = true; 
csp.FromXmlString(xmlText); 
//csp.PublicOnly equals false; 

Ho provato una varietà di versioni di questo codice, ma il problema rimane. Prendo atto che ci sono domande simili come RSA Encryption public key not returned from container? tuttavia ritengo che questo problema sia diverso e non sia mai stata data una risposta soddisfacente.

La domanda è, quindi, come posso importare una chiave pubblica RSA da XML e dare un nome al contenitore chiave mentre si assicura solo una coppia di chiavi pubbliche esistente nel contenitore?

EDIT

Ulteriori ricerche intorno a questa zona mostra anche un problema durante l'importazione della chiave completo da XML e anche impostare le bandiere per consentire l'esportazione della chiave.

CspProviderFlags.UseArchivableKey; 

Quando viene specificato questo flag sulla CSP parametro dell'oggetto un'eccezione di tipo "bandiere valido specificato" è gettato sulla linea csp.FromXmlString(xmlText);

Non riesco davvero a spiegarlo. La chiave è stata creata ed esportata in precedenza in XML, sicuramente se la chiave è stata precedentemente esportata, dovrebbe essere possibile importarla e permetterne l'esportazione di nuovo?

Ho fatto molte ricerche su questo ma non riesco a vedere la risposta a nessuno di questi problemi.

Ho provato a cambiare il tipo di provider csp da PROV_RSA_FULL a PROV_RSA_AES poiché credo che questo sia ora il valore predefinito e ho considerato che le chiavi potrebbero essere state originariamente create utilizzando questo anziché PROV_RSA_FULL ma questo non ha fatto alcuna differenza.

risposta

0

Quando si importano i parametri chiave (da XML o da RSAParameters), RSACryptoServiceProvider si scollega dalla chiave corrente se vengono forniti parametri pubblici; sostituisce solo il contenuto della chiave nel contenitore delle chiavi se vengono importati i parametri privati.

http://referencesource.microsoft.com/#mscorlib/system/security/cryptography/rsacryptoserviceprovider.cs,b027f6909aa0a6d1

Il ImportCspBlob prende un percorso diverso, ma alla fine colpisce la stessa conclusione: se un pubblico di sola blob viene importato spicca ad una chiave temporanea. http://referencesource.microsoft.com/#mscorlib/system/security/cryptography/utils.cs,754f1f4055bba611

Sembra che le API di crittografia di Windows sottostanti non consentano l'archiviazione delle chiavi pubbliche (a parte quando vengono archiviate con le loro chiavi private).

La documentazione CNG a https://msdn.microsoft.com/en-us/library/windows/desktop/bb427412(v=vs.85).aspx dice

Per BCryptExportKey per creare una coppia di chiavi persistente, il BLOB chiave di ingresso deve contenere una chiave privata. Le chiavi pubbliche non sono persistenti.

Si presume che intendessero BCryptImportKey, ma "le chiavi pubbliche non sono persistenti" è autorevole.

Per CAPI Non riesco a trovare nulla di così semplice.

Il meglio che posso trovare è la definizione CAPI di 'contenitore di chiavi' (https://msdn.microsoft.com/en-us/library/windows/desktop/ms721590(v=vs.85).aspx#_security_key_container_gly):

contenitore di chiavi

Una parte del database chiave che contiene tutte le coppie di chiavi (scambio e firma coppie di chiavi) appartenenti a un utente specifico. Ogni contenitore ha un nome univoco che viene utilizzato quando si chiama la funzione CryptAcquireContext per ottenere un handle per il contenitore.

Questa definizione fa riferimento solo a "coppie di chiavi", suggerendo che "chiavi pubbliche" potrebbero essere rifiutate dal livello di archiviazione. Dati i comportamenti di RSACryptoServiceProvider, questo sembra abbastanza probabile.

Problemi correlati