Como faço para adicionar o SSL para um aplicativo .NET que usa HttpListener - ela vai * não * estar em execução no IIS

votos
37

A maioria das edições recentes em negrito Eu estou usando o .net HttpListenerclasse, mas estou não vai estar em execução no IIS e não estou usando ASP.net. Este web site descreve o código para uso real para implementar SSL com asp.net e este site descreve como configurar os certificados (embora eu não tenho certeza se ele funciona somente para IIS ou não).

A documentação classe descreve vários tipos de autenticação (básico, digerir, o Windows, etc.) --- nenhum deles referem-se a SSL. Ele diz que, se HTTPS é usado, você precisará configurar um certificado de servidor . Será que isso vai ser uma configuração de propriedade uma linha e HttpListenerfiguras fora o resto?

Em suma, eu preciso saber como configurar os certificados e como modificar o código para implementar SSL.

Embora não ocorre quando eu estou tentando acessar HTTPS, eu fiz notar um erro no meu log de eventos do sistema - a fonte é Schannel e o conteúdo da mensagem é:

Ocorreu um erro fatal ao tentar acessar a chave privada credencial de servidor SSL. O código de erro retornado do módulo criptográfico é 0x80090016.

EDIT:
Medidas tomadas até agora

  • Criado um trabalho HttpListener em C # que funciona para conexões HTTP (por exemplo, http: // localhost: 8089 / foldername /
  • Criado um certificado usando makecert.exe
  • Adicionado o certificado a ser confiável usando Certmgr.exe
  • Usado Httpcfg.exe para escutar para conexões SSL em uma porta de teste (por exemplo, 8090)
  • Adicionado a porta 8080 para o HttpListener via listener.Prefixes.Add ( https: // localhost: 8090 / foldername / );
  • testado uma conexão do cliente HTTP, por exemplo, ( http: // localhost: 8089 / foldername / ) em um navegador e receber retorno correto
  • testado uma conexão do cliente HTTPS, por exemplo, ( http: // localhost: 8090 / foldername / ) em um navegador e receber Transferência de Dados Interrompida(no Firefox)
  • depuração no visual studio mostra que o retorno de chamada de ouvinte que recebe as solicitações não é atingido quando a conexão HTTPS começa - Eu não vejo qualquer lugar que eu poderia definir um ponto de interrupção para pegar outra anteriormente nada.
  • netstat mostra que portas de escuta estão abertos tanto para HTTPS e HTTP. a porta HTTPS não ir para TIME_WAIT depois que uma conexão é tentada.
  • Fiddler e HTTPAnalyzer não pegar qualquer parte do tráfego, eu acho que não fica longe o suficiente no processo para aparecer nessas ferramentas de análise de HTTP

Questões

  • Qual poderia ser o problema?
  • Há um pedaço de código .Net estou em falta (o que significa que tenho de fazer mais em C # que não basta adicionar um prefixo para o ouvinte que aponta para HTTPS, que é o que eu fiz)
  • Tenha um perdeu uma etapa de configuração em algum lugar?
  • O que mais eu poderia fazer para analisar o problema?
  • É a mensagem de erro na eventos do sistema um sinal do problema? Se sim, como seria ser corrigido?
Publicado 06/08/2008 em 22:18
fonte usuário
Em outras línguas...                            


6 respostas

votos
9

Eu tenho um problema semelhante, e parece que poderia haver um problema com o próprio certificado.

Aqui está o caminho que funcionou para mim:

makecert.exe -r -a sha1 -n CN=localhost -sky exchange -pe -b 01/01/2000 -e 01/01/2050 -ss my -sr localmachine

olhai para cima certificado de impressão digital , copiá-lo para a área de transferência e remover os espaços. Este será um parâmetro após -h no comando seguinte:

HttpCfg.exe set ssl -i 0.0.0.0:801 -h 35c65fd4853f49552471d2226e03dd10b7a11755

em seguida, executar um serviço de acolhimento em https: // localhost: 801 / e ele funciona perfeitamente.

o que não pode fazer o trabalho é para https para rodar em certificado auto-gerado. Aqui está o código eu corro para gerar um (manipulação de erro retirado para maior clareza):

LPCTSTR pszX500 = subject;
DWORD cbEncoded = 0;
CertStrToName(X509_ASN_ENCODING, pszX500, CERT_X500_NAME_STR, NULL, pbEncoded, &cbEncoded, NULL);
pbEncoded = (BYTE *)malloc(cbEncoded);
CertStrToName(X509_ASN_ENCODING, pszX500, CERT_X500_NAME_STR, NULL, pbEncoded, &cbEncoded, NULL);

// Prepare certificate Subject for self-signed certificate
CERT_NAME_BLOB SubjectIssuerBlob;
memset(&SubjectIssuerBlob, 0, sizeof(SubjectIssuerBlob));
SubjectIssuerBlob.cbData = cbEncoded;
SubjectIssuerBlob.pbData = pbEncoded;

// Prepare key provider structure for self-signed certificate
CRYPT_KEY_PROV_INFO KeyProvInfo;
memset(&KeyProvInfo, 0, sizeof(KeyProvInfo));
KeyProvInfo.pwszContainerName = _T("my-container");
KeyProvInfo.pwszProvName = NULL;
KeyProvInfo.dwProvType = PROV_RSA_FULL;
KeyProvInfo.dwFlags = CRYPT_MACHINE_KEYSET;
KeyProvInfo.cProvParam = 0;
KeyProvInfo.rgProvParam = NULL;
KeyProvInfo.dwKeySpec = AT_SIGNATURE;

// Prepare algorithm structure for self-signed certificate
CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm;
memset(&SignatureAlgorithm, 0, sizeof(SignatureAlgorithm));
SignatureAlgorithm.pszObjId = szOID_RSA_SHA1RSA;

// Prepare Expiration date for self-signed certificate
SYSTEMTIME EndTime;
GetSystemTime(&EndTime);
EndTime.wYear += 5;

// Create self-signed certificate
pCertContext = CertCreateSelfSignCertificate(NULL, &SubjectIssuerBlob, 0, &KeyProvInfo, &SignatureAlgorithm, 0, &EndTime, 0);
hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"MY");
CertAddCertificateContextToStore(hStore, pCertContext, CERT_STORE_ADD_REPLACE_EXISTING, 0);

Certificado mostra muito bem e tem uma chave privada a trabalhar, mas https será tempo limite como se a impressão digital não foi registrado. Se alguém sabe por que - comentário plz

EDIT1 : Depois de algum brincar, eu descobri a inicialização para CertCreateSelfSignCertificate que gera certificado apropriado:

CRYPT_KEY_PROV_INFO KeyProvInfo;
memset(&KeyProvInfo, 0, sizeof(KeyProvInfo));
KeyProvInfo.pwszContainerName = _T("my-container");
KeyProvInfo.pwszProvName = _T("Microsoft RSA SChannel Cryptographic Provider");
KeyProvInfo.dwProvType = PROV_RSA_SCHANNEL;
KeyProvInfo.dwFlags = CRYPT_MACHINE_KEYSET;
KeyProvInfo.cProvParam = 0;
KeyProvInfo.rgProvParam = NULL;
KeyProvInfo.dwKeySpec = AT_KEYEXCHANGE;
Respondeu 07/04/2009 em 22:15
fonte usuário

votos
7

Você apenas tem que ligar um certificado para um ip: porto e, em seguida, abrir o seu ouvinte com um prefixo https: //. 0.0.0.0 aplica-se a todos os ip. appid é qualquer GUID aleatório, e certHash é o hash do certificado (às vezes chamado de thumprint).

Execute o seguinte com cmd.exe usando privilégios de administrador.

netsh http add sslcert ipport=0.0.0.0:1234 certhash=613bb67c4acaab06def391680505bae2ced4053b  appid={86476d42-f4f3-48f5-9367-ff60f2ed2cdc}

Se você quiser criar um certificado auto-assinado para testar isso,

  1. Abra o IIS
  2. Clique no seu nome de computador
  3. Clique Certificados de Servidor ícone
  4. Clique em Gerar certificado auto-assinado
  5. Clique duas vezes e ir aos detalhes
  6. Você vai ver a impressão digital lá, basta remover os espaços.

    HttpListener listener = new HttpListener();
    listener.Prefixes.Add("https://+:1234/");
    listener.Start();
    Console.WriteLine("Listening...");
    HttpListenerContext context = listener.GetContext();
    
    using (Stream stream = context.Response.OutputStream)
    using (StreamWriter writer = new StreamWriter(stream))
        writer.Write("hello, https world");
    
    Console.ReadLine();
    

Depois de executar este programa eu apenas navegado para https://localhost:1234ver o texto impresso. Desde o certificado CN não coincide com a url e não está no armazenamento de certificados confiáveis você receberá um aviso de certificado. O texto é criptografado, porém, como você pode verificar com uma ferramenta como o Wireshark.

Se você quiser mais controle sobre a criação de um openssl certificado x509 auto-assinado é uma grande ferramenta e há uma porta para janelas. Eu tinha muito mais sucesso com ele do que a ferramenta makecert.


É também muito importante que a se você está se comunicando com um serviço de https do código que tem um aviso SSL, é necessário configurar o validador certificado no gerenciador de ponto de serviço para contorná-lo para fins de teste.

ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true;
Respondeu 29/09/2012 em 04:55
fonte usuário

votos
6

Eu não tê-lo totalmente implementado ainda, mas este site parece dar uma boa explicação passo a passo de criação dos certificados e o código.

Respondeu 06/08/2008 em 23:29
fonte usuário

votos
4

Aqui está uma forma alternativa de vincular a certifiate SSL para a combinação IP / PORT sem usar httpcfg.exe(XP) ou netsh.exe(Vista +).

http://dotnetcodebox.blogspot.com.au/2012/01/how-to-work-with-ssl-certificate.html

A essência do que é que você pode usar um C ++ HttpSetServiceConfiguration API embutido no Windows para fazê-lo através de programação em vez de através da linha de comando, portanto, remover a dependência do sistema operacional e ter httpcfg instalado.

Respondeu 02/03/2015 em 05:14
fonte usuário

votos
3

A documentação da classe

tem esta nota:

Se você criar um HttpListener usando https, você deve selecionar um certificado de servidor para esse ouvinte. Caso contrário, uma consulta HttpWebRequest deste HttpListener falhará com um perto inesperada da conexão.

e isto:

Você pode configurar certificados de servidor e outras opções ouvinte usando Httpcfg.exe. Veja http://msdn.microsoft.com/library/default.asp?url=/library/en-us/http/http/httpcfg_exe.asp para mais detalhes. O executável é fornecido com o Windows Server 2003, ou pode ser construído a partir do código fonte disponível no SDK da plataforma.

É a primeira nota explicada pelo segundo? Conforme descrito na pergunta, usado Httpcfg.exe para ligar o certificado para uma porta específica. Se eles pretendem algo diferente do que isso, a nota é ambíguo.

Respondeu 08/08/2008 em 17:37
fonte usuário

votos
2

Eu encontrei o mesmo problema que você. Felizmente depois de pesquisar passos concretos sobre esta página tornar SSL trabalhar com o meu HttpListener.

Respondeu 28/01/2009 em 11:22
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more