Jump to content

Certificação de software


Manhoso

Recommended Posts

De acordo com os meus post nesta thread, vou começar a por ideias mais técnicas aqui.

Como disse ao undercover, a DGCI quer que enviemos o certificado gerado pelo openssl (ou pelo menos é essa a minha interpretação). Mas o busilis para quem trabalhar com .NET é que a M$ não trabalhar no mesmo formato. Continuo sem saber o porque deste desvio do standard de SSL.

Por causa disso, fiz um "parser" para a chave privada, no formato hex. Este formato obtém-se da seguinte forma, depois de gerada a chave privadaa (PEM):

openssl rsa -in privada.key -text -noout

Obviamente não postar o código, pois estou no contexto de empresa...

Protocolo de testes: Gerar a encriptação em VB e decriptar usando openssl (linux)

O que sucede é que encriptação e decriptação funciona as mil maravilhas...Mas cedo reparei que não é isso que a DGCI quer. O que eles querem é a assinatura da hash SHA1. Tudo bem, a partir do momento em que tinha uma chave válida (penso eu, uma vez que consigo encriptar e decriptar), consigo gerar a assinatura da hash sem problemas.

O problema surge em validar a assinatura no linux (openssl). As assinaturas geradas não só não são dadas como válidas, como a assinatura gerada pelo openssl é completamente diferente, para os mesmos dados (deveria ser igual).

Ideias?

Hasta,

Link to comment
Share on other sites

Poder pode... Mas era uma situacao a evitar. Por razoes de segurança e tal...

Além de que o open ssl no linux e em windows dá hashes diferentes. Nem estou a falar de hashes assinadas, as hashes dos dados dão diferentes.

Estou a estudar a tua sugestão, undercover. A da bouncy castle...Até agora ainda não está a fazer nada de jeito :S

Link to comment
Share on other sites

Eu acho que já consegui alguma coisa, apenas usando o OpenSSL  😄

gerei um par de chaves

a privada

openssl genrsa 1024 > private.key

e a pública

openssl rsa -in private.key -pubout -out public.key

depois assinei um ficheiro

openssl sha1 -sign private.key -out hash.bin Portaria_363_2010.pdf

e para verificar usei

openssl sha1 -verify public.key -signature hash.bin Portaria_363_2010.pdf

em principio deveria ser este o processo que a DGCI devia usar  🙂

no entanto o campo onde vai estar a hash tem 200 caracteres de texto e por este processo é gerado um ficheiro binário com 128 bytes, será que se tem de colocar a assinatura em base64 ?  ?

Além de que o open ssl no linux e em windows dá hashes diferentes

Vou testar, mas não devia acontecer ...

Poder pode... Mas era uma situacao a evitar. Por razoes de segurança e tal...

Penso que não haja grande problema em usar esta via, em ultimo caso posso inserir algumas medidas de segurança, mas o meu objectivo é por esta coisada a funcionar ... pois o nosso negócio não é andar a trabalhar para a DGCI  :wallbash: vou seguir o caminho do menor esforço, todo o tempo que eu perder com isto é tempo perdido em outras coisas mais úteis / lucráveis  🙂  

Link to comment
Share on other sites

Como disse ao undercover, a DGCI quer que enviemos o certificado gerado pelo openssl (ou pelo menos é essa a minha interpretação).

Eles não querem o certificado. Juntamente com a declaração de Setembro a enviar online deverá ir um ficheiro .txt exclusivamente com a chave pública em PEM.

Link to comment
Share on other sites

O problema surge em validar a assinatura no linux (openssl). As assinaturas geradas não só não são dadas como válidas, como a assinatura gerada pelo openssl é completamente diferente, para os mesmos dados (deveria ser igual).

Ideias?

Hasta,

Manhoso, tenho algumas respostas na manga, mas preciso saber como é que assinaste em VB. É que há mil razões que não estarmos a assinar o texto/ ficheiro que pretendíamos.

Há algumas semanas que estou a fazer uma bateria de teste em vários campos.

