65.9K
CodeProject 正在变化。 阅读更多。
Home

图像的隐写术

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.45/5 (49投票s)

2007 年 5 月 14 日

4分钟阅读

viewsIcon

182210

downloadIcon

36675

使用图像进行加密文本传输

引言

我们的目标是构建一个能够将加密消息嵌入图像中进行发送和接收的简单应用程序。用户可以选择他们想要的图像,程序必须能够判断该图像是否适合隐藏文本。不允许像素变形或尺寸失真。TIF 图像可能会有轻微的尺寸增加或减少,但我们稍后会讨论这一点。用户可以为他们发送的每条消息设置不同的密码,这样管理员就可以向两个组传输同一张图像,但使用不同的密码和不同的消息。

使用代码

下面,我将嵌入文本到图像中的主过程放在这里。代码的每一步都经过注释

If MsgBox("You are about to encrypt and embed this message :[[ 
    " + TextBox1.Text + " ]] , Shall We Proceed?", MsgBoxStyle.OkCancel, 
    "Stealth") = MsgBoxResult.Cancel Then Exit Sub 
        Label2.Text = ""
If RadioButton1.Checked = False And RadioButton2.Checked = False Then
    MsgBox("Please select an extention") 
    Exit Sub
End If 

Dim text As String 
text = TextBox1.Text.ToString + " "
Dim passw As String = "" input("Enter Password To Protect Your Text", passw) 

If passw = "" Then 'err handler for ugly passwords 
    MsgBox("Error ! You Didn,t Choose Any Password To Protect The Message.")
    Exit Sub
ElseIf passw.Length < 4 Then 
    MsgBox("Error ! Password Is Too Short.") 
    Exit Sub 
End If 

Dim amount As Double = text.Length 
process_pass_with_tx(passw, text) ' this will encrypt the test by the 
' password this is done by generating a string from the password and this 
' string is tall enough to perform bit stream xor operation on all chares 
' included in the message text that we want to send. we secured the text,
' now we will try hide the encrypted text in the image.

TextBox1.Text = text 
If RadioButton1.Checked = True Then GoTo mode2 ''started deferences 
between tow modes here 

If Me.OpenFileDialog1.ShowDialog = DialogResult.Cancel Then
    Exit Sub
Else 'err handler to prevent wrong extensions 
    Dim infoReader As System.IO.FileInfo 
    infoReader = My.Computer.FileSystem.GetFileInfo(
        Me.OpenFileDialog1.FileName)
If infoReader.Extension.Substring(1, 3).ToLower <> (
    RadioButton2.Text.ToLower) Then
    MsgBox("Error : Encryption mode requires different extension ")
    Exit Sub 
End If

LoadNewPict(Me.OpenFileDialog1.FileName) 'display the selected image preview 

If PictureBox1.Image.Size.Width < 64 Or PictureBox1.Image.Size.Height < 
    64 Then 
' prevent user from using unproperiate images 
    MsgBox("Error! Tiny Images Cann,t Be Used In Steganography.") 
    Exit Sub
End If

Dim w1 As Integer = PictureBox1.Image.Size.Width - 1
Dim w2 As Integer = PictureBox1.Image.Size.Height - 1 
Dim possible_size As Double = ((w1 - 7) * (w2 - 7)) / 8 ' 8 bits make one 
' char, and avoid edges 
If possible_size < amount Then ' determine if the image is not big enough 
' for text
    MsgBox("This image is not big enough to carry your message", 
        MsgBoxStyle.Critical)
    Exit Sub
End If
End If ' file dialog if 
' load accurding to extention 
Dim dib, val, reslt As Integer
dib = FreeImage.FreeImage_Load(FreeImage.FREE_IMAGE_FORMAT.FIF_TIFF, 
    OpenFileDialog1.FileName, 0) 
On Error GoTo rongex1
Dim ba As bits_array 
ba.Initialize() 
Dim sz As Long
Dim sz1, sz2, sz3, sz4 As Byte
Dim t As Double sz = text.Length ' number of chars to encrypt 
    
sz1 = Decimal.Remainder(sz, 100) ' take the lowest 2 digits of it
t = sz / 100 'take the left numbers (all except lowest 2 digits) 
sz = Decimal.Truncate(t) ' set size_variable to hold left numbers (all except
' lowest 2 digits)
sz2 = Decimal.Remainder(sz, 100) ' repeat 
t = sz / 100 
sz = Decimal.Truncate(t) 
sz3 = Decimal.Remainder(sz, 100) ' ' repeat

