Merge branch 'hash'

This commit is contained in:
JohnE 2016-10-12 02:13:46 -07:00
commit 7c9fec279b
21 changed files with 351 additions and 190 deletions

17
docs/README Normal file
View File

@ -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 ]]

37
docs/README_DSN Normal file
View File

@ -0,0 +1,37 @@
[[ 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 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 ]]
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": ""
}

View File

@ -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"
}

View File

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 120 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@ -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

View File

@ -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):
@ -61,16 +66,140 @@ class JpgBin:
return False
while(self.continue_process):
self.findAllMarker()
self.findAllMarkers()
self.getMoreBytes()
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.addImgData(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
self.processFile(file_h)
#self.processFile(file_h)
while(self.continue_process):
if (self.findMarker(self.makers['SOS'])):
@ -106,6 +235,7 @@ class JpgBin:
self.seekBytes(rec_diff)
else:
self.data_idx += rec_len
return rec_len
#
def seekBytes(self, num_bytes):
@ -114,107 +244,23 @@ 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 findAllMarker(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):
last_idx = len(self.data_buf)

69
libs/jpg_fp.py Normal file
View File

@ -0,0 +1,69 @@
#
#
#
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):
# 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
def __repr__(self):
return "[{}] {} {}(len) {}(fpos)".format(self.marker_cat, self.marker_hexstr, self.marker_size, self.marker_filepos)

View File

@ -1,45 +1,33 @@
#
#
#
from PIL import Image
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)
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
#
def jpgHash(self):
self.fh = open(fname, "rb")
self.jpg = JpgBin()
retval = self.jpg.processFile(self.fh)
print("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))
#
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.???
logging.info("processFile()=={}".format(retval))

View File

@ -7,10 +7,13 @@ 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
fingerprint = False
printmeta = False
printimage = False
def main():
parseArgs()
@ -21,7 +24,9 @@ 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)
printImageInfo(jpg_bin)
# sig = Signature()
# sig.genSig(img_bin)
@ -34,17 +39,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):
@ -55,16 +62,30 @@ 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("***** ***** ***** *****")
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")
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):
@ -77,8 +98,20 @@ def parseArgs():
else:
logging.basicConfig(level=logging.CRITICAL)
if (args.image):
processImage(args.image)
if (args.fingerprint):
global fingerprint
fingerprint = True
if (args.printmeta):
global printmeta
printmeta = True
if (args.printimage):
global printimage
printimage = True
if (args.file):
processImage(args.file)
else:
print('Create PicSeal images')
print(' picseal.py -i <image_file>')

View File

@ -1,5 +1,2 @@
Pillow==3.3.1
pycrypto==2.6.1
pygobject==3.20.1
requests==2.11.0
shellescape==3.4.1

View File

@ -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

View File

@ -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")

View File

View File

@ -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 =)'