WIP: adding jpg image processing support

This commit is contained in:
JohnE 2016-08-30 02:30:42 -07:00
parent fa47d213cb
commit d039f2a9e6
5 changed files with 158 additions and 35 deletions

View File

@ -8,10 +8,9 @@ from Crypto.Hash import SHA512
class Signature: class Signature:
signature = None
key_data = None key_data = None
pub_key = None pub_key = None
priv_key = None sig_data = None
# #
def __init__(self): def __init__(self):
@ -21,9 +20,9 @@ class Signature:
def genSig(self, bin_data): def genSig(self, bin_data):
hshh = SHA512.new() hshh = SHA512.new()
hshh.update(bin_data) hshh.update(bin_data)
signer = PKCS1_v1_5.new(self.priv_key) signer = PKCS1_v1_5.new(self.key_data)
self.signature = signer.sign(hshh) self.sig_data = signer.sign(hshh)
return self.signature return self.sig_data
# #
def verifySig(self, bin_data, bin_sig): def verifySig(self, bin_data, bin_sig):
@ -36,15 +35,22 @@ class Signature:
def genKeys(self): def genKeys(self):
logging.info("Generating public keys...") logging.info("Generating public keys...")
self.key_data = RSA.generate(4096) self.key_data = RSA.generate(4096)
self.pub_key = RSA.importKey( self.key_data.publickey().exportKey('DER')) self.pub_key = self.key_data.publickey()
self.priv_key = RSA.importKey( self.key_data.exportKey('DER')) logging.debug("public key==\n{}".format(self.pub_key.exportKey('PEM')))
logging.debug(self.pub_key.exportKey('PEM')) logging.debug("private key (and pub, other info)==\n{}".format(self.key_data.exportKey('PEM')))
logging.debug(self.priv_key.exportKey('PEM'))
# #
def getKeyPEM(self): def getPrivKeyPEM(self):
return self.key_data.exportKey('PEM') 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): def hashBin(self, bin_data):
hshh = SHA512.new() hshh = SHA512.new()

View File

@ -2,43 +2,79 @@
# #
# #
import logging import logging
import json
import gi import gi
gi.require_version('GExiv2', '0.10') gi.require_version('GExiv2', '0.10')
from gi.repository import GExiv2 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: class ImgExif:
sig_h = None
exif_c = None
img_fn = None
# #
def __init__(self): def __init__(self, img_fn):
self.exif = None self.useImg(img_fn)
self.img_fn = None
self.img_loaded = False
# #
def useImg(self, img_fn): def useImg(self, img_fn):
result = False result = False
try: try:
self.exif = GExiv2.Metadata() self.exif_c = GExiv2.Metadata()
ret = self.exif.open_path(img_fn) ret = self.exif_c.open_path(img_fn)
if (ret): if (ret):
result = True result = True
self.img_loaded = True
except Exception as ex: except Exception as ex:
logging.error(ex) logging.error(ex)
raise raise
self.img_fn = img_fn self.img_fn = img_fn
self.sig_h = {}
# #
def appendKey(self, key): def addKey(self, key):
logging.info('Adding key to metadata...') self.sig_h['pub_key'] = key
self.exif.set_comment(str(key.getKeyPEM()))
#
def addSig(self, sig):
self.sig_h['sig'] = sig
#
def toJSON(self):
return json.dumps(self.sig_h)
# #
def extractKey(self): def extractKey(self):
pemData = self.exif.get_comment() pemData = self.exif_c.get_comment()
#
def saveFile(self): def saveFile(self):
logging.info("Saving image as {}...".format(self.img_fn)) 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()

View File

@ -3,13 +3,81 @@
# #
from PIL import Image 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: class JpgTools:
BUF_CHUNK_SIZE = 2048
data_buf = None
data_idx = None
fh = None
def __init__(self): def __init__(self):
pass 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.open(fname)
# image as a sequence object containing pixel values # image as a sequence object containing pixel values
bin_data = list( im.getdata() ) bin_data = list( im.getdata() )
@ -17,7 +85,8 @@ class JpgTools:
im.tostring() im.tostring()
# #
def getJpgBin(self, fname): def getJpgBin_OLD(self, fname):
img_h = Image.open(fname) img_h = Image.open(fname)
img_bin = list(img_h.getdata()) img_bin = list(img_h.getdata())
return img_bin return img_bin

View File

@ -20,20 +20,32 @@ def main():
# create new pub keys, sign hash # create new pub keys, sign hash
# export signature & public key to a new image file # export signature & public key to a new image file
def processImage(image_fn): 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) (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 # add a digital signature to the metadata
def addSignature(image_fn): def writePubImg(pub_fn, sig):
img = ImgExif() img = ImgExif(pub_fn)
img.useImg(image_fn) img.addKey(sig.getPubKeyPEM())
key = Signature() img.addSig(sig.sig_data)
img.appendKey(key)
img.saveFile() 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): 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)

View File

@ -1,5 +1,5 @@
# #
# # Test Signature Class
# #
from ..libs.crypto_pub import Signature from ..libs.crypto_pub import Signature