t = sz / 100 
sz = Decimal.Truncate(t) 
sz4 = Decimal.Remainder(sz, 100) ' will take final 2 digits, now you can 
' see: the maximum size of text is ( 99 99 99 99 ) 
 
' now we will convert sz1 to bits array and stor it in the first line of the 
' picture after it we will do the sz2 and then sz3 and then sz4.. 
' the coming 4 for loops are used for that 
Dim i, j, m 
i = 0 
j = 1 
ba.Initialize()
byte_to_bits(sz1, ba)
For m = 0 To 7 '''''''''''''''''' 1 
    i = i + 1 
    FreeImage.FreeImage_GetPixelColor(dib, i, j, val) 
    ' set the lowest bit according to my bit
    If odd(val) = True Then
        If ba.bits(m) = False Then 'bit is zero 
            FreeImage.FreeImage_SetPixelColor(dib, i, j, (val + 1))
        End If 
    End If 
    If odd(val) = False Then 
        If ba.bits(m) = True Then 'bit is one 
            FreeImage.FreeImage_SetPixelColor(dib, i, j, (val + 1))
        End If 
    End If 
Next m
ba.Initialize() 
byte_to_bits(sz2, ba) 
For m = 0 To 7 '''''''''''''''''''''' 2 
    i = i + 1 
    FreeImage.FreeImage_GetPixelColor(dib, i, j, val) 
    If odd(val) = True Then
        If ba.bits(m) = False Then 'bit is zero 
            FreeImage.FreeImage_SetPixelColor(dib, i, j, val + 1)
        End If
    End If 
    If odd(val) = False Then 
        If ba.bits(m) = True Then 'bit is one
            FreeImage.FreeImage_SetPixelColor(dib, i, j, val + 1) 
        End If 
    End If 
Next m
ba.Initialize()
byte_to_bits(sz3, ba)
For m = 0 To 7 '''''''''''''''''''''''''''' 3 
    i = i + 1
    FreeImage.FreeImage_GetPixelColor(dib, i, j, val)
    If odd(val) = True Then
        If ba.bits(m) = False Then 'bit is zero 
            FreeImage.FreeImage_SetPixelColor(dib, i, j, val + 1) 
        End If 
    End If 
    If odd(val) = False Then
        If ba.bits(m) = True Then 'bit is one
            FreeImage.FreeImage_SetPixelColor(dib, i, j, val + 1)
        End If 
    End If 
Next m 
ba.Initialize() 
byte_to_bits(sz4, ba)
For m = 0 To 7 ''''''''''''''''''''''''''''' 4 
    i = i + 1 
    FreeImage.FreeImage_GetPixelColor(dib, i, j, val)
    If odd(val) = True Then 
        If ba.bits(m) = False Then 'bit is zero 
            FreeImage.FreeImage_SetPixelColor(dib, i, j, val + 1) 
        End If
    End If 
    If odd(val) = False Then
        If ba.bits(m) = True Then 'bit is one 
            FreeImage.FreeImage_SetPixelColor(dib, i, j, val + 1) 
        End If
    End If 
Next m '''' we have just stored the size of the text 

Dim n As Byte
Dim count As Long 
count = 0 'i already set size ===>>> first line for size 
' Now i will scan the picture from the second line 

