【问题标题】:RSA signed data verification not working PyCryptodomeRSA 签名数据验证不起作用 PyCryptodome
【发布时间】:2020-08-30 07:59:53
【问题描述】:

很抱歉这个非常具体的问题,但我真的要疯了。 我正在尝试制作一个模块,以便在我需要签名或验证签名但遇到问题时简单地导入,无论我输入签名数据还是其他任何内容,验证器都会返回 true, 这是代码:

RSA_Handler.py

from Crypto.PublicKey import RSA
from Crypto.Hash import SHA256
from Crypto.Signature import PKCS1_v1_5
import pickle

def sign(data, exported_key):
    key = RSA.importKey(exported_key)
    signed_data = []
    signed_data.append(data)
    signed_data.append(PKCS1_v1_5.new(key).sign(SHA256.new(pickle.dumps(data))))
    return signed_data


def verify(signed_data, exported_key):
    data = signed_data[0]
    signature = signed_data[1]
    key = RSA.importKey(exported_key)
    h = SHA256.new(pickle.dumps(data))
    try:
        PKCS1_v1_5.new(key).verify(h, signature)
        return True

    except(ValueError, TypeError):
        return False

test01.py

from RSA_Handler import *
import pickle
import os


with open("keys.txt", "rb") as rb:
    keys = rb.read()




signed = sign("hello", keys)
trueorfalse = verify(["this will return"," true whatever I enter"], keys)

print(trueorfalse)

【问题讨论】:

    标签: python rsa signing pycryptodome


    【解决方案1】:

    我可以重现该问题(至少对于 PyCryptodome 的最新版本,即 3.9.8)。似乎行为取决于填充类型。对于发布代码中当前使用的模块PKCS1_v1_5,验证不会在签名无效的情况下引发ValueError,而是将结果作为返回值返回。

    这意味着您的verify() 函数总是返回True,因为即使在签名不匹配的情况下,既不会引发ValueError,也不会评估返回值。

    要解决此问题,您的verify() 函数必须更改如下:

    def verify(signed_data, exported_key):
        data = signed_data[0]
        signature = signed_data[1]
        key = RSA.importKey(exported_key)
        h = SHA256.new(pickle.dumps(data))
        return PKCS1_v1_5.new(key).verify(h, signature)
    

    可以通过以下方式进行测试:

    # Signing
    key = RSA.generate(1024)
    keyPriv = key.exportKey()
    signed = sign(b'Some data', keyPriv)
    
    # Verifying
    #signed[0] = b'Some data'             # Succeeds
    signed[0] = b'Some other data'        # Fails
    keyPub = key.publickey().exportKey()
    verified = verify(signed, keyPub)
    print(verified)
    

    对于 PSS 填充,即对于模块 pss,如果签名无效,则会引发 ValueError。 IE。如果您通过替换切换到此填充

    from Crypto.Signature import PKCS1_v1_5
    

    from Crypto.Signature import pss 
    

    还有PKCS1_v1_5pss 在其余代码中,verify() 函数中的逻辑可以保持不变。

    编辑:

    正如 SquareRootOfTwentyThree 的 answer 中所解释的,PKCS1_v1_5 是一个过时的模块,而必须使用模块 pkcs1_15,根据预期,如果签名无效,它会生成一个 ValueError文档,here

    【讨论】:

    • 此答案已被接受,但并不完全正确。 OP 只是导入一个旧模块 (PKCS1_v1_5),并期望它的行为类似于一个不同的、较新的模块 (pkcs1_15)。 PyCryptodome 文档只使用后者。
    • 是的。使用pkcs1_15 模块是解决问题的正确方法。我错过了。
    【解决方案2】:

    您正在导入过时的模块PKCS1_v1_5,PyCryptodome 中实际上并未记录该模块。在您的代码中,您必须改为:

    from Crypto.Signature import import pkcs1_15
    

    PyCryptodome 文档 (https://www.pycryptodome.org/en/latest/src/signature/pkcs1_v1_5.html) 展示了验证 PKCS#1 v1.5 签名的正确方法示例。

    您使用的旧模块(即PKCS1_v1_5)纯粹是为了向后兼容 PyCrypto,它的行为方式与您观察到的相同(即没有例外 - 这不是那么好,新模块更好)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-24
      • 1970-01-01
      • 1970-01-01
      • 2022-01-01
      • 2016-01-15
      • 2012-01-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多