介紹
GnuPG包提供用於生成和存儲加密密鑰的完整解決方案。它還允許您加密和簽名數據和通信。
在本教程中,您將創建一系列使用Python 3和python-gnupg模塊的腳本。這些腳本允許您對多個文件進行簽名和加密,並在運行腳本之前驗證腳本的完整性。
准備
在繼續本教程之前,請完成以下條件:
- Ubuntu 16.04服務器,擁有sudo權限的非root用戶。在本教程中,我們的用戶將被命名為sammy。
- 確保您已安裝Python 3和pip,安裝教程詳見鏈接。
- 創建GnuPG密鑰對。
第1步 - 檢索密鑰對信息
brew install gnupg
sudo pip3 install python-gnupg
接收到公鑰后,在命令行輸入“gpg --import ytyzx2014gpgpublickey.txt”導入公鑰。
完成准備中的GnuPG教程后,您將在主目錄下的.gnupg
存儲密鑰對。GnuPG使用用戶名和電子郵件存儲密鑰,以幫助識別密鑰對。在此示例中,我們的用戶名是sammy,我們的電子郵件地址是sammy@example.com
。
運行以下命令以獲取可用密鑰的列表:
$ gpg --list-keys
/home/sammy/.gnupg/pubring.gpg ----------------------------- pub 2048R/4920B23F 2018-04-23 uid Sammy <sammy@example.com> sub 2048R/50C06279 2018-04-23
記下uid
輸出行中顯示的電子郵件地址。稍后您將需要它來識別您的密鑰。
第2步 - 安裝Python-GnuPG和簽名文件
使用您的密鑰,您可以安裝python-gnupg
模塊,該模塊充當GnuPG的包裝器,以實現GnuPG和Python 3之間的交互。使用此模塊,您將能夠創建執行以下操作的Python腳本:
- 為文件創建分離的簽名,通過從文件中分離簽名,為簽名過程添加一層安全性。
- 加密文件。
- 解密文件。
- 驗證分離的簽名和腳本。
在繼續測試這些文件上的腳本之前,您將首先創建腳本以及一些測試文件。
首先,讓我們安裝python-gnupg
模塊以及fs
包,這將允許您打開,讀取和編寫測試文件。更新包索引,並使用pip
命令安裝這些包:
$ sudo apt-get update $ sudo pip3 install python-gnupg fs
有了這些軟件包,我們就可以繼續創建腳本和測試文件。
要存儲腳本和測試文件,請在主目錄中創建一個名為python-test
的文件夾:
$ cd ~/ $ mkdir python-test
移至此目錄:
$ cd python-test/
接下來,讓我們創建三個測試文件:
$ echo "This is the first test file" > test1.txt $ echo "print('This test file is a Python script')" > test2.py $ echo "This is the last test file" > test3.txt
要為我們的測試文件創建分離的簽名,讓我們創建一個名為signdetach.py
的腳本,該腳本將定位執行它的目錄中的所有文件。簽名充當時間戳並證明文檔的真實性。
分離的簽名將存儲在一個名為signatures/
的新文件夾中,該文件夾將在腳本運行時創建。
用nano
打開signdetach.py
新文件:
nano signdetach.py
讓我們首先導入腳本所需的所有模塊。這些包括啟用文件導航的os
和fs
包,以及gnupg
:
~/python-test/signdetach.py
#!/usr/bin/env python3 import os import fs from fs import open_fs import gnupg
現在讓我們設置GnuPG的加密密鑰的目錄。GnuPG默認存儲其密鑰在.gnupg
上,所以讓我們用我們的用戶名配置它。請務必使用非root用戶的名稱替換sammy:
~/python-test/signdetach.py
... gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg")
接下來,讓我們創建一個home_fs
變量來將當前目錄位置存儲為文件對象。這將使腳本可以在執行它的目錄中工作:
~/python-test/signdetach.py
... home_fs = open_fs(".")
到現在為止,您的腳本將如下所示:
~/python-test/signdetach.py
#!/usr/bin/env python3 import os import fs from fs import open_fs import gnupg gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg") home_fs = open_fs(".")
此配置塊是您在本教程中使用時將在腳本中使用的基本模板。
接下來,添加代碼以檢查是否存在已命名signatures/
的文件夾,如果該文件夾不存在則創建它:
~/python-test/signdetach.py
... if os.path.exists("signatures/"): print("Signatures directory already created") else: home_fs.makedir(u"signatures") print("Created signatures directory")
創建一個空數組以存儲文件名,然后掃描當前目錄,將所有文件名附加到files_dir
數組:
~/python-test/signdetach.py
... files_dir = [] files = [f for f in os.listdir(".") if os.path.isfile(f)] for f in files: files_dir.append(f)
腳本將要做的下一件事是為文件生成分離的簽名。循環遍歷files_dir
數組將使用密鑰環上的第一個私鑰為每個文件創建簽名。要訪問私鑰,您需要使用您設置的密碼解鎖。替換"my passphrase"
為在准備項中生成密鑰對時使用的密碼:
~/python-test/signdetach.py
... for x in files_dir: with open(x, "rb") as f: stream = gpg.sign_file(f,passphrase="my passphrase",detach = True, output=files_dir[files_dir.index(x)]+".sig") os.rename(files_dir[files_dir.index(x)]+".sig", "signatures/"+files_dir[files_dir.index(x)]+".sig") print(x+" ", stream.status)
完成后,所有簽名都將移動到該signatures/
文件夾。您完成的腳本將如下所示:
~/python-test/signdetach.py
#!/usr/bin/env python3 import os import fs from fs import open_fs import gnupg gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg") home_fs = open_fs(".") if os.path.exists("signatures/"): print("Signatures directory already created") else: home_fs.makedir(u"signatures") print("Created signatures directory") files_dir = [] files = [f for f in os.listdir(".") if os.path.isfile(f)] for f in files: files_dir.append(f) for x in files_dir: with open(x, "rb") as f: stream = gpg.sign_file(f,passphrase="my passphrase",detach = True, output=files_dir[files_dir.index(x)]+".sig") os.rename(files_dir[files_dir.index(x)]+".sig", "signatures/"+files_dir[files_dir.index(x)]+".sig") print(x+" ", stream.status)
現在我們可以繼續加密文件了。
第3步 - 加密文件
在文件夾中執行加密腳本將導致該文件夾中的所有文件在名為encrypted/
的新文件夾中被復制和加密。用於加密文件的公鑰是與您在密鑰對配置中指定的電子郵件相對應的公鑰。
打開一個名為encryptfiles.py
的新文件:
$ nano encryptfiles.py
首先,導入所有必需的模塊,設置GnuPG的主目錄,並創建當前的工作目錄變量:
~/python-test/encryptfiles.py
#!/usr/bin/env python3 import os import fs from fs import open_fs import gnupg gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg") home_fs = open_fs(".")
接下來,讓我們添加代碼來檢查當前目錄是否已經有一個名為encrypted/
的文件夾,如果它不存在則創建它:
~/python-test/encryptfiles.py
... if os.path.exists("encrypted/"): print("Encrypt directory exists") else: home_fs.makedir(u"encrypted") print("Created encrypted directory")
在搜索要加密的文件之前,讓我們創建一個空數組來存儲文件名:
~/python-test/encryptfiles.py
... files_dir = []
接下來,創建一個循環來掃描文件夾中的文件並將它們附加到數組:
~/python-test/encryptfiles.py
... files = [f for f in os.listdir(".") if os.path.isfile(f)] for f in files: files_dir.append(f)
最后,讓我們創建一個循環來加密文件夾中的所有文件。完成后,所有加密文件都將傳輸到該encrypted/
文件夾。在此示例中sammy\@example.com
是加密期間要使用的密鑰的電子郵件ID。請務必將其替換為您在步驟1中記下的電子郵件地址:
~/python-test/encryptfiles.py
... for x in files_dir: with open(x, "rb") as f: status = gpg.encrypt_file(f,recipients=["sammy@example.com"],output= files_dir[files_dir.index(x)]+".gpg") print("ok: ", status.ok) print("status: ", status.status) print("stderr: ", status.stderr) os.rename(files_dir[files_dir.index(x)] + ".gpg", 'encrypted/' +files_dir[files_dir.index(x)] + ".gpg")
如果您的.gnupg
文件夾中存儲了多個密鑰,並且希望使用特定的公鑰或多個公鑰進行加密,則需要在recipients
里通過添加其他收件人或替換當前的收件人來修改陣列。
完成后,您的encryptfiles.py
腳本文件將如下所示:
~/python-test/encryptfiles.py
#!/usr/bin/env python3 import os import fs from fs import open_fs import gnupg gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg") home_fs = open_fs(".") if os.path.exists("encrypted/"): print("Encrypt directory exists") else: home_fs.makedir(u"encrypted") print("Created encrypted directory") files_dir = [] files = [f for f in os.listdir(".") if os.path.isfile(f)] for f in files: files_dir.append(f) for x in files_dir: with open(x, "rb") as f: status = gpg.encrypt_file(f,recipients=["sammy@example.com"],output= files_dir[files_dir.index(x)]+".gpg") print("ok: ", status.ok) print("status: ", status.status) print("stderr: ", status.stderr) os.rename(files_dir[files_dir.index(x)] + ".gpg", "encrypted/" +files_dir[files_dir.index(x)] + ".gpg")
現在讓我們看一下該過程的第二部分:一次解密和驗證多個文件。
第4步 - 解密文件
解密腳本與加密腳本的工作原理大致相同,只是它要在encrypted/
目錄中執行。啟動時,decryptfiles.py
將首先識別使用的公鑰,然后在.gnupg
文件夾中搜索相應的私鑰以解密文件。解密的文件將存儲在一個名為decrypted/
的新文件夾中。
打開一個名為decryptfiles.py
的新文件:
$ nano decryptfiles.py
首先插入配置設置:
~/python-test/decryptfiles.py
#!/usr/bin/env python3 import os import fs from fs import open_fs import gnupg gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg") home_fs = open_fs(".")
接下來,創建兩個空數組以在腳本執行期間存儲數據:
~/python-test/decryptfiles.py
... files_dir = [] files_dir_clean = []
這里的目標是讓腳本將解密后的文件放入自己的文件夾中;否則,加密和解密的文件將混合,難以找到特定的解密文件。要解決此問題,您可以添加將掃描當前文件夾以查看decrypted/文件夾是否存在的代碼,如果不存在,則創建該文件夾:
~/python-test/decryptfiles.py
... if os.path.exists("decrypted/"): print("Decrypted directory already exists") else: home_fs.makedir(u"decrypted/") print("Created decrypted directory")
掃描文件夾並將所有文件名附加到files_dir
數組:
~/python-test/decryptfiles.py
... files = [f for f in os.listdir(".") if os.path.isfile(f)] for f in files: files_dir.append(f)
所有加密文件都將以.gpg
擴展名添加到其文件名中,表明它們已加密。但是,在解密它們時,我們希望在沒有此擴展名的情況下保存它們,因為它們不再加密。
為此,循環遍歷files_dir
數組並從每個文件名中刪除.gpg
擴展名:
~/python-test/decryptfiles.py
... for x in files_dir: length = len(x) endLoc = length - 4 clean_file = x[0:endLoc] files_dir_clean.append(clean_file)
新的“清理”文件名存儲在file_dir_clean
數組中。
接下來,讓我們遍歷文件並解密它們。替換"my passphrase"
為您的密碼以解鎖私鑰:
... for x in files_dir: with open(x, "rb") as f: status = gpg.decrypt_file(f, passphrase="my passphrase",output=files_dir_clean[files_dir.index(x)]) print("ok: ", status.ok) print("status: ", status.status) print("stderr: ", status.stderr) os.rename(files_dir_clean[files_dir.index(x)], "decrypted/" + files_dir_clean[files_dir.index(x)])
完成后,您的腳本文件將如下所示:
~/python-test/decryptfiles.py
#!/usr/bin/env python3 import os import fs from fs import open_fs import gnupg gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg") home_fs = open_fs(".") files_dir = [] files_dir_clean = [] if os.path.exists("decrypted/"): print("Decrypted directory already exists") else: home_fs.makedir(u"decrypted/") print("Created decrypted directory") files = [f for f in os.listdir(".") if os.path.isfile(f)] for f in files: files_dir.append(f) for x in files_dir: length = len(x) endLoc = length - 4 clean_file = x[0:endLoc] files_dir_clean.append(clean_file) for x in files_dir: with open(x, "rb") as f: status = gpg.decrypt_file(f, passphrase="my passphrase",output=files_dir_clean[files_dir.index(x)]) print("ok: ", status.ok) print("status: ", status.status) print("stderr: ", status.stderr) os.rename(files_dir_clean[files_dir.index(x)], "decrypted/" + files_dir_clean[files_dir.index(x)])
使用我們的解密腳本,我們可以繼續驗證多個文件的分離簽名。
第5步 - 驗證分離的簽名
要驗證多個文件的分離數字簽名,讓我們編寫一個verifydetach.py
腳本。此腳本將搜索signatures/
工作目錄中的文件夾,並使用其簽名驗證每個文件。
打開一個名為verifydetach.py
的新文件:
$ nano verifydetach.py
導入所有必需的庫,設置工作和主目錄,並創建空files_dir數組,如前面的示例所示:
~/python-test/verifydetach.py
#!/usr/bin/env python3 import os import fs from fs import open_fs import gnupg gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg") home_fs = open_fs(".") files_dir = []
接下來,讓我們掃描包含我們要驗證的文件的文件夾。文件名將附加到空files_dir
數組:
~/python-test/verifydetach.py
... files = [f for f in os.listdir(".") if os.path.isfile(f)] for f in files: files_dir.append(f)
最后,讓我們使用一個遍歷files_dir
數組的循環來驗證每個文件是否有自己的分離簽名,以搜索文件signatures/
夾中每個文件的分離簽名。當它找到分離的簽名時,它將使用它驗證文件。最后一行打印出每個文件驗證的狀態:
~/python-test/verifydetach.py
... for i in files_dir: with open("../../signatures/" + i + ".sig", "rb") as f: verify = gpg.verify_file(f, i) print(i + " ", verify.status)
完成后,您的腳本將如下所示:
~/python-test/verifydetach.py
#!/usr/bin/env python3 import os import fs from fs import open_fs import gnupg gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg") home_fs = open_fs(".") files_dir = [] files = [f for f in os.listdir(".") if os.path.isfile(f)] for f in files: files_dir.append(f) for i in files_dir: with open("../../signatures/" + i + ".sig", "rb") as f: verify = gpg.verify_file(f, i) print(i + " ", verify.status)
接下來,讓我們來看看如何在服務器執行文件之前驗證文件的簽名。
第6步 - 驗證文件
最終腳本將在執行之前對其進行驗證。從這個意義上講,它類似於verifydetach
,但它具有啟動已驗證腳本的附加功能。它的工作原理是將腳本的名稱作為參數,然后驗證該文件的簽名。如果驗證成功,腳本將向控制台發送消息並啟動已驗證的腳本。如果驗證過程失敗,腳本會將錯誤信息發布到控制台並中止文件執行。
創建一個名為verifyfile.py
的新文件:
$ nano verifyfile.py
讓我們首先導入必要的庫並設置工作目錄:
~/python-test/verifyfile.py
#!/usr/bin/env python3 import os import fs from fs import open_fs import gnupg gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg") home_fs = open_fs(".")
要使腳本正常工作,必須存儲要驗證和執行的文件名。為此,讓我們創建一個名為script_to_run
的新變量:
~/python-test/verifyfile.py
... script_to_run = str(sys.argv[1])
此變量獲取第一個參數並將其存儲在新創建的變量中。接下來,腳本將打開分離的簽名文件,使用其簽名驗證script_to_run
中的文件,然后在通過驗證時執行:
~/python-test/verifyfile.py
... with open("../../signatures/" + script_to_run + ".sig", "rb") as f: verify = gpg.verify_file(f, script_to_run) print(script_to_run + " ", verify.status) if verify.status == "signature valid": print("Signature valid, launching script...") exec(open(script_to_run).read()) else: print("Signature invalid or missing, ") print("aborting script execution")
完成的腳本將如下所示:
~/python-test/verifyfile.py
#!/usr/bin/env python3 import os import sys import fs from fs import open_fs import gnupg gpg = gnupg.GPG(gnupghome="/home/sammy/.gnupg") home_fs = open_fs(".") script_to_run = str(sys.argv[1]) with open("../../signatures/" + script_to_run + ".sig", "rb") as f: verify = gpg.verify_file(f, script_to_run) print(script_to_run + " ", verify.status) if verify.status == "signature valid": print("Signature valid, launching script...") exec(open(script_to_run).read()) else: print("Signature invalid or missing, ") print("aborting script execution")
我們已經完成了腳本的創建,但目前它們只能從當前文件夾中啟動。在下一步中,我們將修改其權限以使其可全局訪問。
第7步 - 使腳本在系統范圍內可用
為了便於讓我們從系統上的任何目錄或文件夾中執行腳本,並將它們放在我們的$PATH
中。使用該chmod
命令為非root用戶提供文件所有者的可執行權限:
$ chmod +x *.py
現在要查找您的PATH
置,請運行以下命令:
$ echo $PATH
-bash: /home/sammy/bin:/home/sammy/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
如果目錄的權限允許,存儲在您的$PATH
中的文件可以從系統中的任何文件夾訪問。您可以將腳本放在您的$PATH
中的任何位置,但是現在讓我們將腳本從python-test/
目錄移動到/usr/local/bin/
。
請注意,我們在復制文件時刪除擴展名.py
。如果看一下我們創建的腳本的第一行,會看到#!usr/bin/env python3
。這行稱為shebang,它有助於操作系統識別執行代碼時使用的bash解釋器或環境。當我們執行腳本時,操作系統會注意到我們將Python指定為我們的環境,並將代碼傳遞給Python執行。這意味着我們不再需要文件擴展名來幫助確定我們想要使用的環境:
$ sudo mv encryptfiles.py /usr/local/bin/encryptfiles $ sudo mv decryptfiles.py /usr/local/bin/decryptfiles $ sudo mv signdetach.py /usr/local/bin/signdetach $ sudo mv verifyfile.py /usr/local/bin/verifyfile $ sudo mv verifydetach.py /usr/local/bin/verifydetach
現在,只需運行腳本名稱以及腳本可能從命令行獲取的任何參數,就可以在系統中的任何位置執行腳本。在下一步中,我們將介紹如何使用這些腳本的一些示例。
第8步 - 測試腳本
現在我們已經將腳本移動到了我們的$PATH
,我們可以從服務器上的任何文件夾運行它們。
首先,使用pwd
命令檢查您是否仍在python-test
目錄中工作:
$ pwd
輸出應該是:
/home/sammy/python-test
您在本教程前面創建了三個測試文件。運行該ls -l
命令以列出文件夾中的文件:
$ ls -l
您應該看到文件python-test
夾中存儲了三個文件:
-rw-rw-r-- 1 sammy sammy 15 Apr 15 10:08 test1.txt -rwxrwxr-x 1 sammy sammy 15 Apr 15 10:08 test2.py -rw-rw-r-- 1 sammy sammy 15 Apr 15 10:08 test3.txt
我們將測試這三個文件的腳本。您可以使用cat命令在加密前快速顯示文件的內容,如下所示:
$ cat test1.txt
This is the first test file
讓我們首先為所有文件創建分離簽名。為此,請從當前文件夾中執行signdetach
腳本:
$ signdetach
Created signatures directory test2.py signature created test1.txt signature created test3.txt signature created
請注意,在輸出中,腳本檢測到signatures/
目錄不存在,所以之后創建了它。然后它也創建了文件簽名。
我們可以通過ls -l
再次運行命令來確認:
$ ls -l
total 16 drwxrwxr-x 2 sammy sammy 4096 Apr 21 14:11 signatures -rw-rw-r-- 1 sammy sammy 15 Apr 15 10:08 test1.txt -rwxrwxr-x 1 sammy sammy 15 Apr 15 10:08 test2.py -rw-rw-r-- 1 sammy sammy 15 Apr 15 10:08 test3.txt
注意列表之間的新signatures
目錄。讓我們列出這個文件夾的內容,並仔細查看其中一個簽名。
要列出所有簽名,請鍵入:
$ ls -l signatures/
total 12 -rw-rw-r-- 1 sammy sammy 473 Apr 21 14:11 test1.txt.sig -rw-rw-r-- 1 sammy sammy 473 Apr 21 14:11 test2.py.sig -rw-rw-r-- 1 sammy sammy 473 Apr 21 14:11 test3.txt.sig
.sig
擴展可以識別分離的簽名文件。同樣,該cat命令可以顯示這些簽名的內容。我們來看看test1.txt.sig
簽名的內容:
$ cat signatures/test1.txt.sig
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJa20aGAAoJENVtx+Y8cX3mMhMH+gOZsLJX3aEgUPZzDlKRWYec AyrXEGp5yIABj7eoLDKGUxftwGt+c4HZud1iEUy8AhtW/Ea6eRlMFPTso2hb9+cw /MyffTrWGpa0AGjNvf4wbxdq7TNpAlw4nmcwKpeYqkUu2fP3c18oZ3G3R3+P781w GWori9FK3eTyVPs9E0dVgdo7S8G1pF/ECo8Cl4Mrj80rERAitQAMbSaN/dF0wUKu okRZPJPVjd6GwqRRkXoqwh0vm4c+p3nAhFV+v7uK2BOUIJKPFbbn58vmmn+LVaBS MFWSb+X85KwwftIezqCV/hqsMKAuhkvfIi+YQFCDXElJMtjPBxxuvZFjQFjEHe8= =4NB5 -----END PGP SIGNATURE-----
此輸出是test1.txt
分離的簽名。
有了簽名,就可以繼續加密我們的文件。為此,請執行以下encryptfiles
腳本:
$ encryptfiles
Created encrypted directory ok: True status: encryption ok stderr: [GNUPG:] BEGIN_ENCRYPTION 2 9 [GNUPG:] END_ENCRYPTION ok: True status: encryption ok stderr: [GNUPG:] BEGIN_ENCRYPTION 2 9 [GNUPG:] END_ENCRYPTION ok: True status: encryption ok stderr: [GNUPG:] BEGIN_ENCRYPTION 2 9 [GNUPG:] END_ENCRYPTION
從輸出中,注意腳本創建了encrypted/
文件夾。另請注意,所有文件都已成功加密。再次運行`ls -l命令並注意目錄中的新文件夾:
$ ls -l
total 20 drwxrwxr-x 2 sammy sammy 4096 Apr 21 14:42 encrypted drwxrwxr-x 2 sammy sammy 4096 Apr 21 14:11 signatures -rw-rw-r-- 1 sammy sammy 15 Apr 15 10:08 test1.txt -rw-rw-r-- 1 sammy sammy 15 Apr 15 10:08 test2.py -rw-rw-r-- 1 sammy sammy 15 Apr 15 10:08 test3.txt
讓我們看看test1.txt
現在是如何加密的:
$ cat encrypted/test1.txt.gpg
-----BEGIN PGP MESSAGE----- Version: GnuPG v1 hQEMA9Vtx+Y8cX3mAQf9FijeaCOKFRUWOrwOkUw7efvr5uQbSnxxbE/Dkv0y0w8S Y2IxQPv4xS6VrjhZQC6K2R968ZQDvd+XkStKfy6NJLsfKZM+vMIWiZmqJmKxY2OT 8MG/b9bnNCORRI8Nm9etScSYcRu4eqN7AeUdWOXAFX+mo7K00IdEQH+0Ivyc+P1d 53WBgWstt8jHY2cn1sLdoHh4m70O7v1rnkHOvrQW3AAsBbKzvdzxOa0/5IKGCOYF yC8lEYfOihyEetsasx0aDDXqrMZVviH3KZ8vEiH2n7hDgC5imgJTx5kpC17xJZ4z LyEiNPu7foWgVZyPzD2jGPvjW8GVIeMgB+jXsAfvEdJJAQqX6qcHbf1SPSRPJ2jU GX5M/KhdQmBcO9Sih9IQthHDXpSbSVw/UejheVfaw4i1OX4aaOhNJlnPSUDtlcl4 AUoBjuBpQMp4RQ== =xJST -----END PGP MESSAGE-----
存儲在原始文件中的句子已被轉換為復雜的字符和數字系列。
現在文件已經過簽名和加密,可以刪除原件並從加密文件中恢復原始郵件。
要刪除原件,請鍵入:
$ rm *.txt *.py
再次運行ls -l
命令以確保已刪除所有原始文件:
$ ls -l
total 8 drwxrwxr-x 2 sammy sammy 4096 Apr 21 14:42 encrypted drwxrwxr-x 2 sammy sammy 4096 Apr 21 14:11 signatures
原始文件刪除后,讓我們解密並驗證加密文件。切換到encrypted
文件夾並列出所有文件:
cd encrypted/ && ls -l
total 12 -rw-rw-r-- 1 sammy sammy 551 Apr 21 14:42 test1.txt.gpg -rw-rw-r-- 1 sammy sammy 551 Apr 21 14:42 test2.py.gpg -rw-rw-r-- 1 sammy sammy 551 Apr 21 14:42 test3.txt.gpg
要解密文件,請從當前文件夾中運行decryptfiles
腳本:
$ decryptfiles
OutputCreated decrypted directory ok: True status: decryption ok stderr: [GNUPG:] ENC_TO D56DC7E63C717DE6 1 0 [GNUPG:] USERID_HINT D56DC7E63C717DE6 Autogenerated Key \<sammy\@example.com\> [GNUPG:] NEED_PASSPHRASE D56DC7E63C717DE6 D56DC7E63C717DE6 1 0 [GNUPG:] GOOD_PASSPHRASE gpg: encrypted with 2048-bit RSA key, ID 3C717DE6, created 2018-04-15 "Autogenerated Key \<sammy\@example.com\>" [GNUPG:] BEGIN_DECRYPTION [GNUPG:] DECRYPTION_INFO 2 9 [GNUPG:] PLAINTEXT 62 1524321773 [GNUPG:] PLAINTEXT_LENGTH 15 [GNUPG:] DECRYPTION_OKAY [GNUPG:] GOODMDC [GNUPG:] END_DECRYPTION ok: True status: decryption ok stderr: [GNUPG:] ENC_TO D56DC7E63C717DE6 1 0 [GNUPG:] USERID_HINT D56DC7E63C717DE6 Autogenerated Key \<sammy\@example.com\> [GNUPG:] NEED_PASSPHRASE D56DC7E63C717DE6 D56DC7E63C717DE6 1 0 [GNUPG:] GOOD_PASSPHRASE gpg: encrypted with 2048-bit RSA key, ID 3C717DE6, created 2018-04-15 "Autogenerated Key \<sammy\@example.com\>" [GNUPG:] BEGIN_DECRYPTION [GNUPG:] DECRYPTION_INFO 2 9 [GNUPG:] PLAINTEXT 62 1524321773 [GNUPG:] PLAINTEXT_LENGTH 15 [GNUPG:] DECRYPTION_OKAY [GNUPG:] GOODMDC [GNUPG:] END_DECRYPTION ok: True status: decryption ok stderr: [GNUPG:] ENC_TO D56DC7E63C717DE6 1 0 [GNUPG:] USERID_HINT D56DC7E63C717DE6 Autogenerated Key \<sammy\@example.com\> [GNUPG:] NEED_PASSPHRASE D56DC7E63C717DE6 D56DC7E63C717DE6 1 0 [GNUPG:] GOOD_PASSPHRASE gpg: encrypted with 2048-bit RSA key, ID 3C717DE6, created 2018-04-15 "Autogenerated Key \<sammy\@example.com\>" [GNUPG:] BEGIN_DECRYPTION [GNUPG:] DECRYPTION_INFO 2 9 [GNUPG:] PLAINTEXT 62 1524321773 [GNUPG:] PLAINTEXT_LENGTH 15 [GNUPG:] DECRYPTION_OKAY [GNUPG:] GOODMDC [GNUPG:] END_DECRYPTION
為每個文件返回的status: decryption ok
腳本,意味着每個文件都被成功解密。
切換到新decrypted/
文件夾並使用cat
命令顯示test1.txt
的內容:
$ cd decrypted/ && cat test1.txt
This is the first test file
我們已經恢復了test1.txt
中我們刪除的文件中存儲的消息。
接下來,讓我們通過使用verifydetach
腳本驗證其簽名來確認此消息確實是原始消息。
簽名文件包含簽名者的身份以及使用簽名文檔中的數據計算的哈希值。在驗證期間,gpg將獲取發送方的公鑰並將其與散列算法一起使用以計算數據的哈希值。計算的散列值和簽名中存儲的值需要匹配才能使驗證成功。
任何對原始文件,簽名文件或發件人公鑰的篡改都將導致哈希值發生變化,驗證過程將失敗。
從decrypted
文件夾中運行腳本:
$ verifydetach
test2.py signature valid test1.txt signature valid test3.txt signature valid
您可以從輸出中看到所有文件都具有有效簽名,這意味着在此過程中文檔未被篡改。
現在讓我們看一下在您簽署文檔后對文檔進行更改時會發生什么。使用nano
打開test1.txt
文件:
nano test1.txt
現在將以下句子添加到文件中:
~/python-test/encrypted/decrypted/test1.txt
This is the first test file Let's add a sentence after signing the file
保存並關閉文件。
現在重新運行verifydetach
腳本並注意輸出的更改方式:
verifydetach
test2.py signature valid test1.txt signature bad test3.txt signature valid
請注意,GnuPG在驗證test1.txt
時返回signature bad
。這是因為我們在簽名后對文件進行了更改。請記住,在驗證過程中,gpg
將簽名文件中存儲的哈希值與您從簽名文檔中計算的哈希值進行比較。我們對test1.txt
文檔所做的更改導致gpg
計算出不同的哈希值。
對於我們的上一次測試,讓我們在腳本執行之前使用verifyfile
來驗證腳本。此腳本可以看作是腳本verifydetach
的擴展,但有以下區別:如果腳本通過驗證過程,verifyfile
將繼續啟動它。
該test2.py
腳本在啟動時會將字符串輸出到控制台。讓我們用它來演示verifyfile
腳本的工作原理。
使用verifyfile運行test2.py腳本:
$ verifyfile test2.py
test2.py signature valid Signature valid, launching script... The second test file is a Python script
從輸出中可以看到腳本驗證了文件的簽名,根據該驗證打印了適當的結果,然后啟動了腳本。
讓我們通過在文件中添加額外的代碼行來測試驗證過程。打開test2.py並插入以下代碼行:
$ nano test2.py
~/python-test/encrypted/decrypted/test2.py
print "The second test file is a Python script" print "This line will cause the verification script to abort"
現在重新運行verifyfile
腳本:
$ verifyfile test2.py
test2.py signature bad Signature invalid, aborting script execution
腳本驗證失敗,導致腳本啟動中止。
結論
該python-gnupg模塊允許在各種加密工具和Python之間進行集成。在某些情況下,例如查詢或將數據存儲到遠程數據庫服務器,快速加密或驗證數據流完整性的能力至關重要。GnuPG密鑰還可用於加密Apple Mail的郵件。
參考文獻:《How To Verify Code and Encrypt Data with Python-GnuPG and Python 3》