首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法用pycryptodome验证RSA签名

无法用pycryptodome验证RSA签名
EN

Stack Overflow用户
提问于 2019-05-07 15:40:53
回答 1查看 1.2K关注 0票数 0

我试图在Android中签名一条消息,然后将消息、签名和公钥发送到Django服务器进行验证。我正在使用服务器上的pycryptodome来验证,但是验证总是失败的--问题是我不知道自己做错了什么。

这就是我在Android上做的事情:

生成一个RSA公钥

代码语言:javascript
复制
val keyPairGenerator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore")

val certStart = Calendar.getInstance()
val certEnd = Calendar.getInstance()
certEnd.add(Calendar.YEAR, 30)

val spec = KeyPairGeneratorSpec.Builder(context)
     .setAlias("MyKeyAlias")
     .setKeySize(1024)
     .setSubject(X500Principal("CN=CryptoIsHard"))
     .setSerialNumber(BigInteger.ONE)
     .setStartDate(certStart.time)
     .setEndDate(certEnd.time)
     .build()

 keyPairGenerator.initialize(spec, SecureRandom.getInstance("SHA1PRNG"))
 keyPairGenerator.generateKeyPair()

使用私钥对消息签名,将签名编码为base64

代码语言:javascript
复制
val message = "some message"
val keystoreEntry = keyStore.getEntry("MyKeyAlias", null) as KeyStore.PrivateKeyEntry
val signer= Signature.getInstance("SHA256withRSA")
signer.initSign(keystoreEntry.privateKey)
signer.update(message.toByteArray(Charsets.UTF_8))
val signature = Base64.encodeToString(signature.sign(), 0)

将公钥解压缩为base64

代码语言:javascript
复制
val keystoreEntry = keyStore.getEntry(KEY_ALIAS, null) as KeyStore.PrivateKeyEntry
val publicKey = Base64.encodeToString(keystoreEntry.certificate.publicKey.encoded, 0)

将消息、签名(base64)和公钥(base64)发送到服务器

试图验证签名

然后在服务器上(使用Python 3、Django 1.11、pycryptodome 3.8.1),我接收消息、签名消息和公钥:

代码语言:javascript
复制
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256

def verify_signature(request):

    response_dict = json.loads(str(request.body, encoding='utf-8'))
    public_key = str(response_dict ['publicKey'])
    signed_message = str(response_dict ['signedMessage'])
    message = str(response_dict ['message'])

在这一点上,我有这样的事情:

代码语言:javascript
复制
print(public_key)

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkmWj9+FLqpCRl35Ac8mFqfJx390kgvhQzNXPp
8/OWqsLitbCQYtw3/sEY60Cz04A3onZNh8iwSms8iZLSZh9Y23/AhSyBXw7XVtCwXQfuZagMwPV2
OhZZGGC8IOsqUOnRswa9L2/SI1i5HQQNqcZ+Su1Po/Xr2+opKps+gHDmPwIDAQAB

print(signed_message)

mdlasq+sN2Hdi+qBTWp6EjMBGYQCCdTSuQlrPozoA3J6dwW0cTXbp7YefD2JlLp8pXkMfYmTivsN
dAKkY/dHEAfUm4YuvaBz72ogwFx8px20JQ0OKVO03FjcZuw1jAGYUrEt8eswTHfmN8yJ/lDVsUlb
UYe/VcD6O/0YWrXGPrI=

然后我试着验证如下:

代码语言:javascript
复制
formatted_public_key = "-----BEGIN RSA KEY-----\n{}-----END RSA KEY-----".format(public_key)
rsa_public_key = RSA.importKey(formatted_public_key)
signature = PKCS1_v1_5.new(rsa_public_key)
digest = SHA256.new()
digest.update(message.encode())

verified = signature.verify(digest, signed_message.encode())

这总是失败的,我不知道为什么。一些问题:

  • 我用“--开始RSA密钥--和--”--结束RSA密钥--“--”--这是对的?没有这样做,我就得到了一个关于RSA密钥格式无效的错误。
  • 我的私钥和签名的消息都有行中断-我应该删除这些吗?我试过和没有他们,这似乎没有什么区别,但会感谢任何建议
  • PyCharm抱怨signature.verify(digest, signature.encode()): 预期类型为ModuleType,改为SHA256Hash。

医生说摘要应该是来自Crypto.Hash的一种类型,我使用的是Crypto.Hash.SHA256Hash,那么为什么PyCharm会抱怨呢?我能无视吗?

  • 我正在使用pycryptodome的PKCS1_v1_5类来创建一个签名验证器。我不知道这是什么,我只是遵循我在上面看到的代码。这是正确的用途吗?
  • 我使用算法"SHA256withRSA“在android上签名,在服务器上使用PKCS1_v1_5使用RSA密钥并传递消息的SHA256哈希。我对所有这些标准都不太了解。这听起来对吗?

我不知道从哪里出发,任何建议都很感激!

EN

回答 1

Stack Overflow用户

发布于 2019-05-07 15:52:43

我想明白了--我忘了这个签名是在安卓端被编码到base64上的,所以需要在服务器端解码。因此,改变这一点:

代码语言:javascript
复制
signature.verify(digest, signed_message.encode())

至:

代码语言:javascript
复制
signature.verify(digest, base64.b64decode(signed_message))

解决问题:)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56026163

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档