I've created private/public key in openssl, and signed some data:
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
now in python, I'm trying to verify this data:
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
the problem is, that pub.verify
expects second parameter to be one-element list with some large number. And I don't know how to convert binary data in file signature
to this integer. Every example about pycrypto shows signature generated from pycrypto, and key.sign()
generates correct signature in form (1832273432...2340234L, )
. But I dont know how to use external signature.
If this is necessary, below are additional informations, which I don't exactly know how to interpret:
Brief technical information:
To verify a signature, the recipient first decrypts the signature using a public key that matches with the senders private key. This produces a digest. Then the recipient calculates a digest from the received data and verifies that it matches with the one in the signature. If the digest match, the signature is valid.
We shall use the pycryptodome package in Python to generate RSA keys. After the keys are generated, we shall compute RSA digital signatures and verify signatures by a simple modular exponentiation (by encrypting and decrypting the message hash). Run the above code example: https://repl.it/@nakov/RSA-key-in-Python.
The Crypto.Signature module is what you want. From the Crypto.Signature.PKCS1_v1_5
documentation:
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."
I had the same problem and here are examples for both, generating and verifying with openssl and python. Hope this helps someone...
Bash:
#!/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!! :)"
After some more reading i've learned (https://en.wikipedia.org/wiki/PKCS_1) that PKCS1_PSS is the new scheme that should be used to create signatures.
Both scripts needs some changes:
Bash:
#!/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!! :)"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With