實體金鑰方便又安全,但前題是私鑰檔案必須妥善保管,一旦被偷走前功盡棄,白忙一場。存到離線媒體會比放在電腦硬碟安全,即便被人遠端控制或偷用電腦,也沒東西可偷。故在備份好金鑰並存入實體金鑰後,應該馬上將其從電腦中刪除,也要避免上傳到雲端,讓檔案從物理上與網路隔離以策安全。保管好除了避免被偷,還要確保資料可用,GPG 採用的 Ed25519/Curve 25519 橢圓曲線密碼學金鑰,256 bit 長度相當於 RSA 3072 bit 金鑰的安全強度,依據維基百科,需要 2330 個量子位元跟 1260 億個 Toffoli Gate (可逆邏輯閘)的量子電腦(參考:2022 IBM 才推進到最多 433 個量子位元)才能破解,換言之,私鑰要是丟了,以目前的科技水準,加密內容再也別想解開,句點。

離線媒體如記憶卡、隨身碟或外接硬碟都有資料遺失風險,快閃記憶體放久了資料可能消失(延伸閱讀:SSD、USB 行動碟擺很久沒用資料會消失?)、機械硬碟比較耐久,但仍可能故障,除了多存幾份彼此備援,我還想到一個可靠的離線媒體 - 印在紙上鎖進保險箱。

例如,隨手生一把測試用 GPG 金鑰,可輸出成以下這種 Base64 編碼:

公私鑰印成一張 A4 紙,裝進信封鎖進保險箱剛剛好。若萬不幸所有離線媒體壞光光,打開保險箱取出信封,開個 Notepad 一個字元一個字元敲回去,金鑰就重生了。(有種乾燥牛肉乾泡開水又變回 A5 和牛的神奇感)

不過,一個字元一個字元敲太累,有沒有更簡單的還原方法?我想到了 QR Code!

算了一下,以包含 SSH 認證用金鑰的 GPG 私鑰為例,Jeffrey.secKey.asc 的長度為 1245 Bytes,QR Code 放得下嗎?依據維基百科,純數字可到 7089 字元、0-9 純大寫字母跟符號可到 4296 字元。金鑰文字檔用 Base64 編號有用到小寫字母,最多可到 2953 字了,私鑰檔不到 1500 字元綽綽有餘。

寫幾行程式來驗證。借用之前研究過的 PowerShell 產生 QRCode 範例,只在 $text 參數加上 ValueFromPipeline = $true 以串接 Get-Content 讀取檔案內容直接轉 QR Code,輕鬆搞定。

Param(
    [Parameter(Mandatory=$true, ValueFromPipeline=$true)]
    [string]$text,
    [string]$imgPath
)
$ErrorActionPreference = "STOP"
Add-Type -Path $PSScriptRoot\QRCoder.dll

$qrGenerator = New-Object QRCoder.QRCodeGenerator
[byte[]] $textBytes = [System.Text.Encoding]::UTF8.GetBytes($text)
$qrCodeData = $qrGenerator.CreateQrCode([byte[]]$textBytes, [int][QRCoder.QRCodeGenerator]::ECCLevel.Q)
$qrCode = New-Object QRCoder.QRCode($qrCodeData)
$img = $qrCode.GetGraphic(20)
if (!$imgPath) { $imgPath = "$(Get-Location)\QRCode-$(Get-Date -Format MMddHHmmssfff).png" }
Write-Host $imgPath
$img.Save($imgPath);

實際列印出來,用手機試刷,成功!

thumbnail


Comments

# by Jimmy

這有現成的解決方案叫「Paperkey」,備份還原時需要相符的公鑰,比較安全。 https://www.jabberwocky.com/software/paperkey/

# by Tom

可否看看Paperkey?

# by Jeffrey

to Jimmy, Tom,原來有現成工具,謝謝分享。公鑰通常是公開流通資訊,我想還原時需要公鑰與安全無關,主要是減少資料量。

# by Victor

我從來沒想過powershell可以create QRcode, 太強大了吧... 哪裡有資料會詳列powershell可以做什麼呢?

# by Jeffrey

to Victor,PowerShell 可以直接引用 .NET 程式庫,還可以動態編譯 C# 程式碼,此門開啟後,.NET 做得到的 PowerShell 都做得到。 呼叫 .NET DLL https://blog.darkthread.net/blog/call-net-lib-with-powershell/ 動態編譯 C# https://blog.darkthread.net/blog/remove-docx-protection/

Post a comment