带AES加密的图片水印加密技术
时间:2010-10-16 来源:AniX
但在他告诉我的方法中,对文本编码方式有特殊要求,特别是中文——必须是GB2312编码,否则还原后的文字将是乱码。并且,仅仅这样对文字进行隐藏是不太安全的,对方只要有一个类似的加解密软件,便可将信息全部还原。
我在研究这种算法一段时间后,有了一些想法——我们可以现将文本信息进行一次AES加密(或其他的加密算法)后,在将加密后的密文写入bmp图片中。这样对文本信息进行处理后,密文既有隐藏式加密的隐秘性,又有算法式加密的复杂性,可谓是一种更强的加密方式!
因此,我将我的方法写成了一个.net类库,并改进了文本的二进制编码方式,使其不受特定编码的限制。
以下是代码,望高手赐教!!
(类库中包含AES加密模块,也可改为其他加密算法)
代码
Imports System.Security
Imports System.Security.Cryptography
Imports System.Text
Imports System.IO
Imports System.Runtime.Serialization.Formatters
Public Class AesWithBMP
<Serializable()> Public Structure KeyFileStructure ‘可用此结构来创建一个密钥文件
Public strKey As String ’密钥
Public strIV As String ‘初始向量
Public IsEnCryptWithBMP As Boolean ’是否写入bmp图片
Public IsInputBMPWithEnCrypt As Boolean ‘写入bmp图片的内容是否经过AES加密
End Structure
Public Sub CreateKeyFile(ByVal strKey As String, ByVal strIV As String, ByVal IsEnCryptWithBMP As Boolean, ByVal IsInputBMPWithEnCrypt As Boolean, ByVal KeySaveName As String, Optional ByVal IsRewriteKeyFile As Boolean = False) ’此函数用于在指定路径创建一个密钥文件
Dim fStream As FileStream = Nothing
Try
If Not File.Exists(KeySaveName) Then
Dim KeyStructure As New KeyFileStructure
With KeyStructure
.strKey = strKey
.strIV = strIV
.IsEnCryptWithBMP = IsEnCryptWithBMP
.IsInputBMPWithEnCrypt = IsInputBMPWithEnCrypt
End With
Dim kFomatter As New Binary.BinaryFormatter
fStream = New FileStream(KeySaveName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None)
kFomatter.Serialize(fStream, KeyStructure) ‘将密钥结构序列化
Else
If IsRewriteKeyFile Then ’当发现同名密钥文件时是否覆盖
Dim KeyStructure As New KeyFileStructure
With KeyStructure
.strKey = strKey
.strIV = strIV
.IsEnCryptWithBMP = IsEnCryptWithBMP
.IsInputBMPWithEnCrypt = IsInputBMPWithEnCrypt
End With
Dim kFomatter As New Binary.BinaryFormatter
fStream = New FileStream(KeySaveName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None)
kFomatter.Serialize(fStream, KeyStructure)
KeyStructure = Nothing
End If
End If
Finally
If fStream IsNot Nothing Then fStream.Close()
End Try
End Sub
Public Sub GetKeyFile(ByVal SBKName As String, ByRef out_KeyFile As KeyFileStructure) ‘此过程用于从密钥文件中获取密钥等信息
Dim fStream As FileStream = Nothing
Try
Dim kFomatter As New Binary.BinaryFormatter
fStream = New FileStream(SBKName, FileMode.Open, FileAccess.Read)
out_KeyFile = kFomatter.Deserialize(fStream)
Finally
If fStream IsNot Nothing Then fStream.Close()
End Try
End Sub
Private Sub EnCrypt(ByVal SourceFileName As String, ByVal ResultFileName As String, ByVal Key As String, ByVal IV As String) ’对指定文件进行AES加密,并保存到指定路径
Dim myCryptoStream As CryptoStream = Nothing
Dim SourceFileStream As FileStream = Nothing
Dim ResultFileStream As FileStream = Nothing
Dim myAESProvider As AesCryptoServiceProvider = Nothing
Try
myAESProvider = New AesCryptoServiceProvider
myAESProvider.Key = ASCIIEncoding.ASCII.GetBytes(Key)
myAESProvider.IV = ASCIIEncoding.ASCII.GetBytes(IV)
Dim myICryptoTransform As ICryptoTransform = myAESProvider.CreateEncryptor(myAESProvider.Key, myAESProvider.IV)
SourceFileStream = New FileStream(SourceFileName, FileMode.Open, FileAccess.Read, FileShare.None)
ResultFileStream = New FileStream(ResultFileName, FileMode.Create, FileAccess.Write)
myCryptoStream = New CryptoStream(ResultFileStream, myICryptoTransform, CryptoStreamMode.Write)
Dim InputByteArray(SourceFileStream.Length - 1) As Byte
SourceFileStream.Read(InputByteArray, 0, InputByteArray.Length)
myCryptoStream.Write(InputByteArray, 0, InputByteArray.Length)
Finally
If myCryptoStream IsNot Nothing Then myCryptoStream.Close()
If SourceFileStream IsNot Nothing Then SourceFileStream.Close()
If ResultFileStream IsNot Nothing Then ResultFileStream.Close()
If myAESProvider IsNot Nothing Then myAESProvider.Clear()
End Try
End Sub
Private Sub DeCrypt(ByVal SourceFileName As String, ByVal ResultFileName As String, ByVal Key As String, ByVal IV As String) ‘对指定文件进行AES解密,并将明文保存到指定路径
Dim myCryptoStream As CryptoStream = Nothing
Dim SourceFileStream As FileStream = Nothing
Dim ResultFileStream As FileStream = Nothing
Dim myAESProvider As AesCryptoServiceProvider = Nothing
Try
myAESProvider = New AesCryptoServiceProvider
myAESProvider.Key = ASCIIEncoding.ASCII.GetBytes(Key)
myAESProvider.IV = ASCIIEncoding.ASCII.GetBytes(IV)
Dim myICryptoTransform As ICryptoTransform = myAESProvider.CreateDecryptor(myAESProvider.Key, myAESProvider.IV)
SourceFileStream = New FileStream(SourceFileName, FileMode.Open, FileAccess.Read, FileShare.None)
ResultFileStream = New FileStream(ResultFileName, FileMode.Create, FileAccess.Write)
myCryptoStream = New CryptoStream(ResultFileStream, myICryptoTransform, CryptoStreamMode.Write)
Dim InputByteArray(SourceFileStream.Length - 1) As Byte
SourceFileStream.Read(InputByteArray, 0, InputByteArray.Length)
myCryptoStream.Write(InputByteArray, 0, InputByteArray.Length)
Finally
If myCryptoStream IsNot Nothing Then myCryptoStream.Close()
If SourceFileStream IsNot Nothing Then SourceFileStream.Close()
If ResultFileStream IsNot Nothing Then ResultFileStream.Close()
If myAESProvider IsNot Nothing Then myAESProvider.Clear()
End Try
End Sub
Public Sub AES_EnCrypt(ByVal SourceFileName As String, ByVal ResultFileName As String, ByVal Key As String, ByVal IV As String, ByVal IsEnCryption As Boolean) ‘主调用过程,用于控制AES加解密过程的调用顺序
If IsEnCryption Then
EnCrypt(SourceFileName, ResultFileName, Key, IV)
Else
DeCrypt(SourceFileName, ResultFileName, Key, IV)
End If
End Sub
Private Function GetBitOfByte(ByVal b As Byte) As Byte() ’将一字节数分解为八个二进制位
Dim res(7) As Byte
For i As Integer = 0 To 7
res(7 - i) = (b >> i) And 1
Next
Return res
End Function
Private Sub EnCryptWithBMP(ByVal SourceFileName As String, ByVal ResultBMPName As String, Optional ByVal IsInputBMPWithEnCrypt As Boolean = False, Optional ByVal strKey As String = "", Optional ByVal strIV As String = "") ‘次调用过程,控制图片水印加密过程的调用顺序
If IsInputBMPWithEnCrypt Then
Dim tempFileName As String = Path.GetTempFileName
EnCrypt(SourceFileName, tempFileName, strKey, strIV)
InputTextToBMP(tempFileName, ResultBMPName)
File.Delete(tempFileName)
Else
InputTextToBMP(SourceFileName, ResultBMPName)
End If
End Sub
Private Sub DeCryptWithBMP(ByVal SourceBMPName As String, ByVal ResultFileName As String, Optional ByVal IsInputBMPWithEnCrypt As Boolean = False, Optional ByVal strKey As String = "", Optional ByVal strIV As String = "") ’次调用过程,控制图片水印解密过程的调用顺序
If IsInputBMPWithEnCrypt Then
Dim tempFileName As String = Path.GetTempFileName
GetTextFromBMP(SourceBMPName, tempFileName)
DeCrypt(tempFileName, ResultFileName, strKey, strIV)
File.Delete(tempFileName)
Else
GetTextFromBMP(SourceBMPName, ResultFileName)
End If
End Sub
Public Sub AESwithBMP_EnCrypt(ByVal SourceFileName As String, ByVal ResultFileName As String, ByVal IsEnCryption As Boolean, Optional ByVal IsInputBMPWithEnCrypt As Boolean = False, Optional ByVal Key As String = "", Optional ByVal IV As String = "") ‘主调用过程,用于控制对图片水印的次调用过程的调用顺序
If IsEnCryption Then
If IsInputBMPWithEnCrypt Then
EnCryptWithBMP(SourceFileName, ResultFileName, True, Key, IV)
Else
EnCryptWithBMP(SourceFileName, ResultFileName)
End If
Else
If IsInputBMPWithEnCrypt Then
DeCryptWithBMP(SourceFileName, ResultFileName, True, Key, IV)
Else
DeCryptWithBMP(SourceFileName, ResultFileName)
End If
End If
End Sub
Private Sub InputTextToBMP(ByVal SourceFileName As String, ByVal BMPName As String) ’将指定的文本信息进行二进制编码后,写入指定bmp图片
Dim fStream As FileStream = Nothing
Dim bmpStream As FileStream = Nothing
Try
fStream = New FileStream(SourceFileName, FileMode.Open, FileAccess.Read)
bmpStream = New FileStream(BMPName, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
Dim dm(1) As Byte
bmpStream.Read(dm, 0, 2)
If Not (dm(0) = 66 AndAlso dm(1) = 77) Then ’bmp图片的前两字节是文件类型标示位
Throw New ApplicationException("目标图片不是合法的BMP位图文件")
End If
Dim i As Integer
Dim BMP_Data(7) As Byte
Dim Text_Data(0) As Byte
Dim Input_Data(7) As Byte
bmpStream.Seek(55, SeekOrigin.Begin) ‘将bmp图片的指针跳到第55字节,因为55字节后才是数据区。
For i = 0 To fStream.Length - 1
fStream.Read(Text_Data, 0, 1)
bmpStream.Read(BMP_Data, 0, 8)
Dim temp_Data() As Byte = GetBitOfByte(Text_Data(0))
For k As Integer = 0 To 7
If temp_Data(k) = 0 Then
Input_Data(k) = BMP_Data(k) And 254
Else
Input_Data(k) = BMP_Data(k) Or 1
End If
Next
bmpStream.Seek(-8, SeekOrigin.Current)
bmpStream.Write(Input_Data, 0, 8)
Next
bmpStream.Read(BMP_Data, 0, 8)
For k As Integer = 0 To 7
Input_Data(k) = BMP_Data(k) Or 1
Next
bmpStream.Seek(-8, SeekOrigin.Current)
bmpStream.Write(Input_Data, 0, 8)
Finally
If fStream IsNot Nothing Then fStream.Close()
If bmpStream IsNot Nothing Then bmpStream.Close()
End Try
End Sub
Private Sub GetTextFromBMP(ByVal SourceBMPName As String, ByVal ResultFileName As String) ‘将指定bmp图片中的二进制信息还原为文本
Dim bmpStream As FileStream = Nothing
Dim fStream As FileStream = Nothing
Try
bmpStream = New FileStream(SourceBMPName, FileMode.Open, FileAccess.Read, FileShare.None)
fStream = New FileStream(ResultFileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None)
Dim dm(1) As Byte
bmpStream.Read(dm, 0, 2)
If Not (dm(0) = 66 AndAlso dm(1) = 77) Then
Throw New ApplicationException("目标图片不是合法的BMP位图文件")
End If
bmpStream.Seek(55, SeekOrigin.Begin)
Do
Dim BMP_Data(7) As Byte
Dim Text_Data(0) As Byte
bmpStream.Read(BMP_Data, 0, 8)
Dim temp_Data(7) As Byte
For k As Integer = 0 To 7
temp_Data(k) = BMP_Data(k) And 1
Next
Dim resByte As Byte = GetByteFromBit(temp_Data)
If resByte = 255 Then
Exit Do
End If
fStream.WriteByte(resByte)
Loop
Finally
If fStream IsNot Nothing Then fStream.Close()
If bmpStream IsNot Nothing Then bmpStream.Close()
End Try
End Sub
Private Function GetByteFromBit(ByVal Bits() As Byte) As Byte ’根据八个二进制位算出对应的十进制数
Dim res As Byte
For i As Integer = 0 To 7
res += Bits(7 - i) * 2 ^ i
Next
Return res
End Function
End Class
相关阅读 更多 +