From f054bd2d0cc870c6360fefc632965939ac9f6ce5 Mon Sep 17 00:00:00 2001 From: JohnE Date: Sat, 24 Sep 2016 15:47:13 -0700 Subject: [PATCH 1/6] MOD: restructured folders and files --- docs/README_DSN | 33 +++++++++++++++++++++++++++++++++ docs/picseal_metadata.json | 7 +++++++ {test => ex}/GExiv2_.py | 0 {test => ex}/exif_r.py | 0 {test => ex}/exif_w.py | 0 {test => ex}/sort.py | 0 {test => img}/bmw_rim_640.jpg | Bin {test => img}/bmw_rim_full.jpg | Bin {test => img}/space.jpg | Bin {test => img}/space_test.jpg | Bin libs/jpg_bin.py | 6 +++--- libs/jpg_tools.py | 5 +++++ test/decrypt_rsa.py | 20 -------------------- test/encrypt_rsa.py | 17 ----------------- test/hieee.sdf.sdf.. | 0 test/signature_test.py | 3 ++- 16 files changed, 50 insertions(+), 41 deletions(-) create mode 100644 docs/README_DSN create mode 100644 docs/picseal_metadata.json rename {test => ex}/GExiv2_.py (100%) rename {test => ex}/exif_r.py (100%) rename {test => ex}/exif_w.py (100%) rename {test => ex}/sort.py (100%) rename {test => img}/bmw_rim_640.jpg (100%) rename {test => img}/bmw_rim_full.jpg (100%) rename {test => img}/space.jpg (100%) rename {test => img}/space_test.jpg (100%) delete mode 100644 test/decrypt_rsa.py delete mode 100644 test/encrypt_rsa.py delete mode 100644 test/hieee.sdf.sdf.. diff --git a/docs/README_DSN b/docs/README_DSN new file mode 100644 index 0000000..50a3979 --- /dev/null +++ b/docs/README_DSN @@ -0,0 +1,33 @@ + + +[[ JPG file parse Pseudo Code ]] + +1) Verify File + a. read JPG file: find record markers, save file locations + b. verify no parsing issues + c. save file locations for metatdate + d. save file locations for image data +2) Generate Hash + a. hash all image data +3) Digital Signature + a. generate new public keys + b. sign hash data with priv key +4) Write new PicSeal file + a. write encrypted original metadata + b. write PicSeal metadata + i. write JSON + b. write image data + + +[[ PicSeal Metadata ]] +JSON Format + +{ + "format_ver": "50", + "pubkey_alg": "rsa", + "pubkey_size": 4096, + "pubkey_pem": "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnvdAyn5JuiRcoL8s+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==", + "image_sig": "6acda44a9e492ddcc0e6ddadbdbd2cc20fdbb06a9264f36268b03aff921332919edb541d9bcdafa2b958276fb553682e5b67d92a127ec8d5d89b29774db86c50", + "metadata_sig": "" +} + diff --git a/docs/picseal_metadata.json b/docs/picseal_metadata.json new file mode 100644 index 0000000..2c4941f --- /dev/null +++ b/docs/picseal_metadata.json @@ -0,0 +1,7 @@ +{ + "format_ver": "50", + "pubkey_alg": "rsa", + "pubkey_size": 4096, + "pubkey_pem": "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnvdAyn5JuiRcoL8s+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==", + "image_sig": "6acda44a9e492ddcc0e6ddadbdbd2cc20fdbb06a9264f36268b03aff921332919edb541d9bcdafa2b958276fb553682e5b67d92a127ec8d5d89b29774db86c50" +} \ No newline at end of file diff --git a/test/GExiv2_.py b/ex/GExiv2_.py similarity index 100% rename from test/GExiv2_.py rename to ex/GExiv2_.py diff --git a/test/exif_r.py b/ex/exif_r.py similarity index 100% rename from test/exif_r.py rename to ex/exif_r.py diff --git a/test/exif_w.py b/ex/exif_w.py similarity index 100% rename from test/exif_w.py rename to ex/exif_w.py diff --git a/test/sort.py b/ex/sort.py similarity index 100% rename from test/sort.py rename to ex/sort.py diff --git a/test/bmw_rim_640.jpg b/img/bmw_rim_640.jpg similarity index 100% rename from test/bmw_rim_640.jpg rename to img/bmw_rim_640.jpg diff --git a/test/bmw_rim_full.jpg b/img/bmw_rim_full.jpg similarity index 100% rename from test/bmw_rim_full.jpg rename to img/bmw_rim_full.jpg diff --git a/test/space.jpg b/img/space.jpg similarity index 100% rename from test/space.jpg rename to img/space.jpg diff --git a/test/space_test.jpg b/img/space_test.jpg similarity index 100% rename from test/space_test.jpg rename to img/space_test.jpg diff --git a/libs/jpg_bin.py b/libs/jpg_bin.py index fefb658..0886b5d 100644 --- a/libs/jpg_bin.py +++ b/libs/jpg_bin.py @@ -61,7 +61,7 @@ class JpgBin: return False while(self.continue_process): - self.findAllMarker() + self.findAllMarkers() self.getMoreBytes() return True @@ -70,7 +70,7 @@ class JpgBin: # def genHash(self, file_h, hash_h): self.hh = hash_h - self.processFile(file_h) + #self.processFile(file_h) while(self.continue_process): if (self.findMarker(self.makers['SOS'])): @@ -120,7 +120,7 @@ class JpgBin: pass # - def findAllMarker(self): + def findAllMarkers(self): (word_b,) = struct.unpack('>H', self.data_buf[self.data_idx:self.data_idx+2]) hex_str = word_b.to_bytes(2, 'big').hex() # RST 0xD(n) (n==0..7) diff --git a/libs/jpg_tools.py b/libs/jpg_tools.py index b559f8c..b475ca1 100644 --- a/libs/jpg_tools.py +++ b/libs/jpg_tools.py @@ -12,9 +12,14 @@ class JpgTools: def __init__(self): pass + # + # process a jpg file, read only + # def getJpgBin(self, fname): self.processFile(fname) + # + # process a jpg file, create new jpg with crypto keys # def jpgHash(self): self.fh = open(fname, "rb") diff --git a/test/decrypt_rsa.py b/test/decrypt_rsa.py deleted file mode 100644 index 7cab933..0000000 --- a/test/decrypt_rsa.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/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 diff --git a/test/encrypt_rsa.py b/test/encrypt_rsa.py deleted file mode 100644 index 081ac37..0000000 --- a/test/encrypt_rsa.py +++ /dev/null @@ -1,17 +0,0 @@ -#!/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") - \ No newline at end of file diff --git a/test/hieee.sdf.sdf.. b/test/hieee.sdf.sdf.. deleted file mode 100644 index e69de29..0000000 diff --git a/test/signature_test.py b/test/signature_test.py index 3b34ad1..502bd47 100644 --- a/test/signature_test.py +++ b/test/signature_test.py @@ -1,7 +1,8 @@ # # Test Signature Class # -from ..libs.crypto_pub import Signature +# run from root of project +from libs.crypto_pub import Signature msg = b'Hieee, this is a test =)' From 9b9df9482e85b44207a9d7549524f74b64675346 Mon Sep 17 00:00:00 2001 From: JohnE Date: Sat, 24 Sep 2016 16:19:59 -0700 Subject: [PATCH 2/6] MOD: moving away from Exiv2, and towards my own binary code --- docs/README_DSN | 6 +++++- libs/img_exif.py | 5 ++++- picseal.py | 17 +++++++++-------- pip-req.txt | 1 - 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/docs/README_DSN b/docs/README_DSN index 50a3979..8b01621 100644 --- a/docs/README_DSN +++ b/docs/README_DSN @@ -12,11 +12,15 @@ 3) Digital Signature a. generate new public keys b. sign hash data with priv key -4) Write new PicSeal file +4) Write new PicSeal Public file a. write encrypted original metadata b. write PicSeal metadata i. write JSON b. write image data +5) Write new PicSeal Private file + a. create thumbnail (smaller files) + b. write PicSeal metadata (JSON) + c. write image data [[ PicSeal Metadata ]] diff --git a/libs/img_exif.py b/libs/img_exif.py index 7addf28..80c28e5 100644 --- a/libs/img_exif.py +++ b/libs/img_exif.py @@ -1,6 +1,9 @@ # +# DEPRECATED # -# +# ditching this for my own custom code +# uses GExiv2, and the C to Python bindings. but pain in the ass to install and config +# very limited read/wriging...cannot create a new application comment block. writing my own import logging import json import gi diff --git a/picseal.py b/picseal.py index 1fd98ae..a20699d 100644 --- a/picseal.py +++ b/picseal.py @@ -7,7 +7,6 @@ import logging from shutil import copyfile #from subprocess import Popen, PIPE, check_call from libs.crypto_pub import Signature -from libs.img_exif import ImgExif from libs.toolbox import Toolbox from libs.jpg_tools import JpgTools @@ -34,17 +33,19 @@ def processImage(image_fn): # add a digital signature to the metadata def writePubImg(pub_fn, sig): - img = ImgExif(pub_fn) - img.addKey(sig.getPubKeyPEM()) - img.addSig(sig.sig_data) - img.saveFile() + pass + # 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()) + pass + # img = ImgExif(priv_fn) + # img.addKey(sig.getPrivKeyPEM()) #img.addSig(sig.sig_data) - img.saveFile() + # img.saveFile() # def copyImage(image_fn): diff --git a/pip-req.txt b/pip-req.txt index 2bd77a7..1aa4e5f 100644 --- a/pip-req.txt +++ b/pip-req.txt @@ -1,5 +1,4 @@ Pillow==3.3.1 pycrypto==2.6.1 -pygobject==3.20.1 requests==2.11.0 shellescape==3.4.1 From ed28d01437ed9f49e39fc13ce5b1fe20efcee965 Mon Sep 17 00:00:00 2001 From: JohnE Date: Sun, 25 Sep 2016 00:01:25 -0700 Subject: [PATCH 3/6] FIN: parsing all markers, saved to fingerprint class --- libs/jpg_bin.py | 249 +++++++++++++++++++++++++++------------------- libs/jpg_fp.py | 60 +++++++++++ libs/jpg_tools.py | 12 +-- picseal.py | 4 +- 4 files changed, 212 insertions(+), 113 deletions(-) create mode 100644 libs/jpg_fp.py diff --git a/libs/jpg_bin.py b/libs/jpg_bin.py index 0886b5d..1a1c448 100644 --- a/libs/jpg_bin.py +++ b/libs/jpg_bin.py @@ -20,29 +20,34 @@ import re import struct import logging +from libs.jpg_fp import JpgFingerprint # class JpgBin: BUF_CHUNK_SIZE = 2048 - data_buf = None - data_idx = 0 - data_len = 0 - fh = None - hh = None markers = { 'SOS': 0xffd9 } - continue_process = True - - metadata_h = {} - img_bin_h = {} - - def __init__(self): - pass + self.data_buf = None + self.data_idx = 0 + self.data_len = 0 + self.fh = None + self.hh = None + + self.continue_process = True + + self.metadata_h = {} + self.img_bin_h = {} + + self.prev_fpos = 0 + self.prev_mhex = 0xdead + self.prev_mstr = "DUH!" + + self.jpg_fp = JpgFingerprint() # def __isJPG(self): @@ -67,6 +72,131 @@ class JpgBin: return True return False + # + def findAllMarkers(self): + (word_b,) = struct.unpack('>H', self.data_buf[self.data_idx:self.data_idx+2]) + hex_str = word_b.to_bytes(2, 'big').hex() + # RST 0xD(n) (n==0..7) + if (0xffd0 == word_b or 0xffd1 == word_b or 0xffd2 == word_b or 0xffd3 == word_b or 0xffd4 == word_b or 0xffd5 == word_b or 0xffd6 == word_b or 0xffd7 == word_b): + logging.info("[ {} : RST ]".format(hex_str)) + self.markerRST(word_b) + # Comments section + elif (0xfffe == word_b): + logging.info("[ {} : Comment ]".format(hex_str)) + self.markerComment(word_b) + # DQT + elif (0xffdb == word_b): + logging.info("[ {} : DQT ]".format(hex_str)) + self.markerDQT(word_b) + # DRI + elif (0xffdd == word_b): + logging.info("[ {} : DRI ]".format(hex_str)) + self.markerDRI(word_b) + # SOF0 - Start of Frame 0 + elif (0xffc0 == word_b): + logging.info("[ {} : SOF0 ]".format(hex_str)) + self.markerSOF0(word_b) + # SOF2 - Start of Frame 2 + elif (0xffc2 == word_b): + logging.info("[ {} : SOF2 ]".format(hex_str)) + self.markerSOF2(word_b) + # DHT + elif (0xffC4 == word_b): + logging.info("[ {} : DHT ]".format(hex_str)) + self.markerDHT(word_b) + # SOS + elif (0xffda == word_b): + logging.info("[ {} : SOS ]".format(hex_str)) + self.markerSOS(word_b) + # EOI + elif (0xffd9 == word_b): + logging.info("[ {} : EOI ]".format(hex_str)) + self.markerEOI(word_b) + # APP 0xE(n) - App Exif Data + # struct.pack(">H", intt).hex() + elif ( re.search(r'ffe.', hex_str ) ): + logging.info("[ {} : App Data ]".format(hex_str)) + self.markerAppData(word_b) + else: + self.data_idx += 1 + + # + # Image Metadata, Exif + # + # + def markerAppData(self, marker_hex): + fpos = self.fh.tell() + rec_len = self.calcSeekBytes() + self.jpg_fp.addImgMetadata(marker_hex, fpos, rec_len, "APP ") + + # + def markerComment(self, marker_hex): + fpos = self.fh.tell() + rec_len = self.calcSeekBytes() + self.jpg_fp.addImgMetadata(marker_hex, fpos, rec_len, "COM ") + + # + # Image Data + # + # + def markerSOS(self, marker_hex): + # rec_len = self.calcSeekBytes() + self.__addImgData(marker_hex, "SOS ") + + + # + def markerRST(self, marker_hex): + self.__addImgData(marker_hex, "RST ") + + + def markerDQT(self, marker_hex): + fpos = self.fh.tell() + rec_len = self.calcSeekBytes() + self.jpg_fp.addImgData(marker_hex, fpos, rec_len, "DQT ") + + # + def markerDRI(self, marker_hex): + fpos = self.fh.tell() + self.data_idx += 4 + self.jpg_fp.addImgData(marker_hex, fpos, 4, "DRI ") + + # + def markerSOF0(self, marker_hex): + fpos = self.fh.tell() + rec_len = self.calcSeekBytes() + self.jpg_fp.addImgData(marker_hex, fpos, rec_len, "SOF0") + + # + def markerSOF2(self, marker_hex): + fpos = self.fh.tell() + rec_len = self.calcSeekBytes() + self.jpg_fp.addImgData(marker_hex, fpos, rec_len, "SOF2") + + def markerDHT(self, marker_hex): + fpos = self.fh.tell() + rec_len = self.calcSeekBytes() + self.jpg_fp.addImgData(marker_hex, fpos, rec_len, "DHT ") + + # + def markerEOI(self, marker_hex): + fpos = self.fh.tell() + self.__addImgData(marker_hex, "EOI ") + self.jpg_fp.addImgData(marker_hex, fpos, 2, "EOI ") + + + # private helper function + def __addImgData(self, mhex, mstr): + fpos = self.fh.tell() + cur_fpos = (fpos - (self.data_len - self.data_idx)) + if (self.prev_fpos > 0): + rec_len = cur_fpos - self.prev_fpos + self.jpg_fp.addImgMetadata(self.prev_mhex, self.prev_fpos, rec_len, self.prev_mstr) + + self.prev_mhex = mhex + self.prev_mstr = mstr + self.prev_fpos = cur_fpos + self.data_idx += 2 + # def genHash(self, file_h, hash_h): self.hh = hash_h @@ -106,6 +236,7 @@ class JpgBin: self.seekBytes(rec_diff) else: self.data_idx += rec_len + return rec_len # def seekBytes(self, num_bytes): @@ -116,103 +247,11 @@ class JpgBin: # def findMarker(self, marker): - pass - # - def findAllMarkers(self): - (word_b,) = struct.unpack('>H', self.data_buf[self.data_idx:self.data_idx+2]) - hex_str = word_b.to_bytes(2, 'big').hex() - # RST 0xD(n) (n==0..7) - if (0xffd0 == word_b or 0xffd1 == word_b or 0xffd2 == word_b or 0xffd3 == word_b or 0xffd4 == word_b or 0xffd5 == word_b or 0xffd6 == word_b or 0xffd7 == word_b): - logging.info("[ {} : RST ]".format(hex_str)) - self.markerRST() - # Comments section - elif (0xfffe == word_b): - logging.info("[ {} : Comment ]".format(hex_str)) - self.markerComment() - # DQT - elif (0xffdb == word_b): - logging.info("[ {} : DQT ]".format(hex_str)) - self.markerDQT() - # DRI - elif (0xffdd == word_b): - logging.info("[ {} : DRI ]".format(hex_str)) - self.markerDRI() - # SOF0 - Start of Frame 0 - elif (0xffc0 == word_b): - logging.info("[ {} : SOF0 ]".format(hex_str)) - self.markerSOF0() - # SOF2 - Start of Frame 2 - elif (0xffc2 == word_b): - logging.info("[ {} : SOF2 ]".format(hex_str)) - self.markerSOF2() - # DHT - elif (0xffC4 == word_b): - logging.info("[ {} : DHT ]".format(hex_str)) - self.markerDHT() - # SOS - elif (0xffda == word_b): - logging.info("[ {} : SOS ]".format(hex_str)) - self.markerSOS() - # EOI - elif (0xffd9 == word_b): - logging.info("[ {} : EOI ]".format(hex_str)) - self.markerEOI() - # APP 0xE(n) - App Exif Data - # struct.pack(">H", intt).hex() - elif ( re.search(r'ffe.', hex_str ) ): - logging.info("[ {} : App Data ]".format(hex_str)) - self.markerAppData() - else: - self.data_idx += 1 - - - # - # Image Metadata, Exif - # - # - def markerAppData(self): - self.calcSeekBytes() - # - def markerComment(self): - self.calcSeekBytes() - - # - # Image Data - # - # - def markerSOS(self): - self.calcSeekBytes() - - def markerRST(self): - self.data_idx += 2 - - def markerDQT(self): - self.calcSeekBytes() - - # - def markerDRI(self): - self.data_idx += 4 - - # - def markerSOF0(self): - self.calcSeekBytes() - - # - def markerSOF2(self): - self.calcSeekBytes() - - def markerDHT(self): - self.calcSeekBytes() - - def markerEOI(self): - self.data_idx += 2 - # self.continue_process = False - def __repr__(self): - pass + return repr(self.jpg_fp) def findMarkers222(self): diff --git a/libs/jpg_fp.py b/libs/jpg_fp.py new file mode 100644 index 0000000..1884210 --- /dev/null +++ b/libs/jpg_fp.py @@ -0,0 +1,60 @@ +# +# +# +class JpgFingerprint: + + def __init__(self): + self.markers_a = [] + self.markers_img = [] + self.markers_meta = [] + self.markers_h = {} + + + def addImgMetadata(self, mhex, mpos, mlen, mstr): + marker = JpgMarker(mhex, mpos, mlen, mstr) + self.markers_a.append(marker) + self.markers_meta.append(marker) + + + def addImgData(self, mhex, mpos, mlen, mstr): + marker = JpgMarker(mhex, mpos, mlen, mstr) + self.markers_a.append(marker) + self.markers_img.append(marker) + + def printImgMarkers(self): + pass + + + def printMDMarkers(self): + pass + + # + def __repr__(self): + str = "" + total = 0 + for marker in self.markers_a: + str += repr(marker) + "\n" + total += marker.marker_size + str += "[TOT ] bytes=={}".format(total) + str += "\n" + return str + + +# +class JpgMarker: + """ + Marker Data Type + """ + def __init__(self, mhex, fpos, mlen, mstr): + self.marker_hex = mhex + self.marker_hexstr = self.marker_hex.to_bytes(2, 'big').hex() + self.marker_filepos = fpos + self.marker_size = mlen + self.marker_cat = mstr + + + def __repr__(self): + return "[{}] {} {}-len {}-fpos".format(self.marker_cat, self.marker_hexstr, self.marker_size, self.marker_filepos) + + + diff --git a/libs/jpg_tools.py b/libs/jpg_tools.py index b475ca1..fa18fbc 100644 --- a/libs/jpg_tools.py +++ b/libs/jpg_tools.py @@ -1,22 +1,22 @@ # # # +import logging from PIL import Image from libs.jpg_bin import JpgBin class JpgTools: - fh = None - def __init__(self): + self.fh = None pass # # process a jpg file, read only # def getJpgBin(self, fname): - self.processFile(fname) + return self.processFile(fname) # # process a jpg file, create new jpg with crypto keys @@ -25,15 +25,15 @@ class JpgTools: self.fh = open(fname, "rb") self.jpg = JpgBin() retval = self.jpg.processFile(self.fh) - - print("processFile()=={}".format(retval)) + logging.info("processFile()=={}".format(retval)) # def processFile(self, fname): self.fh = open(fname, "rb") self.jpg = JpgBin() retval = self.jpg.processFile(self.fh) - print("processFile()=={}".format(retval)) + logging.info("processFile()=={}".format(retval)) + return self.jpg # def process_OLD(self, fname): diff --git a/picseal.py b/picseal.py index a20699d..3ce7da4 100644 --- a/picseal.py +++ b/picseal.py @@ -20,8 +20,8 @@ def main(): # export signature & public key to a new image file def processImage(image_fn): jpg = JpgTools() - img_bin = jpg.getJpgBin(image_fn) - + jpg_bin = jpg.getJpgBin(image_fn) + print( str(jpg_bin) ) # sig = Signature() # sig.genSig(img_bin) From e0d7466730ff7139452f0054b4e5193f09c801c5 Mon Sep 17 00:00:00 2001 From: JohnE Date: Fri, 7 Oct 2016 15:39:31 -0700 Subject: [PATCH 4/6] WIP: hashing the proper parts of the jpg image --- libs/jpg_tools.py | 27 +++++---------------------- picseal.py | 9 ++++++++- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/libs/jpg_tools.py b/libs/jpg_tools.py index fa18fbc..522edbe 100644 --- a/libs/jpg_tools.py +++ b/libs/jpg_tools.py @@ -16,7 +16,11 @@ class JpgTools: # process a jpg file, read only # def getJpgBin(self, fname): - return self.processFile(fname) + self.fh = open(fname, "rb") + self.jpg = JpgBin() + retval = self.jpg.processFile(self.fh) + logging.info("processFile()=={}".format(retval)) + return self.jpg # # process a jpg file, create new jpg with crypto keys @@ -27,24 +31,3 @@ class JpgTools: retval = self.jpg.processFile(self.fh) logging.info("processFile()=={}".format(retval)) - # - def processFile(self, fname): - self.fh = open(fname, "rb") - self.jpg = JpgBin() - retval = self.jpg.processFile(self.fh) - logging.info("processFile()=={}".format(retval)) - return self.jpg - - # - def process_OLD(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_OLD(self, fname): - # img_h = Image.open(fname) - # img_h.??? - diff --git a/picseal.py b/picseal.py index 3ce7da4..8f3916a 100644 --- a/picseal.py +++ b/picseal.py @@ -10,6 +10,7 @@ from libs.crypto_pub import Signature from libs.toolbox import Toolbox from libs.jpg_tools import JpgTools +fingerprint = False def main(): parseArgs() @@ -21,7 +22,9 @@ def main(): def processImage(image_fn): jpg = JpgTools() jpg_bin = jpg.getJpgBin(image_fn) - print( str(jpg_bin) ) + + if (fingerprint): + print( str(jpg_bin) ) # sig = Signature() # sig.genSig(img_bin) @@ -66,6 +69,7 @@ def parseArgs(): parser.add_argument('-v', '--verbose', action='store_true', help="will set logging level to INFO") parser.add_argument('-vv', '--vverbose', action='store_true', help="will set logging level to DEBUG") parser.add_argument('-l', '--logging', action='store_true', help="will supercede the -v option and send all logging to a file, logging.DEBUG") + parser.add_argument('-fp', '--fingerprint', action='store_true', help="fingerprint") args = parser.parse_args() if (args.logging): @@ -78,6 +82,9 @@ def parseArgs(): else: logging.basicConfig(level=logging.CRITICAL) + if (args.fingerprint): + fingerprint = True + if (args.image): processImage(args.image) else: From 498070a48ea3efc4c0774195c6f6e80f8ac53c1b Mon Sep 17 00:00:00 2001 From: JohnE Date: Sat, 8 Oct 2016 18:27:45 -0700 Subject: [PATCH 5/6] NEW: added new marker processing, added print markers metadata CLI, added print markers image CLI --- docs/README | 17 +++++++++ libs/jpg_bin.py | 18 ++++++--- libs/jpg_fp.py | 95 ++++++++++++++++++++++++++--------------------- libs/jpg_tools.py | 2 +- picseal.py | 31 ++++++++++++++-- pip-req.txt | 4 +- 6 files changed, 112 insertions(+), 55 deletions(-) create mode 100644 docs/README diff --git a/docs/README b/docs/README new file mode 100644 index 0000000..80e30e8 --- /dev/null +++ b/docs/README @@ -0,0 +1,17 @@ +***** ***** ***** ***** +*** Picseal *** +***** ***** ***** ***** + +Your Photo is your Crypto Key +Generate a new Crypto Key to share with every photo + + +[[ Requirements ]] +Python 3 +pycrypto==2.6.1 + + + +[[ Usage ]] + + diff --git a/libs/jpg_bin.py b/libs/jpg_bin.py index 1a1c448..6d4b192 100644 --- a/libs/jpg_bin.py +++ b/libs/jpg_bin.py @@ -143,12 +143,11 @@ class JpgBin: # rec_len = self.calcSeekBytes() self.__addImgData(marker_hex, "SOS ") - # def markerRST(self, marker_hex): self.__addImgData(marker_hex, "RST ") - + # def markerDQT(self, marker_hex): fpos = self.fh.tell() rec_len = self.calcSeekBytes() @@ -190,7 +189,7 @@ class JpgBin: cur_fpos = (fpos - (self.data_len - self.data_idx)) if (self.prev_fpos > 0): rec_len = cur_fpos - self.prev_fpos - self.jpg_fp.addImgMetadata(self.prev_mhex, self.prev_fpos, rec_len, self.prev_mstr) + self.jpg_fp.addImgData(self.prev_mhex, self.prev_fpos, rec_len, self.prev_mstr) self.prev_mhex = mhex self.prev_mstr = mstr @@ -245,15 +244,24 @@ class JpgBin: self.getMoreBytes(True) return pos + # + def printMarkerImg(self): + return self.jpg_fp.printImgMarkers() + + # + def printMarkerMeta(self): + return self.jpg_fp.printMDMarkers() + # def findMarker(self, marker): pass - + # def __repr__(self): + return repr(self.jpg_fp) - + # def findMarkers222(self): last_idx = len(self.data_buf) diff --git a/libs/jpg_fp.py b/libs/jpg_fp.py index 1884210..c6c2148 100644 --- a/libs/jpg_fp.py +++ b/libs/jpg_fp.py @@ -3,58 +3,67 @@ # class JpgFingerprint: - def __init__(self): - self.markers_a = [] - self.markers_img = [] - self.markers_meta = [] - self.markers_h = {} - + def __init__(self): + self.markers_a = [] + self.markers_img = [] + self.markers_meta = [] + # self.markers_h = {} + - def addImgMetadata(self, mhex, mpos, mlen, mstr): - marker = JpgMarker(mhex, mpos, mlen, mstr) - self.markers_a.append(marker) - self.markers_meta.append(marker) - - - def addImgData(self, mhex, mpos, mlen, mstr): - marker = JpgMarker(mhex, mpos, mlen, mstr) - self.markers_a.append(marker) - self.markers_img.append(marker) - - def printImgMarkers(self): - pass - - - def printMDMarkers(self): - pass + def addImgMetadata(self, mhex, mpos, mlen, mstr): + marker = JpgMarker(mhex, mpos, mlen, mstr) + self.markers_a.append(marker) + self.markers_meta.append(marker) # - def __repr__(self): - str = "" - total = 0 - for marker in self.markers_a: - str += repr(marker) + "\n" - total += marker.marker_size - str += "[TOT ] bytes=={}".format(total) - str += "\n" - return str + def addImgData(self, mhex, mpos, mlen, mstr): + marker = JpgMarker(mhex, mpos, mlen, mstr) + self.markers_a.append(marker) + self.markers_img.append(marker) + + # + def printImgMarkers(self): + # print ("Got here dummies") + # print ("len=={}".format(len(self.markers_img))) + # print ("*** *** *** ***\n{}".format(retstr)) + return JpgFingerprint.__printMarker(self.markers_img) + + # + def printMDMarkers(self): + return JpgFingerprint.__printMarker(self.markers_meta) + + # + def __repr__(self): + return JpgFingerprint.__printMarker(self.markers_a) + + # + @staticmethod + def __printMarker(markers): + str = "" + total = 0 + for marker in markers: + str += repr(marker) + "\n" + total += marker.marker_size + str += "[TOT ] bytes=={}".format(total) + str += "\n" + return str # class JpgMarker: - """ - Marker Data Type - """ - def __init__(self, mhex, fpos, mlen, mstr): - self.marker_hex = mhex - self.marker_hexstr = self.marker_hex.to_bytes(2, 'big').hex() - self.marker_filepos = fpos - self.marker_size = mlen - self.marker_cat = mstr + """ + Marker Data Type + """ + def __init__(self, mhex, fpos, mlen, mstr): + self.marker_hex = mhex + self.marker_hexstr = self.marker_hex.to_bytes(2, 'big').hex() + self.marker_filepos = fpos + self.marker_size = mlen + self.marker_cat = mstr - def __repr__(self): - return "[{}] {} {}-len {}-fpos".format(self.marker_cat, self.marker_hexstr, self.marker_size, self.marker_filepos) + def __repr__(self): + return "[{}] {} {}(len) {}(fpos)".format(self.marker_cat, self.marker_hexstr, self.marker_size, self.marker_filepos) diff --git a/libs/jpg_tools.py b/libs/jpg_tools.py index 522edbe..50219cd 100644 --- a/libs/jpg_tools.py +++ b/libs/jpg_tools.py @@ -2,7 +2,7 @@ # # import logging -from PIL import Image +# from PIL import Image from libs.jpg_bin import JpgBin diff --git a/picseal.py b/picseal.py index 8f3916a..4f26648 100644 --- a/picseal.py +++ b/picseal.py @@ -11,6 +11,9 @@ from libs.toolbox import Toolbox from libs.jpg_tools import JpgTools fingerprint = False +printmeta = False +printimage = False + def main(): parseArgs() @@ -23,8 +26,8 @@ def processImage(image_fn): jpg = JpgTools() jpg_bin = jpg.getJpgBin(image_fn) - if (fingerprint): - print( str(jpg_bin) ) + printImageInfo(jpg_bin) + # sig = Signature() # sig.genSig(img_bin) @@ -59,6 +62,17 @@ def copyImage(image_fn): copyfile(image_fn, newFileName) return (pubFileName, privFileName) +# +def printImageInfo(jpg_bin2): + if (fingerprint): + print( str(jpg_bin2) ) + + if (printimage): + print( jpg_bin2.printMarkerImg()) + + if (printmeta): + print( jpg_bin2.printMarkerMeta()) + def parseArgs(): print("***** ***** ***** *****") @@ -69,7 +83,9 @@ def parseArgs(): parser.add_argument('-v', '--verbose', action='store_true', help="will set logging level to INFO") parser.add_argument('-vv', '--vverbose', action='store_true', help="will set logging level to DEBUG") parser.add_argument('-l', '--logging', action='store_true', help="will supercede the -v option and send all logging to a file, logging.DEBUG") - parser.add_argument('-fp', '--fingerprint', action='store_true', help="fingerprint") + parser.add_argument('-pm', '--printmeta', action='store_true', help="print the metadata markers") + parser.add_argument('-pi', '--printimage', action='store_true', help="print the image markers") + parser.add_argument('-fp', '--fingerprint', action='store_true', help="fingerprint") args = parser.parse_args() if (args.logging): @@ -83,8 +99,17 @@ def parseArgs(): logging.basicConfig(level=logging.CRITICAL) if (args.fingerprint): + global fingerprint fingerprint = True + if (args.printmeta): + global printmeta + printmeta = True + + if (args.printimage): + global printimage + printimage = True + if (args.image): processImage(args.image) else: diff --git a/pip-req.txt b/pip-req.txt index 1aa4e5f..ded0367 100644 --- a/pip-req.txt +++ b/pip-req.txt @@ -1,4 +1,2 @@ -Pillow==3.3.1 pycrypto==2.6.1 -requests==2.11.0 -shellescape==3.4.1 + From 93c220e6d2ff3899c28237af2099c805634112d4 Mon Sep 17 00:00:00 2001 From: JohnE Date: Wed, 12 Oct 2016 02:13:28 -0700 Subject: [PATCH 6/6] MOD: changed to -f file --- libs/jpg_bin.py | 1 - picseal.py | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libs/jpg_bin.py b/libs/jpg_bin.py index 6d4b192..ffeac8e 100644 --- a/libs/jpg_bin.py +++ b/libs/jpg_bin.py @@ -258,7 +258,6 @@ class JpgBin: # def __repr__(self): - return repr(self.jpg_fp) # diff --git a/picseal.py b/picseal.py index 4f26648..367c361 100644 --- a/picseal.py +++ b/picseal.py @@ -79,7 +79,7 @@ def parseArgs(): print(" ** Pic * Seal ** ") print("***** ***** ***** *****\n") parser = argparse.ArgumentParser() - parser.add_argument('-i', '--image', required=False, help="source image file") + parser.add_argument('-f', '--file', required=False, help="source image file") parser.add_argument('-v', '--verbose', action='store_true', help="will set logging level to INFO") parser.add_argument('-vv', '--vverbose', action='store_true', help="will set logging level to DEBUG") parser.add_argument('-l', '--logging', action='store_true', help="will supercede the -v option and send all logging to a file, logging.DEBUG") @@ -110,8 +110,8 @@ def parseArgs(): global printimage printimage = True - if (args.image): - processImage(args.image) + if (args.file): + processImage(args.file) else: print('Create PicSeal images') print(' picseal.py -i ')