def sign(xml, certContent, rsaKeyContent, signIdValue=None): """Return xmldsig XML string from xml_string of XML. Args: xml: str of bytestring xml to sign certContent: str content of certificate file rsaKeyContent: RSA key private content signIdValue: str of signature id value Returns: str: signed bytestring xml """ keyInfoXml = """<KeyInfo><X509Data/></KeyInfo>""" constSignatureXml = \ """<Signature %(signatureId)sxmlns="http://www.w3.org/2000/09/xmldsig#">%(signedInfoXml)s<SignatureValue>%(signatureValue)s</SignatureValue>%(keyInfoXml)s</Signature>""" signedInfoXml = _signedInfo(xml) signatureValue = signedWithRSA(signedInfoXml, rsaKeyContent) if signIdValue is None: signatureId = "" else: signatureId = "Id='%s' " % signIdValue signatureXml = constSignatureXml % { "signedInfoXml": signedInfoXml, "signatureValue": b64e(signatureValue), "keyInfoXml": keyInfoXml, "signatureId": signatureId, } prefix = "</p1:" foo = xml.split(prefix) after = prefix + foo[1] signedXml = foo[0] + signatureXml + after ns = {"ns": "http://www.w3.org/2000/09/xmldsig#"} signedXml = etree.fromstring(signedXml) tagX509Data = signedXml.find(".//ns:X509Data", namespaces=ns) etree.SubElement(tagX509Data, "X509Certificate").text = certContent xmlEnvelope = etree.tostring(signedXml) return xmlEnvelope
def signCancelWithRsa(cls, bufferXml, rsaKeyContent, certContent): ns = {} signInscricaoPrestador = bufferXml.find('.//InscricaoPrestador', namespaces=ns).text signNumeroNFe = bufferXml.find('.//NumeroNFe', namespaces=ns).text stringConcat = signInscricaoPrestador + signNumeroNFe.zfill(12) digest = SHA.new(stringConcat) rsaKey = RSA.importKey(rsaKeyContent) signer = PKCS1_v1_5.new(rsaKey) sign = signer.sign(digest) b64Signed = b64e(sign) cls.verifySignature(rsaKey, digest, sign) tagCancelSignatureX509Data = bufferXml.find('.//Detalhe', namespaces=ns) etree.SubElement(tagCancelSignatureX509Data, 'AssinaturaCancelamento').text = b64Signed return cls.signWithA1Cert(bufferXml, certContent=certContent, rsaKeyContent=rsaKeyContent)
def _signedInfo(xml): """Return <SignedInfo> for bytestring xml. Args: xml: str of bytestring Returns: str: xml bytestring of <SignedInfo> computed from "xml" """ signedInfoXml = \ """<SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#"%(xmlnsAttr)s><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></CanonicalizationMethod><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></SignatureMethod><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></Transform><Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></Transform></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod><DigestValue>%(digestValue)s</DigestValue></Reference></SignedInfo>""" xmlnsAttr = getXmlnsPrefixes(xml) if xmlnsAttr: xmlnsAttr = " %s" % xmlnsAttr signedInfoXml = signedInfoXml % { "digestValue": b64e(_digest(xml)), "xmlnsAttr": xmlnsAttr } return signedInfoXml
def signRpsWithRsa(cls, bufferXml, rsaKeyContent, certContent): ns = {} signInscricaoPrestador = bufferXml.find('.//InscricaoPrestador', namespaces=ns).text signSerieRPS = bufferXml.find('.//SerieRPS', namespaces=ns).text signNumeroRPS = bufferXml.find('.//NumeroRPS', namespaces=ns).text signDataEmissao = bufferXml.find('.//DataEmissao', namespaces=ns).text signStatusRPS = bufferXml.find('.//StatusRPS', namespaces=ns).text signValorServicos = bufferXml.find('.//ValorServicos', namespaces=ns).text signValorDeducoes = bufferXml.find('.//ValorDeducoes', namespaces=ns).text signCodigoServico = bufferXml.find('.//CodigoServico', namespaces=ns).text signISSRetido = bufferXml.find('.//ISSRetido', namespaces=ns).text signCPFCNPJTomador = bufferXml.find('.//CPFCNPJTomador/CNPJ', namespaces=ns).text if signISSRetido == "false": signISSRetido = "N" else: signISSRetido = "S" stringConcat = '%s%s%s%sT%s%s%015d%015d%05d%s%s' % ( str(signInscricaoPrestador).zfill(8), str(signSerieRPS.ljust(5)).upper(), str(signNumeroRPS).zfill(12), str(signDataEmissao.replace("-", "")), str(signStatusRPS), str(signISSRetido), int(float(signValorServicos) * 100), int(float(signValorDeducoes) * 100), int(signCodigoServico), str(2), str(signCPFCNPJTomador).zfill(14)) digest = SHA.new(stringConcat) rsaKey = RSA.importKey(rsaKeyContent) signer = PKCS1_v1_5.new(rsaKey) sign = signer.sign(digest) b64Signed = b64e(sign) cls.verifySignature(rsaKey, digest, sign) bufferXml.find(".//Assinatura", namespaces=ns).text = b64Signed return cls.signWithA1Cert(bufferXml, certContent=certContent, rsaKeyContent=rsaKeyContent)
def signLoteRps(cls, stringXml, certContent, rsaKeyContent): ns = {} bufferXml = etree.fromstring(stringXml) signInscricaoPrestador = bufferXml.find('.//InscricaoPrestador', namespaces=ns).text signSerieRPS = bufferXml.find('.//SerieRPS', namespaces=ns).text signNumeroRPS = bufferXml.find('.//NumeroRPS', namespaces=ns).text signDataEmissao = bufferXml.find('.//DataEmissao', namespaces=ns).text signStatusRPS = bufferXml.find('.//StatusRPS', namespaces=ns).text signTributacaoRPS = bufferXml.find('.//TributacaoRPS', namespaces=ns).text signValorServicos = bufferXml.find('.//ValorServicos', namespaces=ns).text signValorDeducoes = bufferXml.find('.//ValorDeducoes', namespaces=ns).text signCodigoServico = bufferXml.find('.//CodigoServico', namespaces=ns).text signISSRetido = bufferXml.find('.//ISSRetido', namespaces=ns).text signCPFCNPJTomador = bufferXml.find('.//CPFCNPJTomador/CNPJ', namespaces=ns).text if "false" in signISSRetido: signISSRetido = "N" else: signISSRetido = "S" signNumeroRPS = signNumeroRPS.rjust(12, "0") signDataEmissao = signDataEmissao.replace("-", "") signValorServicos = signValorServicos.replace("R$", "") signValorServicos = signValorServicos.rjust(15, "0") signValorDeducoes = signValorDeducoes.replace("R$", "") signValorDeducoes = signValorDeducoes.rjust(15, "0") signCodigoServico + signCodigoServico.rjust(5, "0") signCPFCNPJIntermediario = bufferXml.find(".//CPFCNPJIntermediario", namespaces=ns).text if signCPFCNPJIntermediario != None: signISSRetidoIntermediario = bufferXml.find(".//ISSRetidoIntermediario", namespaces=ns).text signInscricaoMunicipalIntermediario = bufferXml.find(".//InscricaoMunicipalIntermediario", namespaces=ns).text if "false" in signISSRetidoIntermediario: stringConcat = str(signInscricaoPrestador + signSerieRPS + " " + signNumeroRPS + signDataEmissao + signTributacaoRPS + signStatusRPS + signValorServicos + signValorDeducoes + "0" + signCodigoServico + signISSRetido + signCPFCNPJTomador) else: signISSRetidoIntermediario = "S" signCPFCNPJIntermediario = "2" + signCPFCNPJIntermediario stringConcat = str(signInscricaoPrestador + signSerieRPS + " " + signNumeroRPS + signDataEmissao + signTributacaoRPS + signStatusRPS + signValorServicos + signValorDeducoes + "0" + signCodigoServico + signISSRetido + signCPFCNPJTomador + signCPFCNPJIntermediario + signInscricaoMunicipalIntermediario + signISSRetidoIntermediario) message = str(stringConcat).encode("ascii") digest = SHA.new(message) RSAKey = RSA.importKey(rsaKeyContent) signer = PKCS1_v1_5.new(RSAKey) sign = signer.sign(digest) b64Signed = b64e(sign) cls.verifySignature(rsaKeyContent, digest, sign) ns = {} bufferXml = etree.fromstring(stringXml) bufferXml.find(".//Assinatura", namespaces=ns).text = b64Signed return cls.signWithA1Cert(bufferXml, certContent=certContent, rsaKeyContent=rsaKeyContent)