WIP: adding jpg image processing support
This commit is contained in:
parent
fa47d213cb
commit
d039f2a9e6
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
26
picseal.py
26
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)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
#
|
||||
# Test Signature Class
|
||||
#
|
||||
from ..libs.crypto_pub import Signature
|
||||
|
||||
|
|
Loading…
Reference in New Issue