Initial commit
This commit is contained in:
parent
39c5f79e55
commit
d843ca2c7f
|
@ -0,0 +1,31 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Tue Jun 11 17:10:43 2019
|
||||
|
||||
@author: Administrator
|
||||
"""
|
||||
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
|
||||
img = cv2.imread('a.png',0)
|
||||
img1 = img.astype('float')
|
||||
|
||||
def dct(m):
|
||||
m = np.float32(m)/255.0
|
||||
return cv2.dct(m)*255
|
||||
#print(dct(img1).shape)
|
||||
new_dct=dct(img1)
|
||||
after_dct=[]
|
||||
for i in range(len(new_dct)):
|
||||
for j in range(len(new_dct[0])):
|
||||
after_dct.append(int(new_dct[i][j]))
|
||||
#print(new_dct)
|
||||
#new_dct=new_dct.reshape(-1,1)
|
||||
#print(len(after_dct))
|
||||
#print(after_dct[:600])
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Mon Jun 10 17:30:40 2019
|
||||
|
||||
@author: Administrator
|
||||
"""
|
||||
|
||||
from Jsteg import Jsteg
|
||||
|
||||
|
||||
class F3(Jsteg):
|
||||
def __init__(self):
|
||||
Jsteg.__init__(self)
|
||||
|
||||
def set_sequence_after_dct(self,sequence_after_dct):
|
||||
self.sequence_after_dct=sequence_after_dct
|
||||
sum_len=len(self.sequence_after_dct)
|
||||
zero_len=len([i for i in self.sequence_after_dct if i==0])
|
||||
one_len=len([i for i in self.sequence_after_dct if i in (-1,1)])
|
||||
self.available_info_len=sum_len-zero_len-one_len # 不是特别可靠
|
||||
print ("Load>> 大约可嵌入",sum_len-zero_len-int(one_len/2),'bits')
|
||||
print ("Load>> 最少可嵌入",self.available_info_len,'bits\n')
|
||||
|
||||
def _write(self,index,data):
|
||||
origin=self.sequence_after_dct[index]
|
||||
if origin == 0:
|
||||
return False
|
||||
elif origin in (-1,1) and data==0:
|
||||
self.sequence_after_dct[index]=0
|
||||
return False
|
||||
|
||||
lower_bit=origin%2
|
||||
|
||||
if lower_bit==data:
|
||||
pass
|
||||
elif origin>0:
|
||||
self.sequence_after_dct[index]=origin-1
|
||||
elif origin<0:
|
||||
self.sequence_after_dct[index]=origin+1
|
||||
return True
|
||||
|
||||
def _read(self,index):
|
||||
if self.sequence_after_dct[index] != 0:
|
||||
return self.sequence_after_dct[index]%2
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
if __name__=="__main__":
|
||||
f3=F3()
|
||||
# 写
|
||||
sequence_after_dct=[-1,0,1]*100+[i for i in range(-7,500)]
|
||||
f3.set_sequence_after_dct(sequence_after_dct)
|
||||
info1=[0,1,0,1,1,0,1,0]
|
||||
f3.write(info1)
|
||||
# 读
|
||||
sequence_after_dct2=f3.get_sequence_after_dct()
|
||||
f3.set_sequence_after_dct(sequence_after_dct2)
|
||||
info2=f3.read()
|
||||
print (info2)
|
|
@ -0,0 +1,67 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Tue Jun 11 16:10:51 2019
|
||||
|
||||
@author: Administrator
|
||||
"""
|
||||
|
||||
from Jsteg import Jsteg
|
||||
|
||||
|
||||
class F4(Jsteg):
|
||||
def __init__(self):
|
||||
Jsteg.__init__(self)
|
||||
|
||||
def set_sequence_after_dct(self,sequence_after_dct):
|
||||
self.sequence_after_dct=sequence_after_dct
|
||||
sum_len=len(self.sequence_after_dct)
|
||||
zero_len=len([i for i in self.sequence_after_dct if i==0])
|
||||
one_len=len([i for i in self.sequence_after_dct if i in (-1,1)])
|
||||
self.available_info_len=sum_len-zero_len-one_len # 不是特别可靠
|
||||
print ("Load>> 大约可嵌入",sum_len-zero_len-int(one_len/2),'bits')
|
||||
print ("Load>> 最少可嵌入",self.available_info_len,'bits\n')
|
||||
|
||||
def _write(self,index,data):
|
||||
origin=self.sequence_after_dct[index]
|
||||
if origin == 0:
|
||||
return False
|
||||
elif origin == 1 and data==0:
|
||||
self.sequence_after_dct[index]=0
|
||||
return False
|
||||
|
||||
elif origin == -1 and data==1:
|
||||
self.sequence_after_dct[index]=0
|
||||
return False
|
||||
|
||||
lower_bit=origin%2
|
||||
|
||||
if origin >0:
|
||||
if lower_bit!=data:
|
||||
self.sequence_after_dct[index]=origin-1
|
||||
else:
|
||||
if lower_bit==data:
|
||||
self.sequence_after_dct[index]=origin+1
|
||||
return True
|
||||
|
||||
|
||||
def _read(self,index):
|
||||
if self.sequence_after_dct[index] >0:
|
||||
return self.sequence_after_dct[index]%2
|
||||
elif self.sequence_after_dct[index]<0:
|
||||
return (self.sequence_after_dct[index]+1)%2
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
if __name__=="__main__":
|
||||
f4=F4()
|
||||
# 写
|
||||
sequence_after_dct=[-1,0,1]*100+[i for i in range(-7,500)]
|
||||
f4.set_sequence_after_dct(sequence_after_dct)
|
||||
info1=[0,1,0,1,1,0,1,0]
|
||||
f4.write(info1)
|
||||
# 读
|
||||
sequence_after_dct2=f4.get_sequence_after_dct()
|
||||
f4.set_sequence_after_dct(sequence_after_dct2)
|
||||
info2=f4.read()
|
||||
print (info2)
|
|
@ -0,0 +1,128 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Mon Jun 10 15:26:43 2019
|
||||
|
||||
@author: Administrator
|
||||
"""
|
||||
|
||||
import math
|
||||
|
||||
class Jsteg:
|
||||
def __init__(self):
|
||||
self.sequence_after_dct=None
|
||||
|
||||
def set_sequence_after_dct(self,sequence_after_dct):
|
||||
self.sequence_after_dct=sequence_after_dct
|
||||
self.available_info_len=len([i for i in self.sequence_after_dct if i not in (-1,1,0)]) # 不是绝对可靠的
|
||||
print ("Load>> 可嵌入",self.available_info_len,'bits')
|
||||
|
||||
def get_sequence_after_dct(self):
|
||||
return self.sequence_after_dct
|
||||
|
||||
def write(self,info):
|
||||
"""先嵌入信息的长度,然后嵌入信息"""
|
||||
info=self._set_info_len(info)
|
||||
info_len=len(info)
|
||||
info_index=0
|
||||
im_index=0
|
||||
while True:
|
||||
if info_index>=info_len:
|
||||
break
|
||||
data=info[info_index]
|
||||
if self._write(im_index,data):
|
||||
info_index+=1
|
||||
im_index+=1
|
||||
|
||||
|
||||
def read(self):
|
||||
"""先读出信息的长度,然后读出信息"""
|
||||
_len,sequence_index=self._get_info_len()
|
||||
info=[]
|
||||
info_index=0
|
||||
|
||||
while True:
|
||||
if info_index>=_len:
|
||||
break
|
||||
data=self._read(sequence_index)
|
||||
if data!=None:
|
||||
info.append(data)
|
||||
info_index+=1
|
||||
sequence_index+=1
|
||||
|
||||
return info
|
||||
|
||||
#===============================================================#
|
||||
|
||||
def _set_info_len(self,info):
|
||||
l=int(math.log(self.available_info_len,2))+1
|
||||
info_len=[0]*l
|
||||
_len=len(info)
|
||||
info_len[-len(bin(_len))+2:]=[int(i) for i in bin(_len)[2:]]
|
||||
return info_len+info
|
||||
|
||||
def _get_info_len(self):
|
||||
l=int(math.log(self.available_info_len,2))+1
|
||||
len_list=[]
|
||||
_l_index=0
|
||||
_seq_index=0
|
||||
while True:
|
||||
if _l_index>=l:
|
||||
break
|
||||
_d=self._read(_seq_index)
|
||||
if _d!=None:
|
||||
len_list.append(str(_d))
|
||||
_l_index+=1
|
||||
_seq_index+=1
|
||||
_len=''.join(len_list)
|
||||
_len=int(_len,2)
|
||||
return _len,_seq_index
|
||||
|
||||
# 注意经过DCT会有负值,此处最低有效位的嵌入方式与空域LSB略有不同
|
||||
def _write(self,index,data):
|
||||
origin=self.sequence_after_dct[index]
|
||||
if origin in (-1,1,0):
|
||||
return False
|
||||
|
||||
lower_bit=origin%2
|
||||
if lower_bit==data:
|
||||
pass
|
||||
elif origin>0:
|
||||
if (lower_bit,data) == (0,1):
|
||||
self.sequence_after_dct[index]=origin+1
|
||||
elif (lower_bit,data) == (1,0):
|
||||
self.sequence_after_dct[index]=origin-1
|
||||
elif origin<0:
|
||||
if (lower_bit,data) == (0,1):
|
||||
self.sequence_after_dct[index]=origin-1
|
||||
elif (lower_bit,data) == (1,0):
|
||||
self.sequence_after_dct[index]=origin+1
|
||||
|
||||
return True
|
||||
|
||||
def _read(self,index):
|
||||
if self.sequence_after_dct[index] not in (-1,1,0):
|
||||
return self.sequence_after_dct[index]%2
|
||||
else:
|
||||
return None
|
||||
'''
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
def dct(m):
|
||||
m = np.float32(m)/255.0
|
||||
return cv2.dct(m)*255
|
||||
'''
|
||||
|
||||
if __name__=="__main__":
|
||||
jsteg=Jsteg()
|
||||
# 写
|
||||
sequence_after_dct=[-1,0,1]*100+[i for i in range(-7,500)]
|
||||
#print(sequence_after_dct)
|
||||
jsteg.set_sequence_after_dct(sequence_after_dct)
|
||||
info1=[0,1,0,1,1,0,1,0]
|
||||
jsteg.write(info1)
|
||||
sequence_after_dct2=jsteg.get_sequence_after_dct()
|
||||
# 读
|
||||
jsteg.set_sequence_after_dct(sequence_after_dct2)
|
||||
info2=jsteg.read()
|
||||
print (info2)
|
|
@ -0,0 +1 @@
|
|||
dajkhfahjkf
|
|
@ -0,0 +1 @@
|
|||
dajkhfahjkf
|
|
@ -0,0 +1,69 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Sun May 19 12:43:26 2019
|
||||
|
||||
@author: Administrator
|
||||
"""
|
||||
|
||||
from PIL import Image
|
||||
|
||||
def mod(x,y):
|
||||
return x%y
|
||||
|
||||
def toasc(strr):
|
||||
return int(strr, 2)
|
||||
|
||||
|
||||
#le为所要提取的信息的长度,str1为加密载体图片的路径,str2为提取文件的保存路径
|
||||
def func(le,str1,str2):
|
||||
b=""
|
||||
im = Image.open(str1)
|
||||
lenth = le*8
|
||||
width,height = im.size[0],im.size[1]
|
||||
count = 0
|
||||
for h in range(height):
|
||||
for w in range(width):
|
||||
#获得(w,h)点像素的值
|
||||
pixel = im.getpixel((w, h))
|
||||
#此处余3,依次从R、G、B三个颜色通道获得最低位的隐藏信息
|
||||
if count%3==0:
|
||||
count+=1
|
||||
b=b+str((mod(int(pixel[0]),2)))
|
||||
if count ==lenth:
|
||||
break
|
||||
if count%3==1:
|
||||
count+=1
|
||||
b=b+str((mod(int(pixel[1]),2)))
|
||||
if count ==lenth:
|
||||
break
|
||||
if count%3==2:
|
||||
count+=1
|
||||
b=b+str((mod(int(pixel[2]),2)))
|
||||
if count ==lenth:
|
||||
break
|
||||
if count == lenth:
|
||||
break
|
||||
|
||||
with open(str2,"w",encoding='utf-8') as f:
|
||||
for i in range(0,len(b),8):
|
||||
#以每8位为一组二进制,转换为十进制
|
||||
stra = toasc(b[i:i+8])
|
||||
#将转换后的十进制数视为ascii码,再转换为字符串写入到文件中
|
||||
#print((stra))
|
||||
f.write(chr(stra))
|
||||
print("完成信息提取!")
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
#文件长度
|
||||
le = 11
|
||||
#含有隐藏信息的图片
|
||||
new = "new.png"
|
||||
#信息提取出后所存放的文件
|
||||
get_info = "get_flag.txt"
|
||||
func(le,new,get_info)
|
||||
|
||||
if __name__=='__main__':
|
||||
main()
|
|
@ -0,0 +1,85 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Sun May 19 11:20:05 2019
|
||||
|
||||
@author: Administrator
|
||||
"""
|
||||
|
||||
from PIL import Image
|
||||
|
||||
|
||||
def plus(string):
|
||||
#Python zfill() 方法返回指定长度的字符串,原字符串右对齐,前面填充0。
|
||||
return string.zfill(8)
|
||||
|
||||
def get_key(strr):
|
||||
#获取要隐藏的文件内容
|
||||
with open(strr,"rb") as f:
|
||||
s = f.read()
|
||||
string=""
|
||||
for i in range(len(s)):
|
||||
#逐个字节将要隐藏的文件内容转换为二进制,并拼接起来
|
||||
#1.先用ord()函数将s的内容逐个转换为ascii码
|
||||
#2.使用bin()函数将十进制的ascii码转换为二进制
|
||||
#3.由于bin()函数转换二进制后,二进制字符串的前面会有"0b"来表示这个字符串是二进制形式,所以用replace()替换为空
|
||||
#4.又由于ascii码转换二进制后是七位,而正常情况下每个字符由8位二进制组成,所以使用自定义函数plus将其填充为8位
|
||||
string=string+""+plus(bin(s[i]).replace('0b',''))
|
||||
#print(string)
|
||||
return string
|
||||
|
||||
def mod(x,y):
|
||||
return x%y
|
||||
|
||||
#str1为载体图片路径,str2为隐写文件,str3为加密图片保存的路径
|
||||
def func(str1,str2,str3):
|
||||
im = Image.open(str1)
|
||||
#获取图片的宽和高
|
||||
width,height= im.size[0],im.size[1]
|
||||
print("width:"+str(width))
|
||||
print("height:"+str(height))
|
||||
count = 0
|
||||
#获取需要隐藏的信息
|
||||
key = get_key(str2)
|
||||
keylen = len(key)
|
||||
for h in range(height):
|
||||
for w in range(width):
|
||||
pixel = im.getpixel((w,h))
|
||||
a=pixel[0]
|
||||
b=pixel[1]
|
||||
c=pixel[2]
|
||||
if count == keylen:
|
||||
break
|
||||
#下面的操作是将信息隐藏进去
|
||||
#分别将每个像素点的RGB值余2,这样可以去掉最低位的值
|
||||
#再从需要隐藏的信息中取出一位,转换为整型
|
||||
#两值相加,就把信息隐藏起来了
|
||||
a= a-mod(a,2)+int(key[count])
|
||||
count+=1
|
||||
if count == keylen:
|
||||
im.putpixel((w,h),(a,b,c))
|
||||
break
|
||||
b =b-mod(b,2)+int(key[count])
|
||||
count+=1
|
||||
if count == keylen:
|
||||
im.putpixel((w,h),(a,b,c))
|
||||
break
|
||||
c= c-mod(c,2)+int(key[count])
|
||||
count+=1
|
||||
if count == keylen:
|
||||
im.putpixel((w,h),(a,b,c))
|
||||
break
|
||||
if count % 3 == 0:
|
||||
im.putpixel((w,h),(a,b,c))
|
||||
im.save(str3)
|
||||
|
||||
def main():
|
||||
#原图
|
||||
old = "old.png"
|
||||
#处理后输出的图片路径
|
||||
new = "new.png"
|
||||
#需要隐藏的信息
|
||||
enc = "flag.txt"
|
||||
func(old,enc,new)
|
||||
|
||||
if __name__=='__main__':
|
||||
main()
|
Binary file not shown.
After Width: | Height: | Size: 160 KiB |
Binary file not shown.
After Width: | Height: | Size: 161 KiB |
|
@ -0,0 +1,282 @@
|
|||
# PDF格式学习
|
||||
## PDF简介
|
||||
* PDF是Portable Document Format 的缩写,可翻译为“便携文件格式”,由Adobe System Incorporated 公司在1992年发明。
|
||||
|
||||
* PDF文件是一种编程形式的文档格式,它所有显示的内容,都是通过相应的操作符进行绘制的。
|
||||
* PDF基本显示单元包括:文字,图片,矢量图,图片
|
||||
* PDF扩展单元包括:水印,电子署名,注释,表单,多媒体,3D
|
||||
* PDF动作单元:书签,超链接(拥有动作的单元有很多个,包括电子署名,多媒体等等)
|
||||
## PDF的优点
|
||||
* 一致性:
|
||||
在所有可以打开PDF的机器上,展示的效果是完全一致,不会出现段落错乱、文字乱码这些排版问题。尤其是文档中,本身可以嵌入字体,避免了客户端没有对应字体,而导致文字显示不一致的问题。所以,在印刷行业,绝大多数用的都是PDF格式。
|
||||
* 不易修改:
|
||||
用过PDF文件的人,都会知道,对已经保存之后的PDF文件,想要进行重新排版,基本上就不可能的,这就保证了从资料源发往外界的资料,不容易被篡改。
|
||||
* 安全性:
|
||||
PDF文档可以进行加密,包括以下几种加密形式:文档打开密码,文档权限密码,文档证书密码,加密的方法包括:RC4,AES,通过加密这种形式,可以达到资料防扩散等目的。
|
||||
* 不失真:
|
||||
PDF文件中,使用了矢量图,在文件浏览时,无论放大多少倍,都不会导致使用矢量图绘制的文字,图案的失真。
|
||||
* 支持多种压缩方式:
|
||||
为了减少PDF文件的size,PDF格式支持各种压缩方式: asciihex,ascii85,lzw,runlength,ccitt,jbig2,jpeg(DCT),jpeg2000(jpx)
|
||||
* 支持多种印刷标准:
|
||||
支持PDF-A,PDF-X
|
||||
|
||||
## PDF格式
|
||||
根据PDF官方指南,理解PDF格式可以从四个方面下手——**Objects**(对象)、**File structure**(物理文件结构)、**Document structure**(逻辑文件结构)、**Content streams**(内容流)。
|
||||
|
||||
### 对象
|
||||
|
||||
### 物理文件结构
|
||||
* 整体上分为文件头(Header)、对象集合(Body)、交叉引用表(Xref table)、文件尾(Trailer)四个部分,结构如图。修改过的PDF结构会有部分变化。
|
||||
* 未经修改
|
||||
![未经修改](https://img-blog.csdnimg.cn/20190526170017719.png#pic_center)
|
||||
* 经修改
|
||||
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190526170402806.png#pic_center)
|
||||
#### 文件头
|
||||
* 文件头是PDF文件的第一行,格式如下:
|
||||
```
|
||||
%PDF-1.7
|
||||
```
|
||||
* 这是个固定格式,表示这个PDF文件遵循的PDF规范版本,解析PDF的时候尽量支持高版本的规范,以保证支持大多数工具生成的PDF文件。1.7版本支持1.0-1.7之间的所有版本。
|
||||
|
||||
#### 对象集合
|
||||
* 这是一个PDF文件最重要的部分,文件中用到的所有对象,包括文本、图象、音乐、视频、字体、超连接、加密信息、文档结构信息等等,都在这里定义。格式如下:
|
||||
```
|
||||
2 0 obj
|
||||
...
|
||||
end obj
|
||||
```
|
||||
* 一个对象的定义包含4个部分:前面的2是**对象序号**,其用来唯一标记一个对象;0是**生成号**,按照PDF规范,如果一个PDF文件被修改,那这个数字是累加的,它和对象序号一起标记是原始对象还是修改后的对象,但是实际开发中,很少有用这种方式修改PDF的,都是重新编排对象号;obj和endobj是对象的定义范围,可以抽象的理解为这就是一个左括号和右括号;省略号部分是PDF规定的任意合法对象。
|
||||
* 可以通过R关键字来引用任何一个对象,比如要引用上面的对象,可以使用2 0 R,需要主意的是,R关键字不仅可以引用一个已经定义的对象,还可以引用一个并**不存在的对象**,而且效果就和引用了一个空对象一样。
|
||||