Skip to content

Instantly share code, notes, and snippets.

@carlok
Forked from aellerton/0_export_public_key.py
Last active May 13, 2023 21:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save carlok/74789edcb52e98af650b61690211876c to your computer and use it in GitHub Desktop.
Save carlok/74789edcb52e98af650b61690211876c to your computer and use it in GitHub Desktop.
Python sign message with private key and verify with public key
#!/usr/bin/env python
"""Extract the public key from the private key and write to a file.
"""
from Crypto.Hash import SHA256
from Crypto.Signature import PKCS1_v1_5
from Crypto.PublicKey import RSA
with open("private_key.pem", "r") as src:
private_key = RSA.importKey(src.read())
public_key = private_key.publickey()
with open('public_key.txt', 'w') as out:
out.write(public_key.exportKey().decode('utf-8'))
#!/usr/bin/env python
#from base64 import (b64encode, b64decode)
from Crypto.Hash import SHA256
from Crypto.Signature import PKCS1_v1_5
from Crypto.PublicKey import RSA
#message = "I want this stream signed"
message = input("message? ")
digest = SHA256.new()
digest.update(message.encode('utf-8'))
# Load private key previouly generated
with open ("private_key.pem", "r") as myfile:
private_key = RSA.importKey(myfile.read())
# Sign the message
signer = PKCS1_v1_5.new(private_key)
sig = signer.sign(digest)
# sig is bytes object, so convert to hex string.
# (could convert using b64encode or any number of ways)
print("Signature:")
print(sig.hex())
#!/usr/bin/env python
import sys
from Crypto.Hash import SHA256
from Crypto.Signature import PKCS1_v1_5
from Crypto.PublicKey import RSA
# message = "I want this stream signed"
message = input('Message? ')
digest = SHA256.new()
digest.update(message.encode('utf-8'))
#sig = 'bedc06f6b6cb0edc5c426ec7bb4aad32fbba4efe239e71804047bc0eca3081475641563250092528521879df93ca22474926ecc4baeec98aaf90dffe465ef384917ecf41fbbc332033561f40f13d130d540f9d95114c3b12f05b90351580860453876d4fa30dd6f94a96a92f9684015ccd806c7a053ebf07861091a35d057201'
sig = input('Signature? ')
sig = bytes.fromhex(sig) # convert string to bytes object
# Load public key (not private key) and verify signature
public_key = RSA.importKey(open("public_key.txt").read())
verifier = PKCS1_v1_5.new(public_key)
verified = verifier.verify(digest, sig)
if verified:
print('Successfully verified message')
else:
print('FAILED')

Demonstrate simple private key signature and public key verify

Sequence

You'll need Python 3 and to pip install -r requirements.txt.

Then, set up private and public keys with:

$ bash generate_key.sh 
Generating RSA private key, 1024 bit long modulus
...++++++
..++++++
e is 65537 (0x10001)

$ python 0_export_public_key.py 
(done)

$ cat public_key.txt 
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDU4d3jauQxxI1TmID8q4ejPlMb
1bqYC3GHqnVyJI+TUi84kasfpu3wUbmEhLXwdlSx+w56X6IP2YRhBaYJ7GnI/D2S
dpYh61khiKNaggkrh7d2Z2I1lrtyw0I1209ruKRevKIkvpNKaAVhCYJnBYPOdgJK
2Hg/BGFYnKljSW5GDwIDAetc
-----END PUBLIC KEY-----

Next, create a signature for an arbitrary input message:

$ python 1_sign.py 
message? Hello there
Signature:
6970bbd7c1a1a140fa...............................

Then validate the signature matches for the given input, using only the public key:

$ python 2_verify.py 
Message? Hello there
Signature? 6970bbd7c1a1a140fa24bd65a658ca.........................
Successfully verified message

Validate that a different message with same signature fails:

$ python 2_verify.py 
Message? Foobar
Signature? 6970bbd7c1a1a140fa24bd65a658ca.........................
FAILED
pycryptodome==3.14.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment