【问题标题】:How to verify in pycrypto signature created by openssl?如何验证由 openssl 创建的 pycrypto 签名?
【发布时间】:2011-06-14 20:55:34
【问题描述】:

我在 openssl 中创建了私钥/公钥,并签署了一些数据:

openssl genrsa -out private.pem 1024
openssl rsa -in private.pem -out public.pem -outform PEM -pubout
echo 'data to sign' > data.txt
openssl dgst -md5 < data.txt > hash
openssl rsautl -sign -inkey private.pem -keyform PEM -in hash  > signature

现在在 python 中,我正在尝试验证这些数据:

pubKey = open('public.pem').read()
data = open('data.txt').read()
signature = open('signature').read()

from Crypto import PublicKey
key = PublicKey.RSA.importKey(pubKey)
pub = key.publickey()
hash = MD5.new(data).hexdigest()
# here, hash is same, as contents of 'hash' file
print pub.verify(hash, signature) # <-- here

问题是,pub.verify 期望第二个参数是具有较大数字的单元素列表。而且我不知道如何将文件signature 中的二进制数据转换为这个整数。每个关于 pycrypto 的例子都显示了 from pycrypto 生成的签名,key.sign()(1832273432...2340234L, ) 的形式生成正确的签名。但我不知道如何使用外部签名。

如果有必要,下面是附加信息,我不知道如何解释:

简要技术信息:

  • 数字签名格式:PKCS#7 “Signed-Data”
  • 公钥程序:DSS
  • 密钥长度:512 – 1024 位
  • 公开指数:2 +1
  • 公钥格式:X.509 v3 证书
  • MD(消息摘要)算法:MD5 或 RIPEMD-160 16

【问题讨论】:

    标签: python openssl python-2.x pycrypto


    【解决方案1】:

    Crypto.Signature 模块是您想要的。来自Crypto.Signature.PKCS1_v1_5 文档:

    key = RSA.importKey(open('pubkey.der').read())
    h = SHA.new(message)
    verifier = PKCS1_v1_5.new(key)
    if verifier.verify(h, signature):
       print "The signature is authentic."
    else:
       print "The signature is not authentic."
    

    【讨论】:

      【解决方案2】:

      我遇到了同样的问题,这里有两个示例,使用 openssl 和 python 生成和验证。希望这对某人有所帮助...

      重击:

      #!/bin/bash
      # Generate keys
      openssl genrsa -out priv.pem
      # Export public key
      openssl rsa -pubout -in priv.pem -out pub.pem
      # Create test file
      echo test123 > test.txt
      # Create SHA1 signature
      openssl dgst -sha1 -sign priv.pem -out test.txt.sig test.txt
      # Verify SHA1 signature
      openssl dgst -sha1 -verify pub.pem -signature test.txt.sig test.txt
      

      Python:

      #!/usr/bin/python
      from Crypto.Signature import PKCS1_v1_5
      from Crypto.PublicKey import RSA
      from Crypto.Hash import SHA
      from Crypto import Random
      # Read public key from file
      fd = open('pub.pem', 'r')
      key_data = fd.read()
      fd.close()
      # Load public key
      key = RSA.importKey(key_data)
      # Read test file
      fd = open('test.txt', 'r')
      message = fd.read()
      fd.close()
      # Create SHA1 hash object
      h = SHA.new(message)
      # Create PKCS1 handler
      cipher = PKCS1_v1_5.new(key)
      # Read signature file
      fd = open('test.txt.sig', 'r')
      signature = fd.read()
      fd.close()
      # Verify signature
      print cipher.verify(h, signature)
      # Read private key from file
      fd = open('priv.pem', 'r')
      priv_key_data = fd.read()
      fd.close()
      # Load private key
      priv_key = RSA.importKey(priv_key_data)
      # Create PKCS1 handler
      priv_cipher = PKCS1_v1_5.new(priv_key)
      # Sign hash of test file content and compare
      signature2 = priv_cipher.sign(h)
      if signature == signature2:
          print "Match!! :)"
      

      经过更多阅读后,我了解到 (https://en.wikipedia.org/wiki/PKCS_1) PKCS1_PSS 是应该用于创建签名的新方案。

      两个脚本都需要一些改动:

      重击:

      #!/bin/bash
      # Generate keys
      openssl genrsa -out priv.pem
      # Export public key
      openssl rsa -pubout -in priv.pem -out pub.pem
      # Create test file
      echo test123 > test.txt
      # Create SHA1 signature
      openssl dgst -sha1 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -sign priv.pem -out test.txt.sig test.txt
      # Verify SHA1 signature
      openssl dgst -sha1 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -verify pub.pem -signature test.txt.sig test.txt
      

      Python:

      #!/usr/bin/python
      from Crypto.Signature import PKCS1_PSS
      from Crypto.PublicKey import RSA
      from Crypto.Hash import SHA
      from Crypto import Random
      # Read public key from file
      fd = open('pub.pem', 'r')
      key_data = fd.read()
      fd.close()
      # Load public key
      key = RSA.importKey(key_data)
      # Read test file
      fd = open('test.txt', 'r')
      message = fd.read()
      fd.close()
      # Create SHA1 hash object
      h = SHA.new(message)
      # Create PKCS1 handler
      cipher = PKCS1_PSS.new(key)
      # Read signature file
      fd = open('test.txt.sig', 'r')
      signature = fd.read()
      fd.close()
      # Verify signature
      print cipher.verify(h, signature)
      # Read private key from file
      fd = open('priv.pem', 'r')
      priv_key_data = fd.read()
      fd.close()
      # Load private key
      priv_key = RSA.importKey(priv_key_data)
      # Create PKCS1 handler
      priv_cipher = PKCS1_PSS.new(priv_key)
      # Sign hash of test file content and compare
      signature2 = priv_cipher.sign(h)
      # PKCS1_PSS signatures always differ!
      #if signature == signature2:
      #    print "Match!! :)"
      

      【讨论】:

        【解决方案3】:

        这是解决方案。

        from Crypto.Util import number
        signature  = number.bytes_to_long(signature) #Convert the signature to long
        print pub.verify(hash, (signature,) ) #Pass tuple to verify
        

        【讨论】:

        • 显然这种方式不起作用 - 返回 False。我已经按照您的建议尝试过pastebin.com/uPtrwngm
        【解决方案4】:

        这篇文章给你最好的答案。 How do you verify an RSA SHA1 signature in Python?

        pycrypto 无法验证 OpenSSL 创建的签名。你可以试试 M2Crypto。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-22
          • 2021-05-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-10-06
          相关资源
          最近更新 更多