代码之家  ›  专栏  ›  技术社区  ›  ZioByte

基于自定义CA的xml签名验证

  •  2
  • ZioByte  · 技术社区  · 8 年前

    签名定义如下:

    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">                                                                                                                   
    <SignedInfo>                                                                                                                                                             
      <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>                                                                                  
      <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>                                                                                       
      <Reference URI="">                                                                                                                                                     
        <Transforms>                                                                                                                                                         
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>                                                                                     
          <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>                                                                                           
        </Transforms>                                                                                                                                                        
        <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>                                                                                                  
        <DigestValue>htti3M3ikfm2RooDTNo3Kv7g0K2ongShUfCDUAWpytc=</DigestValue>                                                                                              
      </Reference>                                                                                                                                                           
    </SignedInfo>                                                                                                                                                            
    

    我没有办法改变答案(它是由一个国家机构颁发的),我所有的尝试,以验证证书据称用于签署的结果是错误的。

    我的一个尝试是使用以下简短的测试程序:

    #!/usr/bin/python3                                                                                                                                                       
    
    import signxml                                                                                                                                                           
    
    cf = 'certificate.cer'                                                                                                                                                          
    with open(cf, 'r') as fi:                                                                                                                                                
        cer = fi.read()                                                                                                                                                      
    
    ver = signxml.XMLVerifier()                                                                                                                                              
    
    f = 'response.xml'                                                                                                                                 
    with open(f, 'rb') as fi:                                                                                                                                            
        xml = fi.read()                                                                                                                                                  
    try:                                                                                                                                                                 
        vd = ver.verify(xml, x509_cert=cer)                                                                                                                              
        print('OK')                                                                                                                                                      
    except signxml.exceptions.InvalidSignature as e:                                                                                                                     
        print(e)                                                                                                                                                         
    

    这将导致:

    Signature verification failed: wrong signature length
    

    其他变体有不同的错误,包括:

    Signature verification failed: invalid padding
    

    unable to get local issuer certificate
    

    我是一个经验丰富的程序员,但不是密码学专家,所以我很可能忘记了一些琐碎的事情(对知识渊博的人来说)。

    :如果需要,我可以提供一个完整的例子(失败),因为证书/答案不是“秘密”。

    2 回复  |  直到 8 年前
        1
  •  2
  •   ZioByte    8 年前

    不幸的是事情总是比预期的要复杂一些。

    我已经在努力使用了 sigxml 我必须克服以下问题:

    • sigxml格式 不会(对我)用普通的 xml.etree ; 我不得不使用 lxml.etree 用不同的语法。
    • 平面安装 pip3 install sigxml 将炸弹与一个贬抑错误;我必须从github用 pip3 install git+https://github.com/XML-Security/signxml.git
    • 上的示例 sigxml格式 str 与。 bytes .
    • 用于签署证书的CA颁发机构我用于签署传出消息是 来自CA机构用来签署回复的信息(我没有办法改变这个!)。

    不过,这个故事有个圆满的结局。

    以下测试程序对我有效:

    from signxml import XMLSigner, XMLVerifier, InvalidCertificate
    from lxml import etree
    
    outCAroot = 'outCAroot.pem'
    inCAroot = 'inCAroot.pem'
    cert = open("example.pem").read().encode()
    key = open("example.key").read().encode()
    file_name = 'test.tosend'
    resp_name = 'test.rsp'
    
    xml = etree.parse(file_name)  # (data_to_sign)
    signer = XMLSigner(c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
    signed_xml = signer.sign(xml, key=key, cert=cert)
    try:
        result = XMLVerifier().verify(signed_xml, ca_pem_file=outCAroot)
    except InvalidCertificate as e:
        print(e)
    else:
        print('outgoing signature Ok.')
    
    # here I send signed_xml to remote server and get the response (NO ERRORS!)
    
    answer_xml = etree.parse(resp_name)  # (signed answer)
    try:
        result = XMLVerifier().verify(answer_xml, ca_pem_file=inCAroot)
    except InvalidCertificate as e:
        print(e)
    else:
        print('incoming signature Ok.')
        print('===================')
        print(result.signed_data.decode())
        print('===================')
    

    我希望这将有助于任何人是(或将是)在我的情况。

        2
  •  0
  •   stovfl    8 年前

    :我需要验证POST请求答案中包含的xml签名。

    像文档中的例子那样做 SignXML: XML Signature in Python :

    from signxml import XMLSigner, XMLVerifier
    from xml.etree import ElementTree
    
    cert = open("example.pem").read()
    key = open("example.key").read()
    xml = ElementTree.parse(file_name) #(data_to_sign)
    signed_xml = XMLSigner().sign(xml, key=key, cert=cert)
    result = XMLVerifier().verify(signed_xml)
    

    XMLVerifier()。验证(…)
    验证数据中提供的XML签名并返回由该签名签名的XML节点,如果签名无效,则引发异常。

    class signxml.VerifyResult

    注意 :必须阅读有关 See what is signed and Establish trust !

    相关 : Python elementtree find function reads Signature as empty (None)