For j = 2 To PictureBox1.Image.Size.Height Step 1
    i = 1 
    Do While (i + 7) < PictureBox1.Image.Size.Width ' Step 8 ' may use 
    ' freeimage_getdotspermeterx 
        n = Asc(CChar(text.Substring(count, 1))) ' this give ascii code for 
        ' the every text letter, to reverse it use chr() function
        count = count + 1 
        If count = text.Length Then GoTo out 
            ba.Initialize()
            byte_to_bits(n, ba) ''''''''''' 
        For m = 0 To 7 
            FreeImage.FreeImage_GetPixelColor(dib, i, j, val) 
            ' change it according to my bit
            If odd(val) = True Then 
                If ba.bits(m) = False Then 'bit is zero 
                    FreeImage.FreeImage_SetPixelColor(dib, i, j, val + 1) 
                End If
            End If 
            If odd(val) = False Then 
                If ba.bits(m) = True Then 'bit is one 
                    FreeImage.FreeImage_SetPixelColor(dib, i, j, val + 1)
                End If 
            End If 
            i = i + 1
         Next m 
         i = i + 8 
    Loop 
Next j 
out:
Dim fn As String 
Dim con As Integer = 0 
fn = OpenFileDialog1.FileName + "_stealth.tif" 
up1: 
If File.Exists(fn) = False Then
    FreeImage.FreeImage_Save(FreeImage.FREE_IMAGE_FORMAT.FIF_TIFF, 
        dib, fn, &H800S) 
Else 
    con = con + 1 
    MsgBox("FILE: " + fn + " ALREADY EXISTS ,WE WILL CHANGE THE NAME TO " + 
        OpenFileDialog1.FileName + con.ToString + "_stealth.tif") 
    fn = OpenFileDialog1.FileName + con.ToString + "_stealth.tif" 
    GoTo up1
End If 
Label2.Text = fn
Exit Sub 
mode2: '
' in mode2 we will treat the file with the deferent extension in the same 
way, just change the lib calls according to the extension 
' to decrypt the message we will reverse what we have done 

关注点

您必须将 freeimage.dll 放在与 EXE 相同的路径下才能使其工作。这已经为您完成。输出图像的名称将与输入图像相同,并在末尾加上 "_stealth";如果输出文件已存在,程序将处理这种情况。文本框控件的最大字符数有限制;如果您的文本超出此限制,请尝试将其分开,并为每个部分使用一张图像。有损压缩算法会损坏图像中的加密数据,因此不建议在传输前压缩输出图像。

您可能会注意到某些图像的尺寸发生了一些变化。与总文件大小相比,这种变化很可能被忽略。这可能是因为生成您提供给程序的原始图像的压缩算法与我的 DLL 库中生成输出图像的压缩算法不同,而不是因为嵌入的数据增加了尺寸。证据是:在您运行程序之前,编写一个小型程序并使用我代码中使用的相同函数将您的图像另存为具有相同扩展名的不同名称。假设这个新图像称为 beta。现在运行程序并使用它来嵌入一些文本。看到输出图像了吗?它的尺寸与 beta 图像完全相同。

您可以使用任何您信任的加密算法,例如公钥/私钥、ElGamal 等。我们的隐写术方式独立于图像的比特采样(每像素比特数),但强烈建议与 24 bpp 或更高的图像一起使用。这将保证防止像素变形。大多数网络图像都采样为 24 bpp。

请注意,我的密钥生成方式很弱,因为我只是重复了密钥。如果密钥中的任何字符被发现,那么用它加密的所有消息字符也会被发现。您应该使用良好的函数来生成一个大字符串来进行 XOR,或者使用更好的密码。您也可以通过在应用程序的某个地方使用背景图像来设置版权文本,从而使用此程序进行身份验证。

低位比特(本程序)不适用于 JPEG,因为它们使用有损压缩算法。因此,处理 JPEG 需要额外的工作。您可以获取图像的红/绿/蓝通道并执行相同的操作。您可以使用它来获取直方图近似于水平线的通道,然后像这样将新图像分割成小方块

1 1 1
1 x 1
1 1 1

在中心像素 x,如果得到位 1,则放置一个大于所有邻居的值。如果得到位 0,则放置一个小于所有邻居的值。现在,这里可以容纳数据的可能大小除以 9。这种方法有时可能会导致轻微失真,因为它作用于高位比特。我们只能使用值大于适当阈值的小方块。或者,像这样将图像分割成小方块

X Y
Y X

如果 X 的像素持有相同的值,则该方块代表 1,Y 的像素必须更改为不同的值。如果 Y 的像素持有相同的值,则该方块代表 0,X 的像素必须更改为不同的值。现在当我们接收时,如果 X 的像素和 Y 的像素不同或两者都相同,那么有人动过这张图像,这个比特是无效的。我们可以将此应用于多个通道,因此如果一个通道损坏,我们将使用备份。最后 2 种算法:Alaa Jebran © 2007。

您可能不会惊讶地发现,像 CIA、NSA 等一些大型机构会使用名人网站或色情网站来发送和接收加密消息,这些消息使用的就是类似的技术。

历史

  • 2007 年 5 月 14 日 -- 发布原始版本
  • 2007 年 6 月 25 日 -- 文章编辑并移至 CodeProject.com 文章库
© . All rights reserved.