Base64隱寫原理和提取腳本

一、Base64編解碼過(guò)程
??base64編碼,是把字符對(duì)應(yīng)的ascii碼轉(zhuǎn)換成8bit二進(jìn)制數(shù),把這些字符串轉(zhuǎn)換后的二進(jìn)制數(shù),通過(guò)補(bǔ)0,使得整個(gè)二進(jìn)制字符串是6的倍數(shù),可能需要補(bǔ)16個(gè)0,也可能只需要補(bǔ)8個(gè)0;再將這串長(zhǎng)度是6的倍數(shù)的二進(jìn)制字符串,每6位二進(jìn)制數(shù),按照base64的字符表,轉(zhuǎn)換為對(duì)應(yīng)的字符,末尾補(bǔ)16個(gè)0的情況,會(huì)有兩個(gè)6位全0的二進(jìn)制字符串,這兩個(gè)轉(zhuǎn)換為=;末尾補(bǔ)8個(gè)0的情況,會(huì)有一個(gè)6位全0的二進(jìn)制字符串,這一個(gè)轉(zhuǎn)換為=。

編碼前:A
轉(zhuǎn)二進(jìn)制:01000001
補(bǔ)0使長(zhǎng)度為6的倍數(shù):01000001 00000000 00000000
6bit為單位分割:010000 010000 000000 000000
base64字符表轉(zhuǎn)換:QQ==

編碼前:AB
轉(zhuǎn)二進(jìn)制:01000001 01000010
補(bǔ)0使長(zhǎng)度為6的倍數(shù):01000001 01000010 00000000
6bit為單位分割:010000 010100 001000 000000
base64字符表轉(zhuǎn)換:QUI=

base64字符表:每個(gè)字符序號(hào)的二進(jìn)制數(shù),即為該字符base64編解碼時(shí)對(duì)應(yīng)的6位二進(jìn)制數(shù);
如字符a,在字符表中排26(序號(hào)從0開始),對(duì)應(yīng)的二進(jìn)制數(shù)為011010。
b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

??base64解碼,將base64字符串的每個(gè)字符,按照base64字符表轉(zhuǎn)換為二進(jìn)制數(shù),每個(gè)等號(hào)轉(zhuǎn)換為6個(gè)0,將這個(gè)二進(jìn)制字符串,每8位二進(jìn)制數(shù),按照ascii表,轉(zhuǎn)換為對(duì)應(yīng)的字符;如果base64字符串結(jié)尾為一個(gè)等號(hào),則二進(jìn)制字符串的最后8個(gè)0,直接去掉,因?yàn)槭蔷幋a的時(shí)候補(bǔ)充的;如果base64字符串結(jié)尾為兩個(gè)等號(hào),則二進(jìn)制字符串的最后16個(gè)0,直接去掉;

二、Base64隱寫的原理
??編碼時(shí)補(bǔ)充了0增加等號(hào),解碼時(shí)去除等號(hào)并對(duì)應(yīng)刪除編碼時(shí)補(bǔ)充的0,正因?yàn)檫@一點(diǎn),使隱寫成為可能。

編碼前:A
轉(zhuǎn)二進(jìn)制:01000001
補(bǔ)0使長(zhǎng)度為6的倍數(shù):01000001 00000000 00000000
6bit為單位分割:010000 010000 000000 000000  
(第2個(gè)6位二進(jìn)制字符串010000,的后4個(gè)0,是屬于補(bǔ)位0,解碼時(shí)會(huì)被刪除)

編碼前:AB
轉(zhuǎn)二進(jìn)制:01000001 01000010
補(bǔ)0使長(zhǎng)度為6的倍數(shù):01000001 01000010 00000000
6bit為單位分割:010000 010100 001000 000000
(第3個(gè)6位二進(jìn)制字符串001000,的后2個(gè)0,是屬于補(bǔ)位0,解碼時(shí)會(huì)被刪除)

??上述所說(shuō)的補(bǔ)位0所在的位置,加入我們修改為其他二進(jìn)制數(shù),而不是默認(rèn)的全0,在做base64解碼的時(shí)候,是不會(huì)影響解碼結(jié)果的,因?yàn)檫@些補(bǔ)位0所在的位置,解碼時(shí)都會(huì)被刪除,所以不影響解碼結(jié)果。
??所以我們想要隱藏信息的話,就可以利用這些補(bǔ)位0所在的位置,base64編碼后的字符串,如果有1個(gè)等號(hào),就有兩個(gè)bit的補(bǔ)位0可隱寫,如果有2個(gè)等號(hào),就有四個(gè)bit的補(bǔ)位0可隱寫;如果沒有等號(hào),就沒有補(bǔ)位0可隱寫。

三、Base64隱寫解碼案例
??了解了base64隱寫原理,就可以對(duì)做了隱寫的base64字符串做隱寫位的提取。如以下案例,每個(gè)base64編碼有一個(gè)等號(hào),說(shuō)明每行有兩個(gè)bit的隱寫位,將每行的兩個(gè)bit隱寫隱寫位提取出來(lái),即可破解隱寫。

含有隱寫的base64編碼
YTUwZDllYTBhNTk5OWI0NmVlZmIzN2MzMDMzODlkZmR=
OTk4ODO0OmE4NWU0OTg1OTcyNjk1OzZlOWQ2ZDk5OWO=
NmZjOGJ3ZGUyODBmYmJ4ODYwZjMzZGU5NWUyZjdlNmJ=
ZDBhNDaxMzQ4NWRkZDM3a2a4ZjQwZTE0OWazM2IxMTa=
NzNlOTAzMGUwZDJwMjM3NzM0NjRmM2RhYzYxNDMxYjJ=
OTIwNzJkN2YwN2Y1Y2O0Y2Y2OjAxOTE5OGQ2NDE3NDO=
ZmIyOWIxY2Y0YTI2ZmU0Y2I2MGZiNTIzOTcxM2ZhNjT=
OWQ3NDRkOWEzNWI4NTYwYzIwYjI1ODA3Y2I5Njg4M2Q=
MjI4Z2Z3OTM0MjllMjM4NTM0NjZlNjNiZmUxZDJiZGZ=
YmQ2YjFlNjM1ZWY4YmQ4N2W0MWQ1NGIxODdkY2QwMjW=
ZmFiMTE4OTUyOTdkNjc0NmIwODAwMDdmYWE4MTFkZGU=
NDYzNGQ3NTMwNDZlMGJlNzhmNTMwM2MyMjk3ZjgwNzd=
MTUyZWNjYTViN2M5YWI1NjYzY2VlYTY1MzRxZmE0MjR=
ZGM3Yjk5YWQxNmYwMGU5MWVhYWQ4MDI1MGVlNjNjODC=
ZTc3NDg2MWZzODAwZjM1NTM3MGFlNDRjNDk0NjUxZmZ=
YTRlNjE3Y2E4ZWEwYWNkZTQ1M2QxYjM2YWFmN2U1MjD=
import re
import base64

b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

# ccc.txt為待解密的base64隱寫字符串所在的文件
f = open('ccc.txt','r')
base64str = f.readline()

# pattern2用于匹配兩個(gè)等號(hào)情況時(shí),等號(hào)前的一個(gè)字符
# pattern2用于匹配一個(gè)等號(hào)情況時(shí),等號(hào)前的一個(gè)字符
pattern2 = r'(\S)==$'
pattern1 = r'(\S)=$'

# 提取后的隱寫二進(jìn)制字符加入binstring中
binstring = ''

# 逐行讀取待解密的base64隱寫字符串,逐行處理
while(base64str):
    # 先匹配兩個(gè)等號(hào)的情況,如果匹配不上,再配置一個(gè)等號(hào)的情況
    # 如果無(wú)等號(hào),則沒有隱藏,無(wú)需處理
    if re.compile(pattern2).findall(base64str):
        # mstr為等號(hào)前的一個(gè)字符,該字符為隱寫二進(jìn)制信息所在的字符
        mstr = re.compile(pattern2).findall(base64str)[0]
        # 確認(rèn)mstr字符對(duì)應(yīng)的base64二進(jìn)制數(shù),賦值給mbin
        mbin = bin(b64chars.find(mstr))
        # mbin格式如0b100,mbin[0:2]為0b
        # mbin[2:].zfill(6)為將0b后面的二進(jìn)制數(shù)前面補(bǔ)0,使0b后面的長(zhǎng)度為6
        mbin2 = mbin[0:2] + mbin[2:].zfill(6)
        # 兩個(gè)等號(hào)情況隱寫了4位二進(jìn)制數(shù),所以提取mbin2的后4bit
        # 賦值給stegobin,這就是隱藏的二進(jìn)制信息
        stegobin = mbin2[-4:]
        binstring += stegobin
    elif re.compile(pattern1).findall(base64str):
        mstr = re.compile(pattern1).findall(base64str)[0]
        mbin = bin(b64chars.find(mstr))
        mbin2 = mbin[0:2] + mbin[2:].zfill(6)
        # 一個(gè)等號(hào)情況隱寫了2位二進(jìn)制數(shù),所以提取mbin2的后2bit
        stegobin = mbin2[-2:]
        binstring += stegobin
    base64str = f.readline()

# stegobin將各行隱藏的二進(jìn)制字符拼接在一起
# 從第0位開始,8bit、8bit處理,所以range的步進(jìn)為8
for i in range(0,len(binstring),8):
    # int(xxx,2),將二進(jìn)制字符串轉(zhuǎn)換為10進(jìn)制的整數(shù),再用chr()轉(zhuǎn)為字符
    print(chr(int(binstring[i:i+8],2)),end='')

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 部分節(jié)選自https://www.tuicool.com/articles/RRr2miE ...
    違規(guī)昵稱不予展示閱讀 11,456評(píng)論 1 10
  • base64編碼介紹 Base64是網(wǎng)絡(luò)上最常見的用于傳輸8Bit字節(jié)碼[https://baike.baidu....
    Liver_閱讀 2,189評(píng)論 0 2
  • 每個(gè)文本編輯器都有默認(rèn)的編碼方式(比如 UTF-8 編碼),當(dāng)我們保存文檔的時(shí)候,可以選擇編碼方式,如果沒有特意選...
    _于曼麗_閱讀 1,808評(píng)論 0 1
  • 官網(wǎng) 中文版本 好的網(wǎng)站 Content-type: text/htmlBASH Section: User ...
    不排版閱讀 4,718評(píng)論 0 5
  • 概述 首先,我們先來(lái)說(shuō)下什么是Base64編碼,然后再來(lái)學(xué)習(xí)下Java中Base64編碼的使用。 歷史 ??Bas...
    騎著烏龜去看海閱讀 8,496評(píng)論 5 3

友情鏈接更多精彩內(nèi)容