我正在尝试在Android中签名消息,然后将消息,签名和公钥发送到Django服务器进行验证。我正在服务器上使用pycryptodome进行验证,但验证始终失败-问题是我不知道自己做错了什么。
这是我在Android上所做的:
生成RSA公钥
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
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
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),我收到消息,签名消息和公钥:
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'])
在这一点上,我有这样的东西:
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=
然后我尝试这样验证:
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())
这总是失败,我不知道为什么。一些问题:
我已经用“ ----- BEGIN RSA KEY -----”和“ ----- END RSA KEY -----”包围了公钥,对吗?没有这样做,我得到了关于RSA密钥格式无效的错误
我的私钥和签名消息中都有换行符-我应该删除这些换行符吗?我尝试过使用和不使用它们,似乎没有什么不同,但是希望您能提出任何建议
PyCharm抱怨signature.verify(digest, signature.encode())
:
预期类型为ModuleType,而是使用SHA256Hash。
文档说摘要应该是Crypto.Hash的类型,而我正在使用Crypto.Hash.SHA256Hash,那么为什么PyCharm抱怨呢?我可以忽略吗?
我正在使用pycryptodome的PKCS1_v1_5类创建签名验证器。我不知道那是什么,我只是遵循在SO上看到的代码。
我正在使用算法“ SHA256withRSA”在android上签名,并在服务器上使用带有RSA密钥的PKCS1_v1_5并传递了消息的SHA256哈希。我对所有这些标准知之甚少。听起来不错吗?
我不知道在这里去哪里,任何建议都值得赞赏!
答案 0 :(得分:1)
我知道了-我忘记了签名在Android端已编码为base64,因此需要在服务器端进行解码。所以改变这个:
signature.verify(digest, signed_message.encode())
收件人:
signature.verify(digest, base64.b64decode(signed_message))
解决了问题:)