Skip to content

Instantly share code, notes, and snippets.

@aellerton
Created May 23, 2018 06:14
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save aellerton/2988ff93c7d84f3dbf5b9b5a09f38ceb to your computer and use it in GitHub Desktop.
Save aellerton/2988ff93c7d84f3dbf5b9b5a09f38ceb 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
@aellerton
Copy link
Author

Above I wrote:

One script to validate the signature using only the private key.

What I meant was "one script to validate the signature using only the PUBLIC key".

That point is really important. Validation requires only the public key.

@aellerton
Copy link
Author

generate_key.sh from the other gist:

#!/usr/bin/env bash

# Generate RSA private key
openssl genrsa -out private_key.pem 1024

@zemenfes-afk
Copy link

hello dear , i need to create my own private key from quantum bits what should i do?

@carlok
Copy link

carlok commented Feb 9, 2022

pycrypto is not maintained anymore and 1_sign.py does not work at the moment with Python 3.8.2 so I switched the requirements.txt to pycryptodome==3.14.1 and it works again.
Fork available at my gist fork.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment