diff --git a/libs/crypto_pub.py b/libs/crypto_pub.py index d9e8cc2..0cc5d10 100644 --- a/libs/crypto_pub.py +++ b/libs/crypto_pub.py @@ -8,10 +8,9 @@ from Crypto.Hash import SHA512 class Signature: - signature = None key_data = None pub_key = None - priv_key = None + sig_data = None # def __init__(self): @@ -21,9 +20,9 @@ class Signature: 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 + signer = PKCS1_v1_5.new(self.key_data) + self.sig_data = signer.sign(hshh) + return self.sig_data # def verifySig(self, bin_data, bin_sig): @@ -35,16 +34,23 @@ class Signature: # def genKeys(self): logging.info("Generating public keys...") - 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')) + self.key_data = RSA.generate(4096) + self.pub_key = self.key_data.publickey() + logging.debug("public key==\n{}".format(self.pub_key.exportKey('PEM'))) + logging.debug("private key (and pub, other info)==\n{}".format(self.key_data.exportKey('PEM'))) # - def getKeyPEM(self): + def getPrivKeyPEM(self): return self.key_data.exportKey('PEM') + # + def getPubKeyPEM(self): + return self.pub_key.exportKey('PEM') + + # + def getSignature(self): + return sig_data + # def hashBin(self, bin_data): hshh = SHA512.new() diff --git a/libs/img_exif.py b/libs/img_exif.py index 064e72a..7addf28 100644 --- a/libs/img_exif.py +++ b/libs/img_exif.py @@ -2,43 +2,79 @@ # # import logging +import json import gi gi.require_version('GExiv2', '0.10') from gi.repository import GExiv2 +# +# { 'pub_key':b"\x8f\xab\xfe\xd1\xd5\xb4\xea\xbb\xfa", 'sig':b"\x8f\xab\xfe\xd1\xd5\xb4\xea\xbb\xfa" } +# +# class ImgExif: + sig_h = None + exif_c = None + img_fn = None + # - def __init__(self): - self.exif = None - self.img_fn = None - self.img_loaded = False + def __init__(self, img_fn): + self.useImg(img_fn) # def useImg(self, img_fn): result = False try: - self.exif = GExiv2.Metadata() - ret = self.exif.open_path(img_fn) + self.exif_c = GExiv2.Metadata() + ret = self.exif_c.open_path(img_fn) if (ret): result = True - self.img_loaded = True except Exception as ex: logging.error(ex) raise self.img_fn = img_fn + self.sig_h = {} # - def appendKey(self, key): - logging.info('Adding key to metadata...') - self.exif.set_comment(str(key.getKeyPEM())) + def addKey(self, key): + self.sig_h['pub_key'] = key + + # + def addSig(self, sig): + self.sig_h['sig'] = sig + + # + def toJSON(self): + return json.dumps(self.sig_h) # def extractKey(self): - pemData = self.exif.get_comment() - + pemData = self.exif_c.get_comment() + # def saveFile(self): logging.info("Saving image as {}...".format(self.img_fn)) - self.exif.save_file(self.img_fn) + self.exif_c.set_comment(json.dumps(self.sig_h)) + self.exif_c.save_file(self.img_fn) + # + def saveAsFile(self, fn): + #fn = self.img_fn + "_PICSEAL.jpg" + logging.info("Saving image as {}...".format(fn)) + self.exif_c.set_comment(json.dumps(self.sig_h)) + self.exif_c.save_file(fn) + +# +# TESTING +# +# +def _test(): + img = ImgExif("test/bmw_rim_640_backup.jpg") + img.addKey("-/-THIS IS A KEY-/-") + img.addSig("-/-THIS IS A SIG-/-") + print("JSON: \n{}".format(img.toJSON())) + img.saveFile() + + +if __name__ == '__main__': + _test() diff --git a/libs/jpg_tools.py b/libs/jpg_tools.py index abfbfa5..459f5f2 100644 --- a/libs/jpg_tools.py +++ b/libs/jpg_tools.py @@ -3,13 +3,81 @@ # from PIL import Image +# +# 0xFF,0xD8 - Start of Image +# 0xFF,0xEn - App Exif data +# 0xFF,0xD8 - DQT - Define Quantization Table +# 0xFF,0xDD - DRI - Define Restart Interval +# 0xFF,0xFE - Comments +# 0xFF,0xC0 - SOF0 - Start of Frame +# 0xFF,0xC2 - SOF2 - Start of Frame +# 0xFF,0xC4 - DHT - Define Huffman Tables +# 0xFF,0xDA - SOS - Start of Scan +# 0xFF,0xDn - RST - Restart (n=0..7) +# 0xFF,0xEn - Application +# 0xFF,0xD9 +# +# +# https://en.wikipedia.org/wiki/JPEG class JpgTools: + BUF_CHUNK_SIZE = 2048 + data_buf = None + data_idx = None + fh = None + def __init__(self): pass + # - def process(self, fname): + def jpgHash(self): + + + def findMarkers(self): + last_idx = len(self.data_buf) + while + + + while ord(self.data_buf[self.data_idx]) != 0xFF: + self.data_idx = self.data_idx+1 + + for idx in range(last_idx): + + + while self.data_buf: + + self.getBytes + pass + + + def processFile(self, fname): + self.data_buf = self.fh.read(self.BUF_CHUNK_SIZE) + while self.data_buf: + (ret, fin) = self.findMarkers() + + + + # + def getBytes(self, fname): + if (not self.fh): + self.fh = open(fname, "rb") + self.data_buf = self.fh.read(self.BUF_CHUNK_SIZE) + + + def processFile(self, fname): + self.fh = open(fname, "rb") + self.data_buf = self.fh.read(self.BUF_CHUNK_SIZE) + if (self.data_buf): + self.data_idx = 0 + findMarkers() + + + + + + # + def process_OLD(self, fname): Image.open(fname) # image as a sequence object containing pixel values bin_data = list( im.getdata() ) @@ -17,7 +85,8 @@ class JpgTools: im.tostring() # - def getJpgBin(self, fname): + def getJpgBin_OLD(self, fname): img_h = Image.open(fname) img_bin = list(img_h.getdata()) return img_bin + diff --git a/picseal.py b/picseal.py index 794083c..9ae7c59 100644 --- a/picseal.py +++ b/picseal.py @@ -20,20 +20,32 @@ def main(): # create new pub keys, sign hash # export signature & public key to a new image file def processImage(image_fn): - + jpg = JpgTools() + img_bin = jpg.getJpgBin(image_fn) + sig = Signature() + sig.genSig(img_bin) + (pub_fn, priv_fn) = copyImage(image_fn) - getHash - addSignature(new_fn) + + writePubImg(pub_fn, sig) + writePrivImg(priv_fn, sig) + # add a digital signature to the metadata -def addSignature(image_fn): - img = ImgExif() - img.useImg(image_fn) - key = Signature() - img.appendKey(key) +def writePubImg(pub_fn, sig): + img = ImgExif(pub_fn) + img.addKey(sig.getPubKeyPEM()) + img.addSig(sig.sig_data) img.saveFile() +# +def writePrivImg(priv_fn, sig): + img = ImgExif(priv_fn) + img.addKey(sig.getPrivKeyPEM()) + #img.addSig(sig.sig_data) + img.saveFile() +# def copyImage(image_fn): basename = os.path.basename(image_fn) (filename, ext) = Toolbox.parseFilenameIncExt(basename) diff --git a/test/signature_test.py b/test/signature_test.py index 6ee5a93..3b34ad1 100644 --- a/test/signature_test.py +++ b/test/signature_test.py @@ -1,5 +1,5 @@ # -# +# Test Signature Class # from ..libs.crypto_pub import Signature