NEW: signatures working!!!...but the pycrypto is shit, docs are garbage, examples are wrong...i'll move to a new, more standard crypto library next
This commit is contained in:
parent
780d61f544
commit
fa47d213cb
44
docs/DEV
44
docs/DEV
|
@ -1,44 +0,0 @@
|
||||||
[[[ Picseal ]]]
|
|
||||||
|
|
||||||
|
|
||||||
[[ Debug ]]
|
|
||||||
|
|
||||||
$ exiv2 -ps image.jpg
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[[ MVP Plan ]]
|
|
||||||
|
|
||||||
[ C ]
|
|
||||||
libexiv --> exif read/write
|
|
||||||
libwolfss --> crypto generation
|
|
||||||
|
|
||||||
[ Functions ]
|
|
||||||
# load image file
|
|
||||||
picseal.init(image_file)
|
|
||||||
|
|
||||||
# create pub/priv key pair
|
|
||||||
# add new public key to exif
|
|
||||||
# store priv key in memory
|
|
||||||
picseal.add_new_key(CIPHER_TYPE)
|
|
||||||
|
|
||||||
# hash the image, encrypt hash with priv-key
|
|
||||||
# hash the image & specific exif tags, encrypt hash with priv-key
|
|
||||||
# add signatures to exif
|
|
||||||
picseal.seal_image(HASH_TYPE)
|
|
||||||
|
|
||||||
# write the image with public key, and signature
|
|
||||||
picseal.write_pub(FILE_HANDLE)
|
|
||||||
|
|
||||||
|
|
||||||
# write the image with private key, and signature
|
|
||||||
# ADD PIN??
|
|
||||||
picseal.write_priv(FILE_HANDLE)
|
|
||||||
|
|
||||||
[ seal ]
|
|
||||||
sha-512,public-key
|
|
||||||
|
|
||||||
|
|
||||||
[[ ]]
|
|
||||||
libexiv2-14 (= 0.25-2.1), libc6 (>= 2.14), libgcc1 (>= 1:4.1.1), libstdc++6 (>= 5.2)
|
|
||||||
|
|
|
@ -0,0 +1,209 @@
|
||||||
|
[[[ Picseal ]]]
|
||||||
|
|
||||||
|
"crypto key sharing using your photos"
|
||||||
|
"exif data providing photo integrity, ownership, and crypto key"
|
||||||
|
|
||||||
|
|
||||||
|
[[ Formats]]
|
||||||
|
@ http://stackoverflow.com/questions/12749858/rsa-public-key-format
|
||||||
|
@ http://security.stackexchange.com/questions/57043/most-popular-rsa-key-format
|
||||||
|
|
||||||
|
DER: binary encoded format, sometimes Asn.1 BER-encoded
|
||||||
|
PEM: base64 format of the same DER-encoded file with header&footer lines
|
||||||
|
XML: xml format
|
||||||
|
|
||||||
|
-----BEGIN RSA PUBLIC KEY-----
|
||||||
|
-----END RSA PUBLIC KEY-----
|
||||||
|
|
||||||
|
---- BEGIN SSH2 PUBLIC KEY ----
|
||||||
|
---- END SSH2 PUBLIC KEY ----
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[ WolfSSL ]]
|
||||||
|
|
||||||
|
[ Compile Mac ]
|
||||||
|
@ https://www.wolfssl.com/wolfSSL/Docs-wolfssl-manual-toc.html
|
||||||
|
@ https://www.wolfssl.com/wolfSSL/Docs-wolfssl-manual-2-building-wolfssl.html
|
||||||
|
@ https://wolfssl.github.io/wolfcrypt-py/
|
||||||
|
|
||||||
|
$ brew install autoconf automake libtool
|
||||||
|
$ glibtoolize
|
||||||
|
$ git clone https://github.com/wolfssl/wolfssl.git
|
||||||
|
$ cd wolfssl/
|
||||||
|
$ ./autogen.sh
|
||||||
|
$ ./configure --help
|
||||||
|
$ ./configure --enable-sha512
|
||||||
|
$ make
|
||||||
|
|
||||||
|
|
||||||
|
"In order to prevent conflicts with Apple's own libtool we have prepended a "g"
|
||||||
|
so, you have instead: glibtool and glibtoolize.""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[ gexiv2 ]]
|
||||||
|
# gobject wrapper of the libexiv2 library (which is the engine for exiv2)
|
||||||
|
@ https://wiki.gnome.org/Projects/gexiv2
|
||||||
|
@ http://wiki.gnome.org/GObjectIntrospection
|
||||||
|
@ http://wiki.gnome.org/PyGObject/IntrospectionPorting
|
||||||
|
|
||||||
|
# API docs
|
||||||
|
@ http://lazka.github.io/pgi-docs/#GExiv2-0.10
|
||||||
|
|
||||||
|
[ XMP ]
|
||||||
|
# adding new XMP namespaces
|
||||||
|
@ http://dev.exiv2.org/boards/3/topics/1039
|
||||||
|
|
||||||
|
|
||||||
|
[ install ubuntu ]
|
||||||
|
$ sudo apt-get install libexiv2-dev libgexiv2-dev gir1.2-gexiv2-0.10
|
||||||
|
|
||||||
|
[ install mac ]
|
||||||
|
# install globally (python2)
|
||||||
|
$ brew install exiv2 gexiv2 pygobject3
|
||||||
|
|
||||||
|
# install for python3
|
||||||
|
$ brew reinstall pygobject3 --with-python3
|
||||||
|
|
||||||
|
|
||||||
|
[ build ]
|
||||||
|
$ git clone git://git.gnome.org/gexiv2
|
||||||
|
$ sudo apt-get install gobject-introspection
|
||||||
|
$ sudo apt-get install glib libgirepository1.0-dev
|
||||||
|
$ sudo apt-get install libglib2.0-dev libexiv2-dev python-gobject-dev
|
||||||
|
$
|
||||||
|
$ ./autogen.sh
|
||||||
|
$ ./configure --enable-introspection
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[ EXIF ]]
|
||||||
|
|
||||||
|
[ exiv2 ]
|
||||||
|
# BUILD
|
||||||
|
http://dev.exiv2.org/projects/exiv2/wiki/How_do_I_build_Exiv2_on_the_XYZ_platform
|
||||||
|
|
||||||
|
[ pyexiv2 ]
|
||||||
|
@ http://tilloy.net/dev/pyexiv2/
|
||||||
|
|
||||||
|
|
||||||
|
[ exiftool]
|
||||||
|
# perl program
|
||||||
|
@ http://www.sno.phy.queensu.ca/~phil/exiftool/
|
||||||
|
|
||||||
|
$ brew install exiftool
|
||||||
|
|
||||||
|
|
||||||
|
[[ exiftool]]
|
||||||
|
# perl program
|
||||||
|
# http://www.sno.phy.queensu.ca/~phil/exiftool/
|
||||||
|
|
||||||
|
$ brew install exiftool
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[ Competitors ]]
|
||||||
|
|
||||||
|
[ authentication ]
|
||||||
|
https://getclef.com/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[ Debug ]]
|
||||||
|
|
||||||
|
$ exiv2 -ps image.jpg
|
||||||
|
|
||||||
|
|
||||||
|
[[ Crypto ]]
|
||||||
|
|
||||||
|
[ Public Key ]
|
||||||
|
|
||||||
|
# encrypt
|
||||||
|
@ https://pythonhosted.org/pycrypto/Crypto.Cipher.PKCS1_v1_5.PKCS115_Cipher-class.html#encrypt
|
||||||
|
|
||||||
|
|
||||||
|
[ OpenSSL ]
|
||||||
|
|
||||||
|
openssl genrsa -out ~/myTestKey.pem -passout pass:"f00bar" -des3 2048
|
||||||
|
openssl rsa -pubout -in ~/myTestKey.pem -passin pass:"f00bar" -out ~/myTestKey.pub
|
||||||
|
|
||||||
|
|
||||||
|
[ Cryptography.io ]
|
||||||
|
Fernet (Public Key)
|
||||||
|
@ https://cryptography.io/en/latest/fernet/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[ MVP Plan ]]
|
||||||
|
|
||||||
|
[ C ]
|
||||||
|
libexiv --> exif read/write
|
||||||
|
libwolfss --> crypto generation
|
||||||
|
|
||||||
|
[ Functions ]
|
||||||
|
# load image file
|
||||||
|
picseal.init(image_file)
|
||||||
|
|
||||||
|
# create pub/priv key pair
|
||||||
|
# add new public key to exif
|
||||||
|
# store priv key in memory
|
||||||
|
picseal.add_new_key(CIPHER_TYPE)
|
||||||
|
|
||||||
|
# hash the image, encrypt hash with priv-key
|
||||||
|
# hash the image & specific exif tags, encrypt hash with priv-key
|
||||||
|
# add signatures to exif
|
||||||
|
picseal.seal_image(HASH_TYPE)
|
||||||
|
|
||||||
|
# write the image with public key, and signature
|
||||||
|
picseal.write_pub(FILE_HANDLE)
|
||||||
|
|
||||||
|
|
||||||
|
# write the image with private key, and signature
|
||||||
|
# ADD PIN??
|
||||||
|
picseal.write_priv(FILE_HANDLE)
|
||||||
|
|
||||||
|
[ seal ]
|
||||||
|
sha-512,public-key
|
||||||
|
|
||||||
|
|
||||||
|
[[ Libraries ]]
|
||||||
|
libexiv2-14 (= 0.25-2.1), libc6 (>= 2.14), libgcc1 (>= 1:4.1.1), libstdc++6 (>= 5.2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[ Images ]]
|
||||||
|
|
||||||
|
[ PIL Pillow ]
|
||||||
|
# use pillow, a PIL fork
|
||||||
|
@ https://github.com/python-pillow/Pillow
|
||||||
|
@ http://pillow.readthedocs.io/en/3.0.x/handbook/tutorial.html#reading-and-writing-images
|
||||||
|
|
||||||
|
# no python 3 version :(
|
||||||
|
ver 1.1.7, for Python 2.7, Nov 15 2009
|
||||||
|
|
||||||
|
|
||||||
|
[[ JPG ]]
|
||||||
|
@ http://stackoverflow.com/questions/4550296/how-to-identify-contents-of-a-byte-is-a-jpeg?rq=1
|
||||||
|
@ https://en.wikipedia.org/wiki/Magic_number_%28programming%29
|
||||||
|
@ http://www.effbot.org/imagingbook/image.htm#tag-Image.Image.tobitmap
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[ Testing ]]
|
||||||
|
|
||||||
|
|
||||||
|
[ crypto test ]
|
||||||
|
b'-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnvdAyn5JuiRcoL8s+rAV\nMpoEUioB1NTV97EDG4z/R5pm89v86UkH0xeeB6OS2EacsPHmbIY6oY0IXKA+0EX6\nSZdVSya2vv36fy/CByfHgZsDUxpzMnRZLdYbITBwil7keCTOC4EfnYIMUDsvrx6s\nA+BSEbR1rUkIXMe7NJ2Qssj68lXKMOfhrJ9wUgPLVSTIiDytiX4Wd+yAuo9lUqUk\nxt7FwjEEBV5Nj0yKZp2sJZnqp+pL5dsLsYz9xKNQHonMkGuj+3IthenTkfuXm9a6\nx+Qm3B+6AN4qBd7Uz65tffS2e2OQCzSRVoqEaRUrQKvQcSfJv+w0lh4xoZs41CJE\nc8XmmJeaDqt/zYBQWWYJlvZfpq0oh3mKGmHRtNOnKQmMd+FRJj/5fUvG7WedcHt1\noAkUg1qKu/HBgPNTVN9PWaikM1fA1E8T1koCYN0ecP29Zo8SHwcL6g82ou+fGtae\nSrXW0bFKV1JbF+hF3nBzCw+xDPAXXpUGPTwSXYZa6Gvgfckk4qP17vfFaR9f+hiL\nmW8GUmgfupvbapcG189M+UB9nDUSj3557TJpqItdbH5m4FGNv9tcMRYSwIniVVxw\n+F5FuT7nhd8vC+simwyjlB3hteICya1c7tVo5rav/LBBzHYg9ywPJCdZKUvN3qRE\n4Txbp7DC99x/xZhGck2Cpj8CAwEAAQ==\n-----END PUBLIC KEY-----'
|
||||||
|
privkey==
|
||||||
|
b'-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY-----'
|
||||||
|
text: attack at dawn
|
||||||
|
crypt: b'A!\x81\t\xac\x87n4qw\x84\xcb\xf1\xdc\x1b\xc0\xdcjQ\xecB:A\xae\x14\xcc\xa9IpV\xa6\xc3\x10\xa2G\xc6\xae\xbbb} \xcf\x12\xfd\x92h\xb9\xd1\xc7\x80\xd9Q\xc1\xd8\x9b\x0c\x04\x14@C\xaa6\x0e\xdc\x95\xbf\xd0\x99\x0fV;i\x14\xbb\x86\xe1\xa2\xbfV]\xa4\x97t\xc7L\xc9sh\xd5\xbc6\x03\xea\xe7\x07a\x01\x08\x0e\\\x90|\xacT\xc2\xfb\xb8\xf7\xa9\xc7\x0c\x8a\xd9\xdbD\x8c\x98aWS\xdf.h\xb6\xb2H\x13\xdac\xd9\x7fM\x85\x8e\xa3\x00_\xeb\x15;\xd9J6\xc0\x99\xef\xf7\xf1D\xdb\xe8\x05\xdf\x16\xf9\x07\x13Gtv\xd9^\xcfr>\xd8w\xc6\xf0\xb8\xff\x1b\xf9rt%#\xc0\x83!\xb85\xb3X\xfd\x1a~\xd51D\x0c~3\xeb\x9fRc*\xb4\xa0\x84v?vI\xe00\xdd\x16\xc1u\x9e\xad`-P\xf8/N<83o\x8d\xb0Q\x82\xd5Z\x13\x8e\xee\xfa\xc0\x89.%\xeb\xdd\xc8.P\x03\x87\xe4C7e\xe9\xd1\x13\n\x83\xe9\x89\x0f^\xfb\xc8$\x95\x7f\xe3\x80G\xf9\x96_l\x03\x92\x01\x9e\xd1\x13\x9e\x8b\xdc-C\x02/^\xb5Nl\xcc\x7f\xb6\xb8v\x95\x998\x0c\x18?@\xaf\xaa\x1e\xea;gt\x83d(G\xefO\x1a\rq9>\xc4\xa5\x01-\xcd?q\x94\xf9\xa0\xa0\xe6}\x9aJjp\xa0\x05\xaf\xda\xf2\xc9\xd8\xf0\x1b\xbe\x0b\x80\xdc\x9c\xed\xabu\xc6\x0eT\x11\xbd8\x12\x10@\x9c\xf8\x97E\xea;\xcb\xf3\xaf\xf9\xc7\xad@\xf3#G\xc9&yE=\xa3nZ\xc7(9\xf15e\xae\xe4\xbdXmw\x98\xf5B\x885$w\x9b\x82\x89\xfa\xf6\xe9\xc9\xea\x95[22\xf4\xc9\xb9\xf9\xfb\xe2\xb4\xe8\xe7\xb2J\xc59\xac\x9e\xa9e\x13\xb4\x1c\xea\x18\xacy+\xb3\x01@$\xef\x15Ao\xb7Y\xf5]0I(\xd1\xd8E\x01^\xba\xa4W\x96D\xe5i\xf4e\x08c\xd37\x15\x1fb\xe5\xca\x9eAN^\xc0\xc8\x82\xa9\xb5N\xd2~\xc6d\xf7\xcbq\x02\x90\x1a#I\xf4\xf8\xe7i\xba\xcdQ\xeb\x87Agn\x8f'
|
||||||
|
text: b'attack at dawn'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,21 +2,73 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
import logging
|
import logging
|
||||||
|
from Crypto.Signature import PKCS1_v1_5
|
||||||
from Crypto.PublicKey import RSA
|
from Crypto.PublicKey import RSA
|
||||||
|
from Crypto.Hash import SHA512
|
||||||
|
|
||||||
class PubKey:
|
class Signature:
|
||||||
|
|
||||||
keyData = None
|
signature = None
|
||||||
|
key_data = None
|
||||||
|
pub_key = None
|
||||||
|
priv_key = None
|
||||||
|
|
||||||
|
#
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
logging.info("Generating public keys...")
|
self.genKeys()
|
||||||
self.keyData = RSA.generate(4096)
|
|
||||||
|
|
||||||
|
|
||||||
def genNewKey(self):
|
#
|
||||||
|
def genSig(self, bin_data):
|
||||||
|
hshh = SHA512.new()
|
||||||
|
hshh.update(bin_data)
|
||||||
|
signer = PKCS1_v1_5.new(self.priv_key)
|
||||||
|
self.signature = signer.sign(hshh)
|
||||||
|
return self.signature
|
||||||
|
|
||||||
|
#
|
||||||
|
def verifySig(self, bin_data, bin_sig):
|
||||||
|
hshh = SHA512.new()
|
||||||
|
hshh.update(bin_data)
|
||||||
|
verifier = PKCS1_v1_5.new(self.pub_key)
|
||||||
|
return verifier.verify(hshh, bin_sig)
|
||||||
|
|
||||||
|
#
|
||||||
|
def genKeys(self):
|
||||||
logging.info("Generating public keys...")
|
logging.info("Generating public keys...")
|
||||||
self.keyData = RSA.generate(4096)
|
self.key_data = RSA.generate(4096)
|
||||||
|
self.pub_key = RSA.importKey( self.key_data.publickey().exportKey('DER'))
|
||||||
|
self.priv_key = RSA.importKey( self.key_data.exportKey('DER'))
|
||||||
|
logging.debug(self.pub_key.exportKey('PEM'))
|
||||||
|
logging.debug(self.priv_key.exportKey('PEM'))
|
||||||
|
|
||||||
#
|
#
|
||||||
def getKeyPEM(self):
|
def getKeyPEM(self):
|
||||||
return self.keyData.exportKey('PEM')
|
return self.key_data.exportKey('PEM')
|
||||||
|
|
||||||
|
#
|
||||||
|
def hashBin(self, bin_data):
|
||||||
|
hshh = SHA512.new()
|
||||||
|
hshh.update(bin_data)
|
||||||
|
img_hash = hshh.digest()
|
||||||
|
return img_hash
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# TESTING
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
def _test():
|
||||||
|
msg = b'Hieee, this is a test =)'
|
||||||
|
|
||||||
|
sig = Signature()
|
||||||
|
sig_data = sig.genSig(msg)
|
||||||
|
print("Signature created")
|
||||||
|
print("sig_data=={}".format(sig_data))
|
||||||
|
|
||||||
|
isVerified = sig.verifySig(msg, sig_data)
|
||||||
|
print("isVerified=={}".format(str(isVerified)))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
_test()
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
|
class JpgTools:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
#
|
||||||
|
def process(self, fname):
|
||||||
|
Image.open(fname)
|
||||||
|
# image as a sequence object containing pixel values
|
||||||
|
bin_data = list( im.getdata() )
|
||||||
|
# returns a string containing pixel data, using the standard "raw" encoder
|
||||||
|
im.tostring()
|
||||||
|
|
||||||
|
#
|
||||||
|
def getJpgBin(self, fname):
|
||||||
|
img_h = Image.open(fname)
|
||||||
|
img_bin = list(img_h.getdata())
|
||||||
|
return img_bin
|
24
picseal.py
24
picseal.py
|
@ -6,18 +6,30 @@ import argparse
|
||||||
import logging
|
import logging
|
||||||
from shutil import copyfile
|
from shutil import copyfile
|
||||||
#from subprocess import Popen, PIPE, check_call
|
#from subprocess import Popen, PIPE, check_call
|
||||||
from libs.crypto_pub import PubKey
|
from libs.crypto_pub import Signature
|
||||||
from libs.img_exif import ImgExif
|
from libs.img_exif import ImgExif
|
||||||
from libs.toolbox import Toolbox
|
from libs.toolbox import Toolbox
|
||||||
|
from libs.jpg_tools import JpgTools
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parseArgs()
|
parseArgs()
|
||||||
|
|
||||||
|
|
||||||
|
# hash the image binary data only (not metadata)
|
||||||
|
# create new pub keys, sign hash
|
||||||
|
# export signature & public key to a new image file
|
||||||
def processImage(image_fn):
|
def processImage(image_fn):
|
||||||
|
|
||||||
|
(pub_fn, priv_fn) = copyImage(image_fn)
|
||||||
|
getHash
|
||||||
|
addSignature(new_fn)
|
||||||
|
|
||||||
|
# add a digital signature to the metadata
|
||||||
|
def addSignature(image_fn):
|
||||||
img = ImgExif()
|
img = ImgExif()
|
||||||
img.useImg(image_fn)
|
img.useImg(image_fn)
|
||||||
key = PubKey()
|
key = Signature()
|
||||||
img.appendKey(key)
|
img.appendKey(key)
|
||||||
img.saveFile()
|
img.saveFile()
|
||||||
|
|
||||||
|
@ -25,9 +37,10 @@ def processImage(image_fn):
|
||||||
def copyImage(image_fn):
|
def copyImage(image_fn):
|
||||||
basename = os.path.basename(image_fn)
|
basename = os.path.basename(image_fn)
|
||||||
(filename, ext) = Toolbox.parseFilenameIncExt(basename)
|
(filename, ext) = Toolbox.parseFilenameIncExt(basename)
|
||||||
newFileName = filename + '_' + Toolbox.getTimestampStr() + ext
|
pubFileName = filename + '_' + Toolbox.getTimestampStr() + ext
|
||||||
|
privFileName = filename + '_' + Toolbox.getTimestampStr() + ext
|
||||||
copyfile(image_fn, newFileName)
|
copyfile(image_fn, newFileName)
|
||||||
return newFileName
|
return (pubFileName, privFileName)
|
||||||
|
|
||||||
|
|
||||||
def parseArgs():
|
def parseArgs():
|
||||||
|
@ -52,8 +65,7 @@ def parseArgs():
|
||||||
logging.basicConfig(level=logging.CRITICAL)
|
logging.basicConfig(level=logging.CRITICAL)
|
||||||
|
|
||||||
if (args.image):
|
if (args.image):
|
||||||
newImg = copyImage(args.image)
|
processImage(args.image)
|
||||||
processImage(newImg)
|
|
||||||
else:
|
else:
|
||||||
print('Create PicSeal images')
|
print('Create PicSeal images')
|
||||||
print(' picseal.py -i <image_file>')
|
print(' picseal.py -i <image_file>')
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
import logging
|
||||||
|
from Crypto.PublicKey import RSA
|
||||||
|
from Crypto.Cipher import PKCS1_v1_5
|
||||||
|
|
||||||
|
print ("Generating keys...")
|
||||||
|
|
||||||
|
msg = 'attack at dawn'
|
||||||
|
key = RSA.generate(4096) # I know this is a huge overkill
|
||||||
|
pubkey = RSA.importKey(key.publickey().exportKey('DER'))
|
||||||
|
privkey = RSA.importKey(key.exportKey('DER'))
|
||||||
|
|
||||||
|
cipher = PKCS1_v1_5.new(pubkey)
|
||||||
|
ciphertext = cipher.encrypt(msg.encode())
|
||||||
|
|
||||||
|
print("text: {}".format(msg))
|
||||||
|
print("crypt: {}".format(ciphertext))
|
||||||
|
|
||||||
|
# decrypt(self, ct, sentinel)
|
||||||
|
# ct== cypher text, b'text as bytes'
|
||||||
|
# sentinel== object to be return on error
|
||||||
|
# https://pythonhosted.org/pycrypto/Crypto.Cipher.PKCS1_v1_5.PKCS115_Cipher-class.html#encrypt
|
||||||
|
dcipher = PKCS1_v1_5.new(privkey)
|
||||||
|
secret = dcipher.decrypt(ciphertext, 'ERROR: decrypting')
|
||||||
|
print("text: {}".format(secret))
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# exportKey() documentation says, "construct a new key carrying only the public info"
|
||||||
|
# testing that a new key isn't created, key should be the same
|
||||||
|
#
|
||||||
|
print("\n\n")
|
||||||
|
print("*** *** *** ***")
|
||||||
|
print("*** Key Gen Test ***")
|
||||||
|
print("*** *** *** ***")
|
||||||
|
|
||||||
|
print("*** NEW PUB KEY:")
|
||||||
|
print("{}\n".format(key.publickey().exportKey('PEM')))
|
||||||
|
|
||||||
|
print("*** NEW PUB KEY:")
|
||||||
|
print("{}\n".format(key.publickey().exportKey('PEM')))
|
||||||
|
|
||||||
|
print("*** PRIV KEY:")
|
||||||
|
print("{}\n".format(key.exportKey('PEM')))
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
#
|
||||||
|
#
|
||||||
|
from Crypto.PublicKey import RSA
|
||||||
|
|
||||||
|
def decrypt():
|
||||||
|
externKey="/home/borrajax/myTestKey.pub"
|
||||||
|
publickey = open(externKey, "r")
|
||||||
|
decryptor = RSA.importKey(publickey, passphrase="f00bar")
|
||||||
|
retval=None
|
||||||
|
|
||||||
|
file = open("/tmp/cryptThingy.txt", "rb")
|
||||||
|
retval = decryptor.decrypt(file.read())
|
||||||
|
file.close()
|
||||||
|
return retval
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
decryptedThingy=decrypt()
|
||||||
|
print "Decrypted: %s" % decryptedThingy
|
|
@ -0,0 +1,17 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
#
|
||||||
|
#
|
||||||
|
from Crypto.PublicKey import RSA
|
||||||
|
|
||||||
|
def encrypt(message):
|
||||||
|
externKey="/home/borrajax/myTestKey.pem"
|
||||||
|
privatekey = open(externKey, "r")
|
||||||
|
encryptor = RSA.importKey(privatekey, passphrase="f00bar")
|
||||||
|
encriptedData=encryptor.encrypt(message, 0)
|
||||||
|
file = open("/tmp/cryptThingy.txt", "wb")
|
||||||
|
file.write(encriptedData[0])
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
encryptedThingy=encrypt("Loren ipsum")
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
b'-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnvdAyn5JuiRcoL8s+rAV\nMpoEUioB1NTV97EDG4z/R5pm89v86UkH0xeeB6OS2EacsPHmbIY6oY0IXKA+0EX6\nSZdVSya2vv36fy/CByfHgZsDUxpzMnRZLdYbITBwil7keCTOC4EfnYIMUDsvrx6s\nA+BSEbR1rUkIXMe7NJ2Qssj68lXKMOfhrJ9wUgPLVSTIiDytiX4Wd+yAuo9lUqUk\nxt7FwjEEBV5Nj0yKZp2sJZnqp+pL5dsLsYz9xKNQHonMkGuj+3IthenTkfuXm9a6\nx+Qm3B+6AN4qBd7Uz65tffS2e2OQCzSRVoqEaRUrQKvQcSfJv+w0lh4xoZs41CJE\nc8XmmJeaDqt/zYBQWWYJlvZfpq0oh3mKGmHRtNOnKQmMd+FRJj/5fUvG7WedcHt1\noAkUg1qKu/HBgPNTVN9PWaikM1fA1E8T1koCYN0ecP29Zo8SHwcL6g82ou+fGtae\nSrXW0bFKV1JbF+hF3nBzCw+xDPAXXpUGPTwSXYZa6Gvgfckk4qP17vfFaR9f+hiL\nmW8GUmgfupvbapcG189M+UB9nDUSj3557TJpqItdbH5m4FGNv9tcMRYSwIniVVxw\n+F5FuT7nhd8vC+simwyjlB3hteICya1c7tVo5rav/LBBzHYg9ywPJCdZKUvN3qRE\n4Txbp7DC99x/xZhGck2Cpj8CAwEAAQ==\n-----END PUBLIC KEY-----'
|
||||||
|
privkey==
|
||||||
|
b'-----BEGIN RSA PRIVATE KEY-----\nMIIJKAIBAAKCAgEAnvdAyn5JuiRcoL8s+rAVMpoEUioB1NTV97EDG4z/R5pm89v8\n6UkH0xeeB6OS2EacsPHmbIY6oY0IXKA+0EX6SZdVSya2vv36fy/CByfHgZsDUxpz\nMnRZLdYbITBwil7keCTOC4EfnYIMUDsvrx6sA+BSEbR1rUkIXMe7NJ2Qssj68lXK\nMOfhrJ9wUgPLVSTIiDytiX4Wd+yAuo9lUqUkxt7FwjEEBV5Nj0yKZp2sJZnqp+pL\n5dsLsYz9xKNQHonMkGuj+3IthenTkfuXm9a6x+Qm3B+6AN4qBd7Uz65tffS2e2OQ\nCzSRVoqEaRUrQKvQcSfJv+w0lh4xoZs41CJEc8XmmJeaDqt/zYBQWWYJlvZfpq0o\nh3mKGmHRtNOnKQmMd+FRJj/5fUvG7WedcHt1oAkUg1qKu/HBgPNTVN9PWaikM1fA\n1E8T1koCYN0ecP29Zo8SHwcL6g82ou+fGtaeSrXW0bFKV1JbF+hF3nBzCw+xDPAX\nXpUGPTwSXYZa6Gvgfckk4qP17vfFaR9f+hiLmW8GUmgfupvbapcG189M+UB9nDUS\nj3557TJpqItdbH5m4FGNv9tcMRYSwIniVVxw+F5FuT7nhd8vC+simwyjlB3hteIC\nya1c7tVo5rav/LBBzHYg9ywPJCdZKUvN3qRE4Txbp7DC99x/xZhGck2Cpj8CAwEA\nAQKCAgBqvY+t6JrM+LmR3ozvT+kL70tTeI1+QePiy+NQTp7jj5PtzxvF8ZnlbohY\njMd/nfp8/hFBcehQrgidWaST6UkkvQ8yxS4UlSns2T6p21YletcCqFIN4P44vvm8\nkXAgGZPD8MLCCtQVyUtHXFaqeif6+ldhOBGEZ/PLiPn1XI/a3QVUT7LSoAFzDiQ3\njgCsjWRxxnyoRBgGMrJFkx/wHJ/TQab8vDj8+dOOk1CjkuAS54Ufdz27fBggApIr\nxZV4zAKmPwD/SC21K8s6zPuCUu9cZaCKUmttRcBl7LhtM6yl1PnrZHFGdOfaemxq\nuyIt7LCsKpFX491zp5af80B3gQMAwsAPM+/hlFA4xdQhzx+7E3kFuJ5ufiUFpAT0\nn6c0VvEG6k5jKGSEdf3ooZvAPySuKIy2FYcBsXjB/YfwFOCy09xxe3vyEG4u0OWH\nsM0TX/Z75l9IvY0uM9aWeTBeLlz3ixkRndMJDlgLiO8o3J2Ehjzr0KrYOi2ziSco\nDReQwd+sjBGgjEm+ssfuVqo9LpuhXp6dhSv+2qJ3HPLO5HYpzZBA/YLP+oO3Z4S3\nY5USy4wC/zhWgFfzK0z7pJYESckDss7e3dC9E4FQPdyuTqzDUUZaaJL8s3yV8hWw\ns3Xfv5JL2ATwaZxgpuKm6HdLLd8cebGYGGo2ULUUDL7u4SWgoQKCAQEAvWpCD55i\nJ1nZXMKJyDyB3/PS2J6+thF2vvI4Apq5ixvJnlg5DBYdDOa7x7g7ZCiFm3O8v/V1\nahRLYbQl0IUCDt8j4m7uUO9iDUewggEtOtKMQoF08pmI2z0nnTLyULeBp6rOJwoy\n8r7gP+/y2x3p7NoB3uKju+9fXyawKylV/Yl40nmqKCG23Mo50fd0SiwTNEy5zLsP\nDB/zi6oS8Aez58nTSsdc6KtVXoCE+N90VBmFKK5Kgke+QcOU4oEH2fnRqWYlWYY3\ntC81LTqRkAxWihJECThop0jADfTAckX75wgqc18ak29ZbvAv5ksuAWmlHMWL+JDx\nb+SqJyChGcmb5wKCAQEA1tjSuIdaKgPJowH2jPraOGHuUx+rKU04Ltj35bl9wd4M\nZwhYhHAJEyxi6Y2KSYvgfdSJBQL++SvVatfwxaZPna7sWE5dM1LSsZZByehoKRtB\nE2KJoyLbgHrwqPUCnNmpcXuaaiV7T+iTwLTZfhh+dcajTI0XPtX7LXnM9HABTVRd\nPPQY6Exdotk0aBVerGgQe+cxJty0vNUn9F9dULQaK+KBwh64h1XKJxNMUMO3um3Z\nTvIcTZUEAy9VEIOP5hkcPHwpErkelI83NebxQVQhlXncc26PwgUAraBqTPxNqQUS\nAVtGfiOK5XDRNxMvMUaoH9SNqKlEA25YA37xF64X6QKCAQEAsRyKaNBQNztsY7AD\n5ZeuWRpELQlCijwKLMGQXd8PX2O8QrN7pDGJOGcHbth1sFGznIe8FkIOaAJR+inY\nsgGsyvsbMr9HV6Z+qKw//0/aWwZE4GrsT2wA6/9i6zqYGaF9Oqob2aVPvmt8hEx5\naSmvcijnVuHU+AX7x50FXVZpcYj50NSyppPfyNPO/OXFdxV/X4fes/C1QUEfGZkN\n3CNXtYSibWm9FlIeoR7LN2q5+2lheYh/YxJydEvNC35bORa/VQaOJge6TmFV99Ss\nB2WCBdjOhVCZitIbwvD4geGuiXi5OOfUkceseG9eWpgxjGCcYyrUlrfxCg9miu+X\ns+UwQQKCAQB/d+cVymBpWxPv3cNNA6wjFZ9TvA9OEt2JlfsGVhZRxo9vNdlmwh3w\nPT52OR7Z4d6QaV/eFFf4t9QIbxQQAEtuT5E0F1Jel/4flPl1dKkP8naarLTikFTR\nFp/gbnVdYBqTFPWZkqFl2KSJCgOcN6YX9IGAcplfE4/R/FjokeeD3NDw0BZTBLPt\nYZchRcSE370f9hwIZZvqCUGKUGZJ8oEwllPMO3PZ/8FPi7iUlnpUZsYue6DlOstF\npHiAsr3WlAFXtYac8C4/j/T+ywVKcEL4r3NnHSq3v0YWvX00LeFZrYNwQJpDTo0i\n8dt/JKe0QaqQMAjYD40lx/r6H/+kwAq5AoIBAFK5wojDvzQIL+3vWkzkgE2Y7Ai1\ng0DRz0xLFVEbnETEskCDh3Vx0Qv1fVfM0YwHwVQFqLJL58qOLIqAmzknXPkxX4O/\nH7KnLUwB/w9cQTsgzsNB9t8c9pHnupKMRhc8FiWgjIG4uM2HNxzDecBizFJVx74i\nhDIPlvEkSAKZboc92aWAZRSAt7f/FQnbFkqMxWFUv1Dj9X1gyTXj93lr/Hh/ULaV\nlGt6Uxaf4OaUrAEz2yRFE/px+k69UKLmFg25G2cF35MXuX22XA25XdxpB+HKoRX2\nzNXIilN2d+bcYLnts9onxgZ/WpkazET3WvK7ZJXyvT7xj2Pe7PyWdGON8/k=\n-----END RSA PRIVATE KEY-----'
|
||||||
|
text: attack at dawn
|
||||||
|
crypt: b'A!\x81\t\xac\x87n4qw\x84\xcb\xf1\xdc\x1b\xc0\xdcjQ\xecB:A\xae\x14\xcc\xa9IpV\xa6\xc3\x10\xa2G\xc6\xae\xbbb} \xcf\x12\xfd\x92h\xb9\xd1\xc7\x80\xd9Q\xc1\xd8\x9b\x0c\x04\x14@C\xaa6\x0e\xdc\x95\xbf\xd0\x99\x0fV;i\x14\xbb\x86\xe1\xa2\xbfV]\xa4\x97t\xc7L\xc9sh\xd5\xbc6\x03\xea\xe7\x07a\x01\x08\x0e\\\x90|\xacT\xc2\xfb\xb8\xf7\xa9\xc7\x0c\x8a\xd9\xdbD\x8c\x98aWS\xdf.h\xb6\xb2H\x13\xdac\xd9\x7fM\x85\x8e\xa3\x00_\xeb\x15;\xd9J6\xc0\x99\xef\xf7\xf1D\xdb\xe8\x05\xdf\x16\xf9\x07\x13Gtv\xd9^\xcfr>\xd8w\xc6\xf0\xb8\xff\x1b\xf9rt%#\xc0\x83!\xb85\xb3X\xfd\x1a~\xd51D\x0c~3\xeb\x9fRc*\xb4\xa0\x84v?vI\xe00\xdd\x16\xc1u\x9e\xad`-P\xf8/N<83o\x8d\xb0Q\x82\xd5Z\x13\x8e\xee\xfa\xc0\x89.%\xeb\xdd\xc8.P\x03\x87\xe4C7e\xe9\xd1\x13\n\x83\xe9\x89\x0f^\xfb\xc8$\x95\x7f\xe3\x80G\xf9\x96_l\x03\x92\x01\x9e\xd1\x13\x9e\x8b\xdc-C\x02/^\xb5Nl\xcc\x7f\xb6\xb8v\x95\x998\x0c\x18?@\xaf\xaa\x1e\xea;gt\x83d(G\xefO\x1a\rq9>\xc4\xa5\x01-\xcd?q\x94\xf9\xa0\xa0\xe6}\x9aJjp\xa0\x05\xaf\xda\xf2\xc9\xd8\xf0\x1b\xbe\x0b\x80\xdc\x9c\xed\xabu\xc6\x0eT\x11\xbd8\x12\x10@\x9c\xf8\x97E\xea;\xcb\xf3\xaf\xf9\xc7\xad@\xf3#G\xc9&yE=\xa3nZ\xc7(9\xf15e\xae\xe4\xbdXmw\x98\xf5B\x885$w\x9b\x82\x89\xfa\xf6\xe9\xc9\xea\x95[22\xf4\xc9\xb9\xf9\xfb\xe2\xb4\xe8\xe7\xb2J\xc59\xac\x9e\xa9e\x13\xb4\x1c\xea\x18\xacy+\xb3\x01@$\xef\x15Ao\xb7Y\xf5]0I(\xd1\xd8E\x01^\xba\xa4W\x96D\xe5i\xf4e\x08c\xd37\x15\x1fb\xe5\xca\x9eAN^\xc0\xc8\x82\xa9\xb5N\xd2~\xc6d\xf7\xcbq\x02\x90\x1a#I\xf4\xf8\xe7i\xba\xcdQ\xeb\x87Agn\x8f'
|
||||||
|
text: b'attack at dawn'
|
|
@ -0,0 +1,12 @@
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
from ..libs.crypto_pub import Signature
|
||||||
|
|
||||||
|
msg = b'Hieee, this is a test =)'
|
||||||
|
|
||||||
|
sig = Signature()
|
||||||
|
sig_data = sig.genSig(msg)
|
||||||
|
print("sig_data=={}".format(sig_data))
|
||||||
|
isVerified = sig.verifySig(msg, sig_data)
|
||||||
|
print("isVerified=={}".format(str(isVerified)))
|
Loading…
Reference in New Issue