Merge branch 'hash'
|
@ -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 ]]
|
||||||
|
|
||||||
|
|
|
@ -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": ""
|
||||||
|
}
|
||||||
|
|
|
@ -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"
|
||||||
|
}
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 1.7 MiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
@ -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 logging
|
||||||
import json
|
import json
|
||||||
import gi
|
import gi
|
||||||
|
|
262
libs/jpg_bin.py
|
@ -20,29 +20,34 @@
|
||||||
import re
|
import re
|
||||||
import struct
|
import struct
|
||||||
import logging
|
import logging
|
||||||
|
from libs.jpg_fp import JpgFingerprint
|
||||||
|
|
||||||
#
|
#
|
||||||
class JpgBin:
|
class JpgBin:
|
||||||
|
|
||||||
BUF_CHUNK_SIZE = 2048
|
BUF_CHUNK_SIZE = 2048
|
||||||
data_buf = None
|
|
||||||
data_idx = 0
|
|
||||||
data_len = 0
|
|
||||||
fh = None
|
|
||||||
hh = None
|
|
||||||
|
|
||||||
markers = {
|
markers = {
|
||||||
'SOS': 0xffd9
|
'SOS': 0xffd9
|
||||||
}
|
}
|
||||||
|
|
||||||
continue_process = True
|
|
||||||
|
|
||||||
metadata_h = {}
|
|
||||||
img_bin_h = {}
|
|
||||||
|
|
||||||
|
|
||||||
def __init__(self):
|
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):
|
def __isJPG(self):
|
||||||
|
@ -61,16 +66,140 @@ class JpgBin:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
while(self.continue_process):
|
while(self.continue_process):
|
||||||
self.findAllMarker()
|
self.findAllMarkers()
|
||||||
self.getMoreBytes()
|
self.getMoreBytes()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
return False
|
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):
|
def genHash(self, file_h, hash_h):
|
||||||
self.hh = hash_h
|
self.hh = hash_h
|
||||||
self.processFile(file_h)
|
#self.processFile(file_h)
|
||||||
|
|
||||||
while(self.continue_process):
|
while(self.continue_process):
|
||||||
if (self.findMarker(self.makers['SOS'])):
|
if (self.findMarker(self.makers['SOS'])):
|
||||||
|
@ -106,6 +235,7 @@ class JpgBin:
|
||||||
self.seekBytes(rec_diff)
|
self.seekBytes(rec_diff)
|
||||||
else:
|
else:
|
||||||
self.data_idx += rec_len
|
self.data_idx += rec_len
|
||||||
|
return rec_len
|
||||||
|
|
||||||
#
|
#
|
||||||
def seekBytes(self, num_bytes):
|
def seekBytes(self, num_bytes):
|
||||||
|
@ -114,107 +244,23 @@ class JpgBin:
|
||||||
self.getMoreBytes(True)
|
self.getMoreBytes(True)
|
||||||
return pos
|
return pos
|
||||||
|
|
||||||
|
#
|
||||||
|
def printMarkerImg(self):
|
||||||
|
return self.jpg_fp.printImgMarkers()
|
||||||
|
|
||||||
|
#
|
||||||
|
def printMarkerMeta(self):
|
||||||
|
return self.jpg_fp.printMDMarkers()
|
||||||
|
|
||||||
#
|
#
|
||||||
def findMarker(self, marker):
|
def findMarker(self, marker):
|
||||||
|
|
||||||
pass
|
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):
|
def __repr__(self):
|
||||||
pass
|
return repr(self.jpg_fp)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
def findMarkers222(self):
|
def findMarkers222(self):
|
||||||
last_idx = len(self.data_buf)
|
last_idx = len(self.data_buf)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,45 +1,33 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
from PIL import Image
|
import logging
|
||||||
|
# from PIL import Image
|
||||||
from libs.jpg_bin import JpgBin
|
from libs.jpg_bin import JpgBin
|
||||||
|
|
||||||
|
|
||||||
class JpgTools:
|
class JpgTools:
|
||||||
|
|
||||||
fh = None
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.fh = None
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
#
|
||||||
|
# process a jpg file, read only
|
||||||
|
#
|
||||||
def getJpgBin(self, fname):
|
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):
|
def jpgHash(self):
|
||||||
self.fh = open(fname, "rb")
|
self.fh = open(fname, "rb")
|
||||||
self.jpg = JpgBin()
|
self.jpg = JpgBin()
|
||||||
retval = self.jpg.processFile(self.fh)
|
retval = self.jpg.processFile(self.fh)
|
||||||
|
logging.info("processFile()=={}".format(retval))
|
||||||
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.???
|
|
||||||
|
|
||||||
|
|
59
picseal.py
|
@ -7,10 +7,13 @@ import logging
|
||||||
from shutil import copyfile
|
from shutil import copyfile
|
||||||
#from subprocess import Popen, PIPE, check_call
|
#from subprocess import Popen, PIPE, check_call
|
||||||
from libs.crypto_pub import Signature
|
from libs.crypto_pub import Signature
|
||||||
from libs.img_exif import ImgExif
|
|
||||||
from libs.toolbox import Toolbox
|
from libs.toolbox import Toolbox
|
||||||
from libs.jpg_tools import JpgTools
|
from libs.jpg_tools import JpgTools
|
||||||
|
|
||||||
|
fingerprint = False
|
||||||
|
printmeta = False
|
||||||
|
printimage = False
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parseArgs()
|
parseArgs()
|
||||||
|
@ -21,8 +24,10 @@ def main():
|
||||||
# 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()
|
jpg = JpgTools()
|
||||||
img_bin = jpg.getJpgBin(image_fn)
|
jpg_bin = jpg.getJpgBin(image_fn)
|
||||||
|
|
||||||
|
printImageInfo(jpg_bin)
|
||||||
|
|
||||||
# sig = Signature()
|
# sig = Signature()
|
||||||
# sig.genSig(img_bin)
|
# sig.genSig(img_bin)
|
||||||
|
|
||||||
|
@ -34,17 +39,19 @@ def processImage(image_fn):
|
||||||
|
|
||||||
# add a digital signature to the metadata
|
# add a digital signature to the metadata
|
||||||
def writePubImg(pub_fn, sig):
|
def writePubImg(pub_fn, sig):
|
||||||
img = ImgExif(pub_fn)
|
pass
|
||||||
img.addKey(sig.getPubKeyPEM())
|
# img = ImgExif(pub_fn)
|
||||||
img.addSig(sig.sig_data)
|
# img.addKey(sig.getPubKeyPEM())
|
||||||
img.saveFile()
|
# img.addSig(sig.sig_data)
|
||||||
|
# img.saveFile()
|
||||||
|
|
||||||
#
|
#
|
||||||
def writePrivImg(priv_fn, sig):
|
def writePrivImg(priv_fn, sig):
|
||||||
img = ImgExif(priv_fn)
|
pass
|
||||||
img.addKey(sig.getPrivKeyPEM())
|
# img = ImgExif(priv_fn)
|
||||||
|
# img.addKey(sig.getPrivKeyPEM())
|
||||||
#img.addSig(sig.sig_data)
|
#img.addSig(sig.sig_data)
|
||||||
img.saveFile()
|
# img.saveFile()
|
||||||
|
|
||||||
#
|
#
|
||||||
def copyImage(image_fn):
|
def copyImage(image_fn):
|
||||||
|
@ -55,16 +62,30 @@ def copyImage(image_fn):
|
||||||
copyfile(image_fn, newFileName)
|
copyfile(image_fn, newFileName)
|
||||||
return (pubFileName, privFileName)
|
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():
|
def parseArgs():
|
||||||
print("***** ***** ***** *****")
|
print("***** ***** ***** *****")
|
||||||
print(" ** Pic * Seal ** ")
|
print(" ** Pic * Seal ** ")
|
||||||
print("***** ***** ***** *****\n")
|
print("***** ***** ***** *****\n")
|
||||||
parser = argparse.ArgumentParser()
|
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('-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('-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('-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()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if (args.logging):
|
if (args.logging):
|
||||||
|
@ -77,8 +98,20 @@ def parseArgs():
|
||||||
else:
|
else:
|
||||||
logging.basicConfig(level=logging.CRITICAL)
|
logging.basicConfig(level=logging.CRITICAL)
|
||||||
|
|
||||||
if (args.image):
|
if (args.fingerprint):
|
||||||
processImage(args.image)
|
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:
|
else:
|
||||||
print('Create PicSeal images')
|
print('Create PicSeal images')
|
||||||
print(' picseal.py -i <image_file>')
|
print(' picseal.py -i <image_file>')
|
||||||
|
|
|
@ -1,5 +1,2 @@
|
||||||
Pillow==3.3.1
|
|
||||||
pycrypto==2.6.1
|
pycrypto==2.6.1
|
||||||
pygobject==3.20.1
|
|
||||||
requests==2.11.0
|
|
||||||
shellescape==3.4.1
|
|
||||||
|
|
|
@ -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
|
|
|
@ -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")
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#
|
#
|
||||||
# Test Signature Class
|
# 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 =)'
|
msg = b'Hieee, this is a test =)'
|
||||||
|
|
||||||
|
|