Tempo de vida da chave privada do Windows simplificado
Quando uma carga de trabalho carrega uma PKCS#12/PFX no Windows sem definir as opções de EphemeralKeySet armazenamento, o PersistKeySet .NET determina quando a chave privada não é mais necessária e deve ser apagada. Em versões anteriores do .NET (e no .NET Framework), dois conjuntos diferentes de lógica foram usados. No .NET 9, há um único conjunto de lógicas.
Comportamento anterior
Anteriormente, ao carregar um certificado (e sua chave privada) de um PKCS#12/PFX com new X509Certificate2(pfx, password, flags)
, o certificado carregado representava o tempo de vida da chave privada. Quando esse objeto de certificado foi descartado (ou finalizado se fosse coletado sem ser descartado), a chave privada associada foi excluída. Não ocorreu qualquer partilha de propriedade ou transferência de propriedade.
Ao carregar um certificado (e sua chave privada) de um PKCS#12/PFX com X509Certificate2Collection.Import(pfx, password, flags)
o , cada certificado carregado que tinha uma chave privada rastreava o tempo de vida, como acontece com a carga de certificado único. Mas, além disso, um marcador foi colocado na cópia nativa do certificado para indicar que quaisquer cópias também devem rastrear o tempo de vida da chave privada. Se um segundo X509Certificate2 objeto foi criado em termos do mesmo valor subjacente PCERT_CONTEXT
, então qualquer cópia que foi descartada (ou finalizada) primeiro apagou a chave privada de baixo da outra cópia.
O código a seguir falhou (com um CryptographicException ou um NullReferenceException) porque a chave privada foi excluída:
X509Certificate2Collection coll = new X509Certificate2Collection(pfx, password, X509KeyStorageFlags.DefaultKeySet);
X509Certificate2Collection coll2 = coll.Find(X509FindType.FindBySubjectName, "", false);
coll2 = null;
GC.Collect();
GC.WaitForPendingFinalizers();
using (RSA key = coll[0].GetRSAPrivateKey())
{
key.SignData(pfx, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
}
Novo comportamento
A partir do .NET 9, o tempo de vida é sempre associado à X509Certificate2 instância que foi produzida diretamente a partir da carga PKCS#12/PFX.
O mesmo trecho de código na seção Comportamento anterior agora é bem-sucedido.
Versão introduzida
.NET 9 Visualização 7
Tipo de mudança de rutura
Esta mudança é uma mudança comportamental.
Razão para a alteração
A maioria das cargas de trabalho que carregam um PKCS#12/PFX usam a carga de certificado único e entendem a mecânica de vida útil associada a esse método. A mecânica associada à carga de recolha era muitas vezes surpreendente e, por vezes, levava ao apagamento prematuro das chaves.
Ação recomendada
Se você entendeu o gerenciamento do tempo de vida da carga da coleção e dependia da chamada Dispose
de um clone para causar a eliminação da chave, certifique-se de que também está (ou em vez disso) chamando Dispose
o objeto carregado original.