Optei finalmente por implementar tudo com linhas de comando chamados a partir do VB, funciona tudo na perfeição e já posso pedir a certificação logo que possa cruzar teste com mais alguém. No entanto, para futuro, seria bom, implementar com o próprio VB. Para isso, preciso realmente de "companhia" nos aspectos técnicos.

Link to comment
Share on other sites

Bem, depois de ler a documentação técnica da DGCI, o processo é simples em qualquer linguagem de programação.

Para isso usa-se o OpenSSL via linha de comandos, seja em Windows ou Linux, através de system calls no VB.NET/C#, no caso do PHP existe uma lib especifica para isso portanto os conceitos são os mesmos.

1º Criar chave privada encriptada (necessita password)

openssl genrsa -des3 -out private.pem 1024

2º Criar chave publica

openssl rsa -in private.pem -passin pass:minha_password -out public.pem -outform PEM –pubout 

3º Criar Hash

echo "2010-05-18;2010-05-18T11:22:19;FAC 001/14;3.12; " | openssl dgst -sha1 -sign private.pem -passin pass:minha_password | openssl enc -base64 > hash.txt

4º Verificação (Opcional) -> deve dar Verified OK

type hash.txt | openssl enc -base64 -d > hash.bin
echo "2010-05-18;2010-05-18T11:22:19;FAC 001/14;3.12; " | openssl sha1 -verify public.pem -signature hash.bin

5º Entregar o public.pem à DGCI e implementar os system calls da vossa aplicação

PS: A chave privada ser encriptada é opcional, no entanto temos de assegurar que a chave não se sabe facilmente, o algoritmo pode ser mudado para outro para além do DES

Link to comment
Share on other sites

Desculpem não ter dito nada no fim de semana, mas entretanto na sexta, consegui implementar o mecanismo como a DGCI quer. A cena de não andarmos a trabalhar para a DGCI para mim é treta...pois se não fizermos o mecanismo de cerrtificação, não temos a dita e por conseguinte vende-se menos...

A abordagem via sys calls chegou a estar em cima da mesa, mas apenas como último recurso, pois na minha opinião isso é estar a martelar. E para martelos já chegam os que são precisos para por o sw a funcionar.

Agora, passando a coisas práticas:

1º - Usando OpenSSL, gerar chave privada:

openssl genrsa -out privada.key 1024

2º - Gerar chave pública

openssl rsa -in privada.key -pubout -out publica.key

Agora, aqui temos várias hipoteses:

a) usar uma lib para traduzir de openssl para .NET(XML): Bouncy castle ou outra;

b)fazer a vossa propria lib para traduzir;

c) system calls (menos elegante);

Eu segui a via b) traduzindo a versão hexadecimal da chave privada. Primeiro obtive-a com:

openssl rsa -in privada.key -noout -text -out privada.hex

Esta abordagem tem a vantagem de não ter de me preocupar com endianess.

A partir dai é gerar a hash assinada e tá feito.

Com os testes preliminares que fiz ontem, as hashes estão válidas.

Amanha vou fazer os testes como deve ser.

Se usarem a abordagem com system calls não se esqueçam que o resultado tem de ir para a BD e não ficar num ficheiro de texto 😉

Resumindo, acho que até se consegue responder bem aos requisitos da DGCI...o texto que eles produziram é que não é dos mais claros... 😛

Hasta

Link to comment
Share on other sites

A cena de não andarmos a trabalhar para a DGCI para mim é treta...pois se não fizermos o mecanismo de cerrtificação, não temos a dita e por conseguinte vende-se menos...

Sim, mas não te vai aumentar as vendas, certo !?

A abordagem via sys calls chegou a estar em cima da mesa, mas apenas como último recurso, pois na minha opinião isso é estar a martelar. E para martelos já chegam os que são precisos para por o sw a funcionar.

Bem em relação a martelos, tens razão e não tens razão, se temos um SO e uma aplicação amplamente difundida como o OpenSSL que até a aconselhada e exemplificada pela DGCI, porque não usá-los em conjunto para chegarmos ao nosso objectivo, em vez de estarmos a reinventar a roda

