Assinatura do HLK com um HSM
Introdução
Este tópico descreve alguns dos problemas de instalação e configuração que podem ocorrer ao usar um HSM (Módulo de Segurança de Hardware) baseado em rede de terceiros para armazenar certificados EV (Validação Estendida).
Tela de fundo
Empacotamento de HLK
Os arquivos de pacote HLKX usam as Open Packaging Conventions. A especificação faz parte de um grupo de trabalho ISO, o que implica que os arquivos HLKX não são compatíveis com o Signtool.
Assinatura do Pacote HLK
Quando o HLK assina um pacote, a assinatura e as relações são colocadas no pacote junto com os dados HLK. Estes são os dados que System.IO.Packaging.PackageDigitalSignature
usa para validar a assinatura nos dados do pacote.
Observação
Atualmente, a assinatura do pacote HLK dá suporte apenas a certificados RSA e DSA, conforme determinado pela biblioteca .NET usada para assinar System.Security.Cryptography.Xml.SignedXml
Provedores de serviços criptográficos
Um CSP (provedor de serviços de criptografia) contém implementações de padrões e algoritmos criptográficos. No mínimo, um CSP consiste em uma DLL (biblioteca de vínculo dinâmico) que implementa as funções no CryptoSPI (uma interface de programa do sistema). A maioria dos CSPs contém a implementação de todas as suas próprias funções. No entanto, alguns CSPs implementam suas funções principalmente em um programa de serviço baseado no Windows gerenciado pelo gerenciador de controle de serviço do Windows. Outros implementam funções em hardware, como um cartão inteligente ou coprocessador seguro. Se um CSP não implementar suas próprias funções, a DLL atuará como uma camada de passagem, facilitando a comunicação entre o sistema operacional e a implementação real do CSP.
Repositório e registro de certificado
Todos os certificados no Repositório de certificados são mapeados para uma DLL do CSP que fará a assinatura final. Isso pode ser visto na entrada do registro abaixo.
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider\Microsoft Enhanced DSS and Diffie-Hellman Cryptographic Provider]
"Image Path"="%SystemRoot%\\system32\\dssenh.dll"
"SigInFile"=dword:00000000
"Type"=dword:0000000d
Assinatura do pacote HLKX com um certificado hospedado por um HSM baseado em rede
Configuração do Controlador
Para configurar um controlador HLK para assinar com um certificado HSM, o seguinte deve estar presente no sistema:
- Uma AC (autoridade de certificação) do HSM
- Um arquivo CSP do HSM
As instruções sobre como configurar um cliente HSM com esses componentes devem ser documentadas pelo provedor de HSM.
Assinar com o HLK
Se o controlador estiver configurado corretamente, você poderá apontar para o certificado do HSM como faria com um certificado instalado localmente do HLK e assinar o pacote.
Testar a configuração do HSM
Usar o Signtool
O primeiro passo para entender se podemos assinar é tentar assinar um arquivo usando o signtool. Isso nos permitirá verificar se o fluxo de trabalho de assinatura está funcionando corretamente. Primeiro vamos assinar um arquivo PE (exe ou dll). Por exemplo, assinar usando um nome:
signtool sign /f HighValue.cer /csp "Hardware Cryptography Module" /kHighValueContainerMyControl.exe
signtool sign /n "My Company Certificate" MyFile.exe
ou assinar usando o hash SHA1 do certificado instalado:
signtool sign /sha1 0cf1d2f7befc7d143678f86963aef5572b710cf2 MyFile.exe
O nome do certificado é encontrado nas Informações da Entidade e o hash SHA1 é encontrado na Impressão digital. Ao usar o hash, remova todos os espaços e caracteres especiais que estão no hash para que o formato se pareça com o exemplo acima. Você também pode assinar usando um arquivo PFX (Personal Information Exchange). Isso provavelmente não é o que você deseja fazer, pois um arquivo PFX pode conter a chave privada, enquanto um certificado contém apenas a chave pública.
signtool sign /f certdata.pfx MyFile.exe
Você pode verificar a assinatura usando o signtool
signtool verify /v /pa MyFile.exe
Se você conseguiu assinar e verificar um arquivo usando qualquer coisa, exceto um arquivo PFX, poderá tentar assinar um pacote HLK. Se você não conseguiu assinar, consulte a seção Solução de problemas.
Usar PackageDigitalSignature
Há um exemplo de código de assinatura usando PackageDigitalSignature
no final deste documento na seção Exemplos de código. Você também deve ter obtido o arquivo C# completo quando recebeu este documento. Para usar este exemplo, você precisará fornecer um caminho completo para seu pacote não assinado e a impressão digital do certificado que você usará para assinar. Se você não conseguiu assinar, consulte a seção Solução de problemas.
Solução de problemas
A causa mais provável é que não há um certificado e um CSP associado instalado em seu sistema a partir do HSM. Algumas das coisas que você pode tentar são as seguintes:
- Você consegue entrar neste sistema usando apenas as ferramentas suportadas pelo seu fornecedor de HSM?
- O fornecedor do HSM instala um certificado e um CSP neste sistema?
- Quais são as propriedades do certificado?
- O seu fornecedor de HSM oferece suporte e documenta usando o signtool? Se um arquivo puder ser assinado usando o Signtool com um HSM, isso será um indicador de que o sistema foi configurado corretamente e implica que o HLK também pode assinar pacotes HLKX.
- Ao executar o código de exemplo (HSM_example.cs), o que é impresso para o CspKeyContainerInfo.ProviderName
- Esse nome de provedor é mapeado para a DLL CSP fornecida pelo fornecedor correto. Essas informações podem ser encontradas no registro, conforme mostrado acima.
Exemplos de código
PackageDigitalSignatureManager
public static void Sign(string package, X509Certificate2 certificate)
{
// Open the package to sign it
Package packageToSign = Package.Open(package);
// Specify that the digital signature should exist
// embedded in the signature part
PackageDigitalSignatureManager signatureManager = new PackageDigitalSignatureManager(packageToSign);
signatureManager.CertificateOption = CertificateEmbeddingOption.InCertificatePart;
// We want to sign every part in the package
List<Uri> partsToSign = new List<Uri>();
foreach (PackagePart part in packageToSign.GetParts())
{
partsToSign.Add(part.Uri);
}
// We will sign every relationship by type
// This will mean the signature is invalidated if *anything* is modified in //the package post-signing
List<PackageRelationshipSelector> relationshipSelectors = new List<PackageRelationshipSelector>();
foreach (PackageRelationship relationship in packageToSign.GetRelationships())
{
relationshipSelectors.Add(new PackageRelationshipSelector(relationship.SourceUri, PackageRelationshipSelectorType.Type, relationship.RelationshipType));
}
try
{
signatureManager.Sign(partsToSign, certificate, relationshipSelectors);
}
finally
{
packageToSign.Close();
}
}