Asssinar string com private key e sha1

329 views
Skip to first unread message

Fabiano Moraes

unread,
Mar 17, 2015, 4:50:36 PM3/17/15
to python...@googlegroups.com
Buenas Pessoal,

Seguinte, estou arrancando os cabelos aqui. Estou trabalhando em uma integração com a prefeitura de SP, para emissão de NFSe, e estou com o seguinte problema.
Tenho que assinar uma string (gerada conforme os dados da NFSe) usando o certificado digital e sha1, mas já tentei milhares de coisas e até agora nada, só recebo o erro de assinatura inválida.
Eu já uso o certificado para fazer a conexão com o web service. Extrai a private key e certificate tudo certinho, o problema mesmo é assinar a string. Se alguém puder me dar uma luz, fico muito agradecido.
Lembrando que já estou assinando o XML, essa tag assinatura é uma outra frescura de SP.

Abraço!

Juan Lopes

unread,
Mar 17, 2015, 6:32:14 PM3/17/15
to python...@googlegroups.com
Não entendo de NFE, mas só uma dica: poste o que você já fez até agora, para a galera poder ver se tem algum erro.

--
--
------------------------------------
Grupo Python-Brasil
http://www.python.org.br/wiki/AntesDePerguntar
 
<*> Para visitar o site do grupo na web, acesse:
http://groups.google.com/group/python-brasil
 
<*> Para sair deste grupo, envie um e-mail para:
python-brasi...@googlegroups.com

---
Você recebeu essa mensagem porque está inscrito no grupo "Python Brasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para python-brasi...@googlegroups.com.
Para mais opções, acesse https://groups.google.com/d/optout.

--

Diego Garcia

unread,
Mar 17, 2015, 8:06:56 PM3/17/15
to python...@googlegroups.com

Fabiano Moraes

unread,
Mar 18, 2015, 1:37:17 PM3/18/15
to python...@googlegroups.com
Então, esses projetos eu não consigo me basear, estou fazendo nota fiscal de serviço e não de produto. O meu problema também não é com a assinatura normal do XML, tag signature e tudo mais, isso já está certo, eu acho...
O problema é que por algum motivo estúpido, a prefeitura de SP exige outra tag de assinatura, que é montada a partir dos dados da nota. Essa string gerada precisa ser assinada com o mesmo certificado. Ai que está o problema.
Vou colocar o que eu tenho até agora:

Assinar o XML (Tag Signature):

from signxml import xmldsig

xmldsig(xml, digest_algorithm="sha1").sign(
            algorithm="rsa-sha1",
            key=self.key, cert=self.cert,
            c14n_algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315")


Tag Assinatura:

A string gerada é 39479676fafas00000000000320150303TNN00000000001290000000000000000000106231853773000144.
A partir dai eu faço:

import hmac
from hashlib import sha1

hmac.new(self.key, sign_string, sha1).hexdigest()


Onde self.key é minha chave privada que eu extraí do certificado .pfx.

Obrigado pela ajuda pessoal,
Abraço!



Você recebeu essa mensagem porque está inscrito em um tópico no grupo "Python Brasil" dos Grupos do Google.
Para cancelar inscrição nesse tópico, acesse https://groups.google.com/d/topic/python-brasil/0lJGjlpQs6A/unsubscribe.
Para cancelar inscrição nesse grupo e todos os seus tópicos, envie um e-mail para python-brasi...@googlegroups.com.

Fabiano Moraes

unread,
Mar 18, 2015, 1:43:59 PM3/18/15
to python...@googlegroups.com
Trecho retirado da doc oficial:

O RPS deverá ter uma assinatura digital. Esta assinatura utilizará o mesmo certificado digital usado na
assinatura da mensagem XML (item 3.2.2A), com os mesmos padrões de criptografia assimétrica RSA e
algoritmo message digest SHA-1.
Para criar a assinatura deverá ser gerado um Hash (utilizando SHA1) de uma cadeia de caracteres
(ASCII) com informações do RPS emitido. Este Hash deverá ser assinado utilizando RSA. A assinatura
do Hash será informada na TAG Assinatura (tipo RPS apresentado no item 4.2.1).
A cadeia de caracteres a ser assinada deverá conter 86 posições com as informações apresentadas na
tabela a seguir:

Com base no trecho da mensagem XML apresentada, montamos a seguinte string de caracteres:
"31000000OL0300000000000120070103TNN00000000205000000000000050000002658100013167474254209999999000106S"
Note que o valor dos serviços (R$ 20.500,00) foi transformado em 2050000, o valor de deduções (R$
5.000,00) foi transformado em 500000. Também foi acrescentado à série do RPS um espaço em branco
à direita para preencher as 5 posições.

Observação: não é necessário informar os dados de intermediário na assinatura se não houver
intermediário. Como exemplo, sem intermediário a string montada seria dessa forma:
"31000000OL03 00000000000120070103TNN00000000205000000000000050000002658100013167474254”

2º - Converta a cadeia de caracteres ASCII para bytes.
3º - Gere o HASH (array de bytes) utilizando SHA1.
4º - Assine o HASH (array de bytes) utilizando RSA-SHA1.

Fabiano Moraes

unread,
Mar 18, 2015, 2:02:26 PM3/18/15
to python...@googlegroups.com
Outra maneira que eu tentei:

from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
from base64 import b64encode, b64decode

rsakey = RSA.importKey(self.key)
signer = PKCS1_v1_5.new(rsakey)
digest = SHA.new()
digest.update(b64encode(sign_string))
sign = signer.sign(digest)

return b64encode(sign)
Reply all
Reply to author
Forward
0 new messages