Esta abordagem tem a vantagem de não ter de me preocupar com endianess.

Com base 64 tb não te precisas de preocupar daí ser amplamente usado em sistemas de rede de computadores

Se usarem a abordagem com system calls não se esqueçam que o resultado tem de ir para a BD e não ficar num ficheiro de texto

Sim isso está implícito na parte em que se tem de se "implementar os system calls da vossa aplicação"

o texto que eles produziram é que não é dos mais claros

A portaria está muito pouco clara, no entanto a FAQ e a documentação técnica está muito clara em relação a tudo, tenho pena de só ter encontrado estes dois documentos já no final da implementação.

A tua solução é muito boa no entanto não é nada útil à comunidade, pois a parte mais importante não é revelada, logo para quem queira fazer algo não vai encontrar na tua solução um caminho visível, só vai encontrar uma meia solução

Link to comment
Share on other sites

Como disse anteriormente, apenas entrei nesta discussão para dar algum contributo, por muito minimo que seja. Agora, mais que isto não posso dar, pois a implementação, pese embora ter sido eu a fazer, não me pertence, mas sim a empresa para a qual trabalho...

Peço desculpa por não poder dar mais pormenores...Espero que compreendam.

Link to comment
Share on other sites

Undercover, pelo teu método encriptando a chave privada, não há problema se os ficheiros contendo essa chave privada e respectiva pública estiverem disponíveis do lado do cliente, visto que está encriptada e não têm a nossa password? Obrigado.

Link to comment
Share on other sites

Boa tarde,

Já li e reli os vossos posts úteis, mas continuo com algumas dúvidas relacionadas com a assinatura que coloco a vossa consideração (se tiverem paciência para me responder  😁).

Utilizo VB.Net e já testei as mais variadas abordagens ao problema:

- system calls ao openssl:

Dim procAssin As New Process()
        With procAssin.StartInfo
            .UseShellExecute = False
            .RedirectStandardOutput = True
            .RedirectStandardError = True
            .StandardOutputEncoding = Encoding.GetEncoding("Windows-1252")
            .FileName = "cmd.exe"
            .WorkingDirectory = "C:\OpenSSL-Win32\bin"
            .Arguments = "/c echo " & Chr(34) & Me.txtIn.Text & Chr(34) & " | openssl dgst -sha1 -sign C:\OpenSSL-Win32\bin\fzPrivateKey.pem -r | openssl enc -base64"
        End With
        procAssin.Start()
        procAssin.WaitForExit()
        Dim strErro As String = procAssin.StandardError.ReadToEnd()
        Dim strAssinatura As String = procAssin.StandardOutput.ReadToEnd()
        Me.txtOut2.Text = "Assinatura:" & _
                         vbCrLf & strAssinatura & strErro

- um dll da Chilkat (muito baseado no exemplo http://www.example-code.com/vbdotnet/rsa_openssl_sign.asp)

- a library System.Security da 2.0 (nomeadamente o Namespace System.Security.Cryptography), utilizando a PrivateKey gerada no OpenSSl e exportada para XML:

Dim privateKey As RSACryptoServiceProvider
        Dim pkxml As String

        privateKey = New RSACryptoServiceProvider
        pkxml = ReadXMtoString("c:\fzPrivateKey.xml")
        privateKey.FromXmlString(pkxml)

        Dim buffer As Byte() = Encoding.Default.GetBytes(Me.txtIn.Text)
        Dim hash As Byte() = SHA1Managed.Create().ComputeHash(buffer)
        Dim formatter As RSAPKCS1SignatureFormatter = New RSAPKCS1SignatureFormatter(privateKey)

        formatter.SetHashAlgorithm("SHA1")

        Dim signature As Byte() = formatter.CreateSignature(hash)
        dt = New Data()
        dt.Bytes = signature

        Me.txtOut.Text = Me.txtOut.Text & _
                         vbCrLf & "Base64:" & dt.Base64 & _
                         vbCrLf & "Hex:" &  dt.Hex 

Estas duas últimas opções são as que me agradam mais porque não tenho que instalar/distribuir os componentes do OpenSSl, nem o Microsoft Visual C++ 2008 Redistributable Package. E obviamente é mais interessante a última opção porque o Chillkat RSA é pago. Contudo, nas duas últimas opções não consigo obter a mesma assinatura (assim o acho na minha ignorância) que o openssl. Já testei com a versão 1.0.0a e 0.9.8odo Openssl, já mudei configurações e nada.

Alguém tem alguma sugestão? Uma vez que as regras técnicas da portaria referem a utilização do Openssl, não queria investir mais num sistema que não devolve resultados idênticos.

Já me ocorreu que o problema esteja relacionado com a versão do PKCS#1, que no .Net 2.0 é a v1.5 e no OpenSll actual é a v2.0 (acho eu). Fará isto sentido?

Obrigado pela atenção.

Link to comment
Share on other sites

        Dim buffer As Byte() = Encoding.Default.GetBytes(Me.txtIn.Text)
        Dim hash As Byte() = SHA1Managed.Create().ComputeHash(buffer)
        Dim formatter As RSAPKCS1SignatureFormatter = New RSAPKCS1SignatureFormatter(privateKey)

        formatter.SetHashAlgorithm("SHA1")

        Dim signature As Byte() = formatter.CreateSignature(hash)

Sem ter visto muita coisa sobre o teu código, parece-me que estás a fazer a mesma operação 2 vezes, posso estar enganado é só uma sugestão sem ter feito nenhum teste, tu vais buscar o texto no Me.txtIn.Text e convertes para bytes, portanto aqui tens um problema de encodings, devias não usar o Encoding.Default mas sim o Encoding.GetEncoding("Windows-1252"), depois disto tu crias logo a Hash mas se reparares o RSAPKCS1SignatureFormatter já faz isso quando defines qual o algoritmo de Hash que queres, aqui formatter.SetHashAlgorithm("SHA1"), penso que deverias gerar a assinatura apenas assim formatter.CreateSignature(buffer) e retirar a linha  Dim hash As Byte() = SHA1Managed.Create().ComputeHash(buffer).

Link to comment
Share on other sites

Muito obrigado ao manhoso e ao undercover pelos posts, foram de grande ajuda.

Também encontrei esse problema. para testar a assinatura tive que primeiro por num ficheiro, e gerar a hash desse ficheiro

Manhoso, tens toda a razão. Não utilizando o comando echo e assinando em vez disso um txt com a string, fica igualzinho ao output do .net. O mais engraçado é que depois de andar  :wallbash: e de tomar a informação das regras técnicas como certa, hoje ao almoço saiu este aditamento no site das DGCI:

http://info.portaldasfinancas.gov.pt/NR/rdonlyres/84B18C77-577B-4581-A846-2DB0201B0FB4/0/1_Aditamento_Especificaca_regras_tecnicas.pdf

E nem contempla a tua solução. Além disso, ainda acrescentam o que também descobri esta manhã: é necessário o argumento "-A" no comando "enc" para que o output seja todo em linha (sem line-feeds).

, parece-me que estás a fazer a mesma operação 2 vezes, ... penso que deverias gerar a assinatura apenas assim formatter.CreateSignature(buffer)

Undercover, na realidade o comando "RSAPKCS1SignatureFormatter.CreateSignature" destina-se apenas a assinar um hash e não o produz. Contudo, o teu post levou-me a rever o código e a descobrir que o objecto "RSACryptoServiceProvider" (que utilizo para suportar  a privatekey) possui um método para assinar, o "SignData" (este sim calculando o hash implicitamente). Assim, o código que apresentei no meu post anterior simplifica-se para:

'referenciando o System.Security e importando o namespace System.Security.Cryptography
                 Dim privateKey As RSACryptoServiceProvider 
Dim pkxml As String
Dim dt As Data

privateKey = New RSACryptoServiceProvider
pkxml = ReadXMtoString("c:\fzPrivateKey.xml") 'aqui pode ficar embutida a string da privatekey em vez de ler dum xml
privateKey.FromXmlString(pkxml)

Dim buffer As Byte() = Encoding.GetEncoding("Windows-1252").GetBytes(Me.txtIn.Text)
Dim signature As Byte() = privateKey.SignData(buffer, "SHA1")

dt = New Data()
dt.Bytes = signature

Me.txtOut.Text = "Signature:" & _
	vbCrLf & "Base64:" & vbCrLf & dt.Base64 & _
	vbCrLf & "Hex:" & vbCrLf & dt.Hex

...tens um problema de encodings, devias não usar o Encoding.Default mas sim o Encoding.GetEncoding("Windows-1252")...

Na realidade o meu Encoding.Default não produzia problemas, mas realmente fica muito melhor com uma referência explícita ao ("Windows-1252".

Mais uma vez, obrigado  😁.

Link to comment
Share on other sites

Boas, seguindo o exemplo do mganilho, consigo gerar a hash correctamente com a private key (xml) e depois consigo validar essa hash com a public key correspondente (xml).

Agora tenho uma duvida. Por exemplo, quero encriptar a palavra XPTO; em windows, linux, e nesta abordagem em vb net, gerou-me 3 hash's diferentes.

Tenho uma versão (usando system calls no openssl) já implementada, mas precisa que a chave privada esteja disponível na pasta da aplicação, ainda que encriptada (já que sem a password ninguém consegue fazer nada dela).

Mas gostaria de ir pela última, usando a key exportada para XML. Só que a minha dúvida, é que pelo openssl, a frase XPTO dá origem a uma hash, e indo pelo vb net com a chave em xml gera-me outra hash totalmente diferente.

Depois como é para os senhores da dgci validarem? É que se lhes der uma hash gerada no VB, e eles a validarem com a chave publica em openssl, dá verification failure.

Obrigado desde já pela ajuda...

EDIT: OK esqueçam... já está tudo ok...

Link to comment
Share on other sites

Boa tarde baguera,

Podes utilizar perfeitamente o código .Net, desde que utilizes a técnica de Visual Basic Fusion explicada no artigo:

http://msdn.microsoft.com/en-us/library/ms364069(VS.80).aspx

Ou seja, crias um wrapper em VB.Net que depois podes referenciar em VB6 e utilizar normalmente.

Para tal basta:

[*]criar um projecto "Class Library" em VB.Net

[*]apagar a classe de defeito

[*]inserir uma classe nova utilizando o template "COM Class" (não disponível em VS Express que te posso enviar por email se quiseres, já nem sei se o saquei há anos do artigo acima citado)

[*]implementar o código normalmente

[*]assinar o projecto (opcional mas tenho tido muito melhores resultados assim). Simplesmente fazer My Project>Signing, marcar "Sign the assembly" e criar uma nova chave (no combo seleccionar "<New...>"). Esta assinatura não tem nada a ver com o problema da encriptação que estamos a falar, utilizo-a em todos os wrappers que faço.

[*]compilar o projecto (que origina automaticamente o registo do assembly como COM através da ferramenta regasm.exe (explicada mais à frente)

[*]em VB6, na lista das referências COM, surge uma entrada para cada COM Class registada, basta seleccioná-la (também é possivel registar manualmente o ficheiro tlb que surge ao lado do dll)

A visibilidade COM das Classes .Net é conseguida pela utilização da ferramenta regasm.exe, embutida na .Net Framework desde a versão 1.1. Esta ferramenta regista o assembly .net, emulando o COM com base nos GUID's existentes no cabeçalho da COM Classs (por isso, não copiar uma COM Class sem os alterar, o template gera-os sempre de novo).

Para registar o dll noutro pc, ou noutra localização, utilizar um bat semelhante a este:

path=%path%;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727

regasm /u "criptoWrapper.dll"
regasm /codebase /tlb "criptoWrapper.dll"

pause

Boa sorte  😄 .

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.