介紹如何使用 OpenSSL 指令,以 AES 與 RSA 這兩個對稱式與非對稱式加密演算法,加密與解密大型檔案。
首先要產生一個測試加密用的大檔案,產生的方式有很多種,任選一種來使用即可:
# 建立大小為 100MB 的檔案 fallocate -l 100M sample.txt # 從 /dev/urandom 讀取亂數建立大小為 100MB 的檔案 dd if=/dev/urandom of=sample.txt bs=100M count=1 # 從 /dev/urandom 讀取亂數建立大小為 100MB 的檔案 head -c 100M /dev/urandom > sample.txt
以上三種方式都會建立一個檔案名稱為 sample.txt
的測試檔案,其檔案大小為 100MB,以下我們將使用這種加密方式,來對這個檔案進行加密與解密。
AES 是目前主流的對稱式加密演算法,可以用一支金鑰(或密碼)對資料進行加密,而解密時也是使用同一支金鑰,AES 支援的金鑰長度有 128 位元、192 位元與 256 位元三種,以下是 OpenSSL 常見的一些 AES 加密指令。
最單純的 AES 對稱式加密方式,就是直接以輸入的密碼進行加密:
# 以 AES-256 方式搭配 CBC 模式加密 openssl enc -aes-256-cbc -pbkdf2 -p -in sample.txt -out sample.txt.enc
enter AES-256-CBC encryption password: Verifying - enter AES-256-CBC encryption password: salt=3BFFA34D495F97DE key=F420AAE47B421879E3DC5CBB727623437B511F3DFE5D94DEFCA99031A5AEF276 iv =F4AC0251A02EEAE548C897D58CC35D2F
上面這行指令執行時,會讓使用者從鍵盤輸入兩次密碼,而加密後會顯示 salt
、key
與 iv
資訊,其中各參數的意義如下:
enc
:進行對稱式加密。-aes-256-cbc
:採用 AES-256 搭配 CBC 模式加密。-pbkdf2
:採用 PBKDF2 演算法。-p
:輸出 salt
、key
與 iv
資訊。-in sample.txt
:指定輸入的未加密檔案為 sample.txt
。-out sample.txt.enc
:指定輸出的加密檔案為 sample.txt.enc
。若要將加密的 sample.txt.enc
解密,只要將原本的指令加上 -d
這個解密參數,並指定好輸入與輸出檔案即可,而 -p
參數在解密時就可以不必放了:
# 以 AES-256 方式搭配 CBC 模式解密 openssl enc -aes-256-cbc -d -pbkdf2 \ -in sample.txt.enc -out sample_decrypted.txt
OpenSSL 支援的對稱式加密演算法有很多,某些演算法若沒有正確使用,會造成安全性問題,對於初學者來說建議採用高強度的 AES 演算法搭配 CBC 模式,也就是這裡我們採用的模式。若要查詢 OpenSSL 所支援的對稱式加密演算法清單,可以使用以下指令:
# 列出 OpenSSL 所有支援的對稱式加密演算法 openssl enc -list # 查詢 OpenSSL 對稱式加密演算法文件 man openssl-enc
另一種 AES 對稱式加密方式是先以亂數產生一組金鑰,將金鑰儲存在檔案中,再以這個金鑰檔案進行 AES 加密。以下指另可產生亂數金鑰:
# 產生亂數金鑰 openssl rand 32 > symmetric_keyfile.key
然後再使用這個金鑰檔案以 AES-256 方式搭配 CBC 模式加密:
# 使用金鑰檔案以 AES-256 方式搭配 CBC 模式加密 openssl enc -aes-256-cbc -pbkdf2 -pass file:./symmetric_keyfile.key \ -in sample.txt -out sample.txt.enc
以下是以金鑰檔案解密的指令,同樣只是加上 -d
這個解密參數而已,指令結構大同小異:
# 使用金鑰檔案以 AES-256 方式搭配 CBC 模式解密 openssl enc -aes-256-cbc -d -pbkdf2 -pass file:./symmetric_keyfile.key \ -in sample.txt.enc -out sample_decrypted.txt
這裡使用 -pass
讀取密碼檔時,根據手冊說明,只會讀取密碼檔案中的第一行,所以可能對於二進位檔案會有讀取不完全的問題。
在非對稱式加密演算法中,RSA 算是一種廣泛被使用的標準演算法,但是由於 RSA 是一種非常耗費計算資源的演算法,所以不適合用來加密太大的檔案,實務上若希望以非對稱式加密演算法保護資料,會先產生一組亂數金鑰,以 AES 搭配亂數金鑰的方式加密較大的檔案,然後再以 RSA 的公鑰加密那一支亂數金鑰,最後將加密的資料與加密後的亂數金鑰放在一起。而解密時則是以 RSA 私鑰先解開亂數金鑰,再以 AES 搭配亂數金鑰解開真正的資料。
首先依據上面 AES 金鑰檔案加密的描述方式,產生一組亂數金鑰 symmetric_keyfile.key
,並以這組亂數金鑰搭配 AES 演算法加密資料。
接著另外產生一組 RSA 私鑰:
# 產生 RSA 私鑰 openssl genpkey -algorithm RSA -out private_key.pem \ -pkeyopt rsa_keygen_bits:4096
其中各參數的意義如下:
genpkey
:產生私鑰。-algorithm RSA
:指定採用 RSA 演算法。-out private_key.pem
:指定輸出的金鑰檔案為 private_key.pem
。-pkeyopt rsa_keygen_bits:4096
:設定產生私鑰的選項,將 RSA 私鑰長度設為 4096
。執行之後,會將 RSA 私鑰存放於 private_key.pem
這個檔案中,我們可以查看私鑰的內容:
# 查看 RSA 私鑰內容
cat private_key.pem
-----BEGIN PRIVATE KEY----- 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 +/UsH+A9k06Pfu6c1kkaJ2uA47RkTA== -----END PRIVATE KEY-----
然後從 RSA 私鑰產生 RSA 公鑰,將 RSA 公鑰儲存於 public_key.pem
:
# 從 RSA 私鑰產生 RSA 公鑰 openssl rsa -pubout -in private_key.pem -out public_key.pem
writing RSA key
查看 RSA 公鑰內容:
# 查看 RSA 公鑰內容
cat public_key.pem
-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA14bmuqwltgErnLS9JWtN r30DoDAuRY5wawzpOWN+zpzUr8jFY90od8KZI6txQeJRTA9zPDbk56Q1d2DReWlM dDQS9M2hYWPUPZWiQo9MoImNbWuM+Y+Dw3hWEniOYPCjakzQxRhtrEfArvFcah1G Akx8eWIKGUlKjBh9Zi3gR4DII1y37xAQrgRr0+JlaR04fJ2Cf5t/B2lDmVXBYJ4w 72yYk6htQknVr5wFOHDQvJ/n6dLM+R6uhqX+Sa+UbAGqb50IHYCTri++jIUOFs6F x2ejKFSBrK/I6CEcqv9NjIgkx0cK8eG35lZ2EAKxdWGPPG1ZoNLoW+TT1J/E3puv UG0rgyRA3FOVJdCK5mqHp1AagK7eabUOOHPhRI/wKp/cRQeuyBQKKJPQjmgQr2se dQGNyG9jPRhC5yFhzFzMDOsbIogcFSLoeiBTVQ21OK+7hKDAs5abJ9INE/szA71C 7tX/1jDM2alae9b0vfz46N0UP0TTevj3jKU9g0tCO0sQh0pRSmv6po2OLP7PZZvj 8c/YGLD3F8QwcdELpg/HCgfMJ63QXyr908ScQ505SN/PeaSAC3I9ZW/xjQ4DgU9o Zs4aIbT302mhuXXyRfbHWBfhPNM16PXCNjrBf6oeQm7arwues97YOd8sCYVbipks 2cOWkCk1ngrI0iHgL2mftBkCAwEAAQ== -----END PUBLIC KEY-----
使用 RSA 公鑰加密 AES 的亂數金鑰 symmetric_keyfile.key
:
# 以 RSA 公鑰加密亂數金鑰 openssl pkeyutl -encrypt -inkey public_key.pem -pubin \ -in symmetric_keyfile.key -out symmetric_keyfile.key.enc
經過 RSA 加密過後的 AES 亂數金鑰,會儲存於 symmetric_keyfile.key.enc
這個檔案中,將這個檔案跟加密後的資料一起存放,這樣就完成整個加密的動作了。
在解密的階段,先以 RSA 私鑰解密亂數金鑰:
# 以 RSA 私鑰解密亂數金鑰 openssl pkeyutl -decrypt -inkey private_key.pem \ -in symmetric_keyfile.key.enc -out symmetric_keyfile.key
解開 AES 亂數金鑰 symmetric_keyfile.key
之後,再以上面敘述的 AES 金鑰檔案解密方式,進行資料的解密。