Por Gilberto Uchôa
gilbertouchoa@yahoo.com.br
Gilberto Uchôa trabalha na Hepta Informática desde 1993, sempre na área de desenvolvimento, atuando em projetos como gerente de projeto e arquiteto de soluções, e atuando nas áreas de consultoria e treinamento, ministrando os cursos oficiais das várias plataformas de desenvolvimento da Microsoft.

Assinaturas Digitais Usando WSE

Assinatura Digital

Uma informação de alguma forma associada a uma mensagem, identificando de forma inequívoca a origem desta mensagem.

WSE

Web Services Enhancements, um SDK da Microsoft que implementa os padrões "WS-*" da OASIS (Organization for the Advancement of Structured Information Standards), um grupo similar em funcionamento ao W3C, que "recomenda" padrões a serem usados nas diversas áreas da indústria de software. O padrão "WS-*" é na verdade uma série de recomendações em várias áreas relativas a web services, tais como WS-Security (segurança de web services), WS-Routing (roteamento end-to-end de mensagens usando web services), WS-Attachments (anexação de documentos em mensagens SOAP), e outros.

Sumário

Este artigo apresenta a o conceito de assinatura digital, a importância de uso das assinaturas digitais para garantir a identidade do originador de uma mensagem e um exemplo de implementação de geração e verificação de assinaturas digitais usando a biblioteca WSE - Web Services Enhancements da Microsoft.

Não-Repudiação: A Necessidade de Garantir a Origem de Uma Mensagem
            Assinaturas e Autenticação
            Assinaturas Digitais
            Os Detalhes de Implementação
Usando WSE para Gerar Uma Assinatura Digital - Preparação
            Obtendo um Certificado para Testes
            Exportando o Certificado para Arquivo
            Instalando o WSE
Usando WSE para Gerar Uma Assinatura Digital - Codificação
            Geração da Assinatura
            Verificação da Assinatura
Pontos Finais
           

Não-Repudiação: A Necessidade de Garantir a Origem de Uma Mensagem

Repudição (repudiation) é uma forma de ataque a um sistema informatizado. Basicamente consiste em o usuário dizer "Não fui eu!". A "versão web service" deste ataque é bem simples: você expõe um serviço da sua empresa via web service. O seu cliente chama o web service, fazendo com que a sua empresa realize um trabalho em benefício dele, e na hora de apresentar a fatura, você ouve "Mas não fui eu!".

Veja que isto só pode ser evitado se você tiver uma forma inequívoca de comprovar que sim, realmente foi ele quem executou a chamada. Estes mecanismos são chamados de mecanismos de não-repudiação (non-repudiation), e são implementados com o uso de alguma forma de assinatura digital.

Assinaturas e Autenticação

A assinatura digital funciona exatamente como a assinatura que você coloca em um documento. Suponha que você vai vender o seu apartamento. Você faz o seu "instrumento particular de compra e venda", que é o contrato de venda do apê. O comprador revisa este contrato e diz "ok, concordo com tudo". Mas a maneira de formalizar a mensagem "ok, concordo com o contrato" é assiná-lo. A assinatura garante que ele está de acordo com o contrato, e serve para evitar que ele diga depois "Mas eu não concordei com o contrato!!!". Agora, ele ainda pode alegar que a assinatura não é a dele. Para isto, é envolvida no negócio uma terceira entidade, o cartório. O cartório é uma parte isenta no negócio, e as outras duas partes envolvidas - você e seu comprador - implicitamente confiam nele. Então desta forma a autenticidade de uma assinatura pode ser estabelecida:

  1. Seu comprador vai ao cartório e reconhece a firma dele, ou seja, apresenta um documento que o identifica (p.e., a carteira de identidade), e depois assina um monte de vezes um cartão. O cartório agora sabe que a assinatura naquele cartão é a assinatura do seu comprador.
  2. Seu comprador assina o contrato de venda do apê, e vai no cartório para reconhecer a firma, ou seja, para o cartório atestar que a assinatura que está no contrato é a assinatura que ele tem como sendo a registrada para o comprador.
  3. Você armazena o contrato com a firma reconhecida para qualquer eventualidade.

Desta forma, caso o comprador mais tarde diga "Mas eu não concordei com o contrato!!!", você retira o contrato assinado por ele, e com a assinatura reconhecida pelo cartório, e esfrega na fuça dele. Veja que somente a assinatura não basta; deve haver a autenticação da assinatura para que o documento tenha validade legal.

Assinaturas Digitais

A assinatura digital funciona exatamente da mesma forma. Suponha que você tem um serviço de entrega de pacotes. Você criou um site, e criou um web service para que seus clientes possam solicitar a entrega de um pacote:

    <WebMethod()> _
    Public Sub NovaEntrega( _
        ByVal origem As Endereco, _
        ByVal destino As Endereco, _
        ByVal idPacote As String, _
        ByVal dataHoraRecebimento As DateTime)

Outras empresas podem chamar o seu web service. Seu "Gerente Dos Motoboys" tira o relatório com as entregas a fazer no dia e despacha o pessoal. No fim do mês, sua empresa envia a nota de cobrança para todo mundo que usou seus serviços, cobrando todas as entregas que foram realizadas no mês.

A questão óbvia é: como evitar que, quando da apresentação da nota, o seu cliente fale "Mas não fui eu quem fez esse pedido!"? Para isto você vai usar assinaturas digitais. De uma forma geral, o processo de uso da assinatura digital é o seguinte:

  1. Você gera um par de chaves de criptografia assimétrica (se você não conhece criptografia assimétrica dê uma olhada aqui).
  2. Você fornece a sua chave pública a uma CA, e pede um certificado digital para ela. Uma CA (certification authority), ou autoridade certificadora, é uma empresa responsável por emitir certificados digitais.
  3. Você fornece documentos comprovando que você é você, ou que você representa sua empresa, dependendo de se o certificado é para você ou para a sua empresa.
  4. A CA cria um documento que contém a sua chave pública assinada com a chave privada da CA, garantido que o documento foi gerado pela CA. Esse documento é o certificado digital.

Veja agora que fica simples evitar o problema de repudição do nosso serviço de entregas. Você coloca como exigência básica de uso do seu serviço que a empresa que está usando o serviço tem que ter um certificado digital. O sistema que está chamando o seu web service gera uma assinatura do pedido sendo feito e passa esta assinatura como parâmetro do método:

    <WebMethod()> _
    Public Sub NovaEntrega( _
        ByVal origem As Endereco, _
        ByVal destino As Endereco, _
        ByVal idPacote As String, _
        ByVal dataHoraRecebimento As DateTime, _
        ByVal assinaturaPedido As Byte())

Seu web service recebe o pedido, valida a assinatura, assim garantindo sua origem, e armazena a assinatura em caso de necessidade de validação de um determinado pedido.

Os Detalhes de Implementação

"Tá, eu entendi como eu uso a assinatura digital. Mas o quê tem dentro dela? Como ela garante que eu sou eu?"

A assinatura digital se baseia no uso de chaves públicas e privadas de criptografia. Estas chaves são sempre geradas aos pares, sendo matematicamente relacionadas.Uma informação criptografada com a chave pública só pode ser descriptografada com a chave privada, e vice-versa. É no "vice-versa" que estamos interessados.

A assinatura digital é gerada da seguinte forma:

  1. Você gera o hash da mensagem a assinar. Um hash é uma representação estatisticamente única da mensagem; existem vários algoritmos comerciais de geração de hashes hoje em dia, tais como o MD5 e a família SHA de algoritmos. O resultado destes algoritmos é um array de bytes, que representa a mensagem original. 
  2. Você criptografa o hash com sua chave privada. De acordo com a teoria, somente a correspondente chave pública pode descriptografar esta informação, gerando o valor original (o hash da mensagem).

O resultado da criptografia do hash da mensagem original é a assinatura digital da mensagem. Para verificar a mensagem, deve ser feito o seguinte:

  1. Você descriptografa a assinatura da mensagem com a chave pública de quem enviou a mensagem. O resultado será um valor que deve ser o hash da mensagem.
  2. Você aplica na mensagem o mesmo algoritmo de hash que foi aplicado na geração da assinatura.
  3. Você compara os dois hashes, o que você gerou e o obtido pela descriptografia da assinatura digital. Caso os dois hashes sejam iguais, a assinatura é válida, e você sabe que quem gerou a assinatura foi o dono da chave privada correspondente à chave pública que você usou na conferência.

"Aaaahhnnntááááá. Mas e o certificado digital? Aonde ele entra nessa parada?"

O certificado digital garante a identidade do dono da chave pública. Lembre que ele é um documento, contendo a chave pública em questão, e assinado pela CA, que garante que verificou a identidade do pretenso dono daquela chave pública. Então ao verificar uma assinatura usando uma chave pública que está dentro de um certificado digital, você tem certeza de quem criou a assinatura, desta forma identificando inequivocamente o originador da mensagem. 

Usando WSE para Gerar uma Assinatura Digital - Preparação

O WSE facilita a geração e conferência de assinaturas digitais ao disponibilizar uma classe que consegue carregar um certificado digital, e extrair dele as chaves pública e/ou privada presentes no certificado. De posse destas chaves, fica fácil gerar ou verificar assinaturas, usando as classes do namespace System.Security.Cryptography.

A biblioteca de classes do .NET Framework implementa os dois algoritmos de assinatura digital mais comuns hoje em dia: RSA (Rivest, Shamir e Adleman - seus inventores) e DSA (Digital Signature Algorithm). Vamos usar o RSA, pela simples razão de que foi o algoritmo usado para criar o certificado digital que usei nos testes.

Obtendo um Certificado para Testes

A primeira providência que você deve fazer é obter um certificado digital para testes. Se sua empresa tem um, ótimo. Se você pode obter este certificado para fins de testes, coitada da sua empresa. O certificado pode ser usado para assinar documentos, então ele deveria ser guardado dentro da sala do presidente, trancado dentro da gaveta dele. Você pode gerar um certificado de testes (veja esse outro post do meu blog), ou você pode obter um de graça na GlobalSign. Recomendo que você use este último para obter um certificado de teste para este artigo - a geração do certificado de testes requer alguns passos a mais do que o que está descrito aqui.

Qualquer que seja o método que você usar, após a obtenção do certificado, ele estará instalado na sua máquina. Você pode acessá-lo através do snap-in Certificates do MMC:

1.      Clique em Start | Run, digite mmc.exe e pressione Ok. Uma console vazia do MMC será aberta.

2.      Selecione a opção de menu File | Add/Remove Snap-in..., clique em Add..., e selecione Certificates. Clique em Add, deixe o default My user account, e clique em Finish. Feche todas as janelas (exceto a do MMC ;).

3.      Abra o caminho "Certificates - Current User | Personal | Certificates". Seu certificado de testes deve estar lá dentro.

Exportando o Certificado para Arquivo

Para nos aproximarmos mais de uma situação real, vamos gravar o certificado obtido em arquivo. Você pode gravar o certificado de duas formas: com a chave privada ou sem a chave privada.

§         Você pode exportar o certificado com a chave privada para, p.e., mantê-lo em uma mídia removível (memória flash, pen drive, smart card) e só fornecê-lo quando necessário. Isto aumenta bastante a segurança da aplicação.

§         Você pode exportar o certificado sem a chave privada para, p.e.,  disponibilizá-lo para download para qualquer um que deseja verificar assinaturas digitais geradas por você. Isto poderia se aplicar à nossa situação.

Ainda no snap-in Certificates, que usamos no passo anterior, faça o seguinte:

1.      Clique com o botão direito no certificado a exportar.

2.      Selecione a opção All Tasks | Export....

3.      Na tela de apresentação do Wizard de Exportação de Certificado, clique Next.

4.      Na tela Export Private Key, deixe selecionado o valor default No, do not export the private key.

5.      Na tela Export File Format, deixe selecionado o valor default DER encoded binary X.509 (.CER). Este é o único formato de arquivo de certificado reconhecido pela biblioteca WSE.

6.      Na tela File to Export, selecione o caminho e nome do arquivo. Vamos chamá-lo de CertificadoChavePublica.cer neste artigo.

7.      Na tela final, clique Finish.

Agora temos o arquivo CertificadoChavePublica.cer, que contém só a chave pública, e pode ser fornecido para qualquer pessoa que tenha que verificar a assinatura gerada.

Instalando o WSE

O WSE pode ser baixado de http://msdn.microsoft.com/webservices/building/wse/, ou da página de downloads da Microsoft, caso eles retirem este link. A versão mais atual quando da elaboração deste artigo era a 2.0 sp3, mas o exemplo que eu fiz foi produzido na versão 1.0 sp1. Como houveram muitas modificações de uma versão para outra, recomendo que só para efeito de estudo você instale a versão 1.0 sp1 para acompanhar este artigo.

Usando WSE para Gerar uma Assinatura Digital - Codificação

Tá bom, geek. Abra o VS.NET e crie uma nova aplicação Windows Form. E como infelizmente aqui no meu trabalho só tem VB.NET, e eu estou fazendo este artigo em uma ensolarada tarde de trabalho, pois hoje é véspera das minhas férias e ainda por cima o chefe não veio, vai ser VB.NET mesmo.

A nossa interface vai ser a seguinte:

Primeiro de tudo, acrescente uma referência para o WSE (Microsoft.Web.Services.dll), e já coloque os seguintes Imports:

Imports Microsoft.Web.Services.Security.X509

Imports System.Text

Imports System.Security.Cryptography

Geração da Assinatura

A título de simplicidade, vamos supor que a nossa mensagem é uma string, e vamos gerar sua assinatura. Veja que este esquema se adequa bem a qualquer situação, pois qualquer que seja a sua mensagem, você pode facilmente criar uma representação dela como string, escrevendo-a como XML, e usar o que vamos ver aqui.

O click do nosso botão Gera Assinatura é bem simples:

    Private Sub LinkLabel1_LinkClicked( _

        ByVal sender As Object, ByVal e As LinkLabelLinkClickedEventArgs) _

        Handles LinkLabel1.LinkClicked

 

        Dim assinatura As Byte() = GeraAssinatura(TextBox1.Text)

        TextBox2.Text = Convert.ToBase64String(assinatura)

 

    End Sub

A função GeraAssinatura gera um array de bytes a partir da string a assinar, e invoca a função que realmente faz a assinatura digital:

    Function GeraAssinatura(ByVal mensagem As String) As Byte()

        Dim mensagemEmBytes As Byte() = Encoding.UTF8.GetBytes(mensagem)

        Dim assinatura As Byte() = Assina(mensagemEmBytes)

        Return assinatura

    End Function

A função Assina realiza o algoritmo que citamos antes: geração do hash da mensagem a assinar (pelo método ComputeHash da classe HashAlgorithm, usando o algoritmo SHA-1), depois gera a assinatura usando o hash gerado. A classe X509Certificate pertence ao WSE, e é usada para carregar o certificado, mediante sua thumbprint (veja a próxima função para um detalhamento disto). Veja que a propriedade Key do certificado retorna um objeto da classe System.Security.Cryptography.RSA, que é a chave privada contida no certificado. Usamos então Key.ExportParameters(True) para criar um objeto RSACriptoServiceProvider, que representa a chave privada, e disponibiliza o método de geração de assinatura digital (SignHash). E a assinatura é gerada.

    ReadOnly HASH_CERTIFICADO As Byte() = _

        {&H5, &HB7, &HD9, &H34, &H6B, &HDA, &H5A, &H75, &H64, &HA2, _

         &HC4, &H68, &HC3, &HC1, &HD9, &H4A, &HDE, &HB5, &H62, &H18}

 

    Function Assina(ByVal dados As Byte()) As Byte()

        ' Carrega o certificado com a chave privada que será usada para assinar a mensagem

        Dim certificado As X509Certificate = CarregaCertificado(HASH_CERTIFICADO)

        ' Gera o hash da informação a enviar

        Dim algoritmoHash As HashAlgorithm = HashAlgorithm.Create("SHA1")

        Dim hash As Byte() = algoritmoHash.ComputeHash(dados)

        ' Carrega um objeto RSA com a chave privada presente no certificado

        Dim algoritmoAssinatura As New RSACryptoServiceProvider

        algoritmoAssinatura.ImportParameters(certificado.Key.ExportParameters(True))

        ' Gera a assinatura

        Dim assinatura As Byte() = algoritmoAssinatura.SignHash(hash, _

            CryptoConfig.MapNameToOID("SHA1"))

        Return assinatura

    End Function

Finalmente, o método de carga do certificado carrega o certificado do certificate store (o repositório de certificados), que são arquivos e/ou entradas de registry feitas para o armazenamento de certificados digitais. É verificado se o certificado foi criado para assinaturas digitais (você solicita isto quando da criação do certificado), e se ele contém uma chave privada (sem a qual não podemos gerar a assinatura digital).

    Function CarregaCertificado(ByVal hashCertificado As Byte()) As X509Certificate

        Dim repositorioCertificados As X509CertificateStore

        Try

            ' Abre o repositório de certificados do usuário corrente

            repositorioCertificados = _

                X509CertificateStore.CurrentUserStore(X509CertificateStore.MyStore)

            If Not repositorioCertificados.OpenRead() Then

                Throw New Exception("Não foi possível abrir o certificate store.")

            End If

            ' Localiza o certificado a usar na assinatura pelo seu hash

            Dim certificados As X509CertificateCollection = _

                repositorioCertificados.FindCertificateByHash(hashCertificado)

            Select Case certificados.Count

                Case 0 : Throw New Exception("Certificado não encontrado.")

                Case 1 ' Tudo ok, achou o certificado

                Case Is > 1 : Throw New Exception("Mais de um certificado foi " + _

                    "encontrado para o hash fornecido.")

                Case Else : Throw New Exception("X509CertificateCollection < 0")

            End Select

            Dim certificado As X509Certificate = certificados(0)

            ' Verifica se o certificado pode ser usado para assinaturas digitais

            Select Case True

                Case Not certificado.SupportsDigitalSignature

                    Throw New Exception("Certificado não suporta assinaturas digitais.")

                Case certificado.Key Is Nothing

                    Throw New Exception("Certificado não possui chave privada - " + _

                        "não pode ser usado para gerar uma assinatura digital.")

            End Select

            Return certificado

        Finally

            If Not repositorioCertificados Is Nothing Then repositorioCertificados.Close()

        End Try

    End Function

Veja que o certificado é carregado mediante seu thumbprint. Isto nada mais é do que um hash do certificado que é usado para que um programa possa solicitar a carga de um certificado específico do repositório de certificados. O thumbprint do certificado pode ser obtido ao se dar um duplo-clique no certificado no snap-in Certificates do MMC:

Copie e cole o valor da caixa de texto no seu fonte, e acrescente "&H" antes de cada par de dígitos. Veja o array HASH_CERTIFICADO na função Assina apresentada anteriormente.

Ok, agora você já pode testar a geração da assinatura. Rode o programa, forneça um valor na caixa de texto Mensagem, e pressione Gera Assinatura. O valor da assinatura deverá aparecer na caixa de texto Assinatura.

Verificação da Assinatura

Para verificar a assinatura, vamos supor que estamos em outra aplicação, rodando em outra máquina. Então vamos usar a chave pública gravada no arquivo de exportação que geramos antes para verificar a assinatura.

O botão Verifica Assinatura da nossa aplicação também é bem simples. Convertemos a assinatura (que está como uma string base-64 na segunda caixa de texto) para bytes e chamamos o método de verificar assinaturas, informando a assinatura, a mensagem a qual ela (supostamente) se refere, e o arquivo aonde está a chave pública que deve ser usada para a conferência da assinatura:

    Private Sub LinkLabel2_LinkClicked( _

        ByVal sender As Object, ByVal e As LinkLabelLinkClickedEventArgs) _

        Handles LinkLabel2.LinkClicked

 

        Dim assinatura As Byte() = Convert.FromBase64String(TextBox2.Text)

        If VerificaAssinatura(assinatura, TextBox1.Text, _

            "C:\Temp\CertificadoChavePublica.cer") _

        Then

            MsgBox("Assinatura confere!", MsgBoxStyle.Information)

        Else

            MsgBox("Assinatura NÃO confere.", MsgBoxStyle.Critical)

        End If

 

    End Sub

 O método VerificaAssinatura executa o algoritmo de verificação de assinaturas que vimos antes: ele calcula o hash da mensagem com o mesmo algoritmo que o criador da assinatura deve ter usado (SHA1 no nosso caso),  carrega a chave pública e solicita à classe RSACryptoServiceProvider para verificar a assinatura digital (método VerifyHash).

    Function VerificaAssinatura( _

        ByVal assinatura As Byte(), _

        ByVal mensagem As String, _

        ByVal nomeArquivoCertificado As String _

    ) As Boolean

        ' Calcula o hash da informacao recebida

        Dim mensagemEmBytes As Byte() = Encoding.UTF8.GetBytes(mensagem)

        Dim algoritmoHash As HashAlgorithm = HashAlgorithm.Create("SHA1")

        Dim hash As Byte() = algoritmoHash.ComputeHash(mensagemEmBytes)

        ' Carrega o certificado com a chave publica do cliente

        Dim certificado As X509Certificate = CarregaCertificado(nomeArquivoCertificado)

        ' Verifica a assinatura recebida

        Dim algoritmoAssinatura As New RSACryptoServiceProvider

        algoritmoAssinatura.ImportParameters(certificado.PublicKey.ExportParameters(False))

        Return algoritmoAssinatura.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"), _

            assinatura)

    End Function

 Por último, o método CarregaCertificado usado aqui não carrega o certificado pelo seu thumbprint, como vimos na assinatura, mas sim a partir de um arquivo:

    Function CarregaCertificado(ByVal nomeArquivo As String) As X509Certificate

        Dim certificado As X509Certificate = X509Certificate.CreateCertFromFile(nomeArquivo)

        Return certificado

    End Function

E pronto. Teste gerando a assinatura para uma string, e fazendo pequenas modificações na assinatura ou na string. Até mesmo a menor modificação torna a assinatura inválida, pois a função de hash produz resultados bastante diferentes mesmo com modificações pequenas na informação na qual o hash é calculado.

Pontos Finais

Alguns pontos devem ser destacados sobre o exemplo apresentado aqui.

§         Qualquer operação de criptografia exige seu preço em termos de uso de CPU. E a criptografia assimétrica é o tipo mais pesado de criptografia, no tocante a processamento. Então um teste de carga antes de a solução entrar em produção se torna mandatório.
 

§         Para uso especificamente em web services: a biblioteca WSE foi feita para trabalhar principalmente a nível do protocolo SOAP, que é o protocolo de codificação das mensagens trocadas por um web service e seu cliente. Realmente, se você usar no seu web service exatamente o que eu fiz aqui (que é o que eu estou fazendo hoje), você está executando o mesmo trabalho duas vezes, pois a informação a ser assinada tem que ser serializada em um array de bytes, depois a mesma informação tem que ser serializada como XML para envio dentro da mensagem SOAP. Eu estou razoavelmente convencido de que existe uma forma mais otimizada de fazer o que eu estou fazendo aqui, mas de novo a pressa foi inimiga da perfeição. Um lema que tristemente se repetiu durante este projeto foi "Pode não ser a melhor forma, mas funciona!". Bem, é um risco que você sempre corre quando adota pela primeira vez uma tecnologia em um projeto.

Apesar de tudo, a assinatura digital é um mecanismo extremamente interessante para qualquer tipo de interação em e-commerce, e mesmo para sistemas corporativos internos, e a sua tendência é se popularizar, com o lançamento do e-CPF e e-CNPJ criados pela Receita Federal. Mais sobre este assunto no próprio site da Receita (http://www.receita.fazenda.gov.br/). Um outro site muito bom é o da Autoridade Certificadora Raiz da ICP-Brasil (Infra-estrutura de Chaves Públicas - Brasil), que contém inclusive links sobre legislação, algo que você deve rever caso deseje proteger suas operações usando assinaturas digitais.

 

 

 

Dicas para quem está começando:
Veja os próximos eventos
que você não pode perder :

22/11/2008 SQL Launch -
Linhares - ES
Por : devASPNet


22/11/2008 SQL Launch- SQL Server 2008
Rio Paranaiba - Viçosa - MG
Por : devASPNet


22/11/2008 SQL Launch - SQL Server 2008
Volta Redonda - RJ
Por : devASPNet


22/11/2008 SQL Launch- SQL Server 2008
Franca - SP
Por : devASPNet


22/11/2008 SQL Launch - SQL Server 2008
Canoinhas - SC
Por : devASPNet


22/11/2008 SQL Launch - SQL Server 2008
Tefé - AM
Por : devASPNet


25/11/2008 SQL Launch - SQL Server 2008
Rio de Janeiro - RJ
Por : devASPNet


27/11/2008 SQL Lauch- SQL Server 2008
São Paulo - SP
Por : devASPNet


28/11/2008 SQL Launch - SQL Server 2008
São Paulo - SP
Por : devASPNet


29/11/2008 SQL Launch- SQL Server 2008
Pedro Leopoldo - MG
Por : devASPNet


29/11/2008 SQL Launch- SQL Server 2008
Petropolis - RJ
Por : devASPNet


29/11/2008 SQL Launch
Floriano - PI
Por : devASPNet


29/11/2008 SQL Launch - SQL Server 2008
Rio de Janeiro - RJ
Por : devASPNet


29/11/2008 SQL Launch - SQL Server 2008
Natal - RN
Por : devASPNet


29/11/2008 SQL Launch- SQL Server 2008
Santa Maria - RS
Por : devASPNet


29/11/2008 SQL Launch
Ituiutaba - MG
Por : devASPNet


5/12/2008 Cloud Computing e o Windows Azure
São Paulo - SP
Por : devASPNet


6/12/2008 SQL Server 2008 Community Launch
São Paulo - SP
Por : devASPNet

Leituras imperdíveis para quem está começando:

º Otimizando a performance no ASP.NET::..
º Criando objetos de paginação personalizados na grid::..
º Uma cesta de compras em ASP.NET::..
º Utilizando o Refresh de parâmetros no .NET::..
º ASP.NET FORMS Authentication::..
º Utilizando propriedades dinâmicas no .NET::..
º Corrigindo problemas de deleção em grid com paginação::..
º Cuidado com os componentes de validação::..
º Otimizando o InitializeComponent::..
º Movendo fonte de aplicações entre máquinas::..
º Agilizando a performance da IDE do VS.NET::..
º Utilizando Short Circuit no VB.NET::..


























  Parceiros:
20% de desconto para os membros do grupo na aquisição de livros e inscrição para eventos

Receba dicas de programação e programação .NET:
E-mail:
Incluir Excluir