ねらい:VBAで“実務的な暗号化”を安全に使い分ける
暗号化は「守る対象」によって最適解が変わります。ファイルを配布するならZIPのAESやExcelのパスワード保存、テキストや設定値を隠すならOS標準のDPAPI(ユーザー紐付け暗号)や共通キーAESが有効です。初心者でも貼って動かせるVBAテンプレートを、用途別(ファイル/テキスト/整合性ハッシュ)で示し、失敗しないための鍵管理・クオート・待機・復帰の重要ポイントを深掘りします。
重要ポイントの深掘り
- 暗号は“方式より運用”が命です。鍵(パスワード/キー)をどこに置くか、誰が復号できるべきかを先に決めます。自作アルゴリズム(XORや自前AES)は避け、OS標準や実績ツールを呼ぶのが安全です。
- Excelの「保存パスワード」は現行Officeでは暗号化付きの保存(配布に有効)。ZIPのAES-256(7-Zip)も標準。テキストの機密はDPAPI(ユーザー固有)か、共有前提なら共通キーAESを使います。
- パスやパスワードは必ずダブルクォートで囲み、非表示・完了待ち(戻り値判定)を徹底。開始・終了枠でUI復帰を保証します。
ファイル暗号化:Excelのパスワード保存と7-Zip AES
Excelブックをパスワード付きで保存(現行Officeは暗号化付き)
' ModEncryptFile_Excel.bas
Option Explicit
Public Sub SaveWorkbookEncrypted(ByVal outPath As String, ByVal password As String)
On Error GoTo EH
AppEnter "SaveEncrypted"
ActiveWorkbook.SaveAs Filename:=outPath, Password:=password, WriteResPassword:="",
ReadOnlyRecommended:=False, AccessMode:=xlNoChange
AppLeave
MsgBox "暗号化保存(パスワード付)完了: " & outPath, vbInformation
Exit Sub
EH:
AppLeave
MsgBox "失敗: " & Err.Description, vbExclamation
End Sub
VB重要ポイントの深掘り
- ExcelのSaveAs Passwordは“開くためのパスワード”で暗号化付き(現行xlsx/xlsm)。マクロ含む配布に向きます。業務で鍵を使い回すなら、配布先管理と鍵伝達手順をセットで運用してください。
- パスワードはコードに直書きしないのが鉄則。入力ダイアログや外部安全保管(資格情報マネージャなど)で受け渡しを検討します。
7-ZipでAES-256暗号ZIPにする(戻り値で確実に判定)
' ModEncryptFile_7z.bas
Option Explicit
Public Sub ZipEncryptWith7z(ByVal srcFolder As String, ByVal zipPath As String, ByVal password As String)
On Error GoTo EH
Dim exe As String: exe = """C:\Program Files\7-Zip\7z.exe""" ' 環境に合わせて設定
Dim cmd As String
cmd = exe & " a -tzip -p" & """" & password & """" & " -mem=AES256 -y " & _
"""" & zipPath & """ " & """" & srcFolder & "\*"""
ShellRunWait cmd
MsgBox "AES-256暗号ZIP作成完了: " & zipPath, vbInformation
Exit Sub
EH:
MsgBox "失敗: " & Err.Description, vbExclamation
End Sub
Private Sub ShellRunWait(ByVal cmd As String)
Dim sh As Object: Set sh = CreateObject("WScript.Shell")
Dim rc As Long: rc = sh.Run(cmd, 0, True)
If rc <> 0 Then Err.Raise 8010, , "外部コマンド失敗: " & rc
End Sub
VB重要ポイントの深掘り
- AES-256の暗号ZIPは受け手のOS/ツール互換が高く、配布に最適。戻り値で失敗検知が可能。パス・パスワードのクオート徹底で日本語も安全に通します。
- 実行パスが環境で異なるため、設定化(セルやConfigファイル)にすると配布が楽です。
テキスト暗号化:PowerShellで安全に委譲(DPAPIとAES)
ユーザー紐付け暗号(DPAPI):そのPCのそのユーザーだけが復号可能
' ModCrypto_Dpapi.bas
Option Explicit
Public Function EncryptTextDpapi(ByVal plain As String) As String
Dim ps As String
ps = "powershell -NoProfile -Command " & _
"""$s='" & EscapePS(plain) & "'; " & _
"$sec=ConvertTo-SecureString -String $s -AsPlainText -Force; " & _
"ConvertFrom-SecureString $sec"""
EncryptTextDpapi = ExecReadAll(ps)
End Function
Public Function DecryptTextDpapi(ByVal cipher As String) As String
Dim ps As String
ps = "powershell -NoProfile -Command " & _
"""$sec='" & EscapePS(cipher) & "' | ConvertTo-SecureString; " & _
"[Runtime.InteropServices.Marshal]::PtrToStringUni([Runtime.InteropServices.Marshal]::SecureStringToBSTR($sec))"""
DecryptTextDpapi = ExecReadAll(ps)
End Function
Private Function ExecReadAll(ByVal cmd As String) As String
Dim sh As Object: Set sh = CreateObject("WScript.Shell")
Dim p As Object: Set p = sh.Exec(cmd)
ExecReadAll = p.StdOut.ReadAll
End Function
Private Function EscapePS(ByVal s As String) As String
EscapePS = Replace(Replace(s, "'", "''"), """", "`" & """")
End Function
VB重要ポイントの深掘り
- DPAPIは鍵管理不要。“そのユーザーのログオン鍵”で暗号化されるため、PC内の秘匿設定や資格トークン保管に最適。共有はできません(それが安全)。
- 文字列は安全にエスケープしてPowerShellへ渡します。機密はファイルに書かず、必要時のみメモリで処理しましょう。
共有前提のAES暗号(共通キー):同じキーで複数人が復号可能
' ModCrypto_AES.bas
Option Explicit
Public Function EncryptTextAes(ByVal plain As String, ByVal keyHex As String, ByVal ivHex As String) As String
Dim ps As String
ps = "powershell -NoProfile -Command " & _
"""$p='" & EscapePS(plain) & "'; " & _
"$k='" & keyHex & "'; $v='" & ivHex & "'; " & _
"$aes=[System.Security.Cryptography.Aes]::Create(); " & _
"$aes.Key=[byte[]]($k -split '([A-Fa-f0-9]{2})' | ? { $_ -match '^[A-Fa-f0-9]{2}$' } | % {[Convert]::ToByte($_,16)}); " & _
"$aes.IV=[byte[]]($v -split '([A-Fa-f0-9]{2})' | ? { $_ -match '^[A-Fa-f0-9]{2}$' } | % {[Convert]::ToByte($_,16)}); " & _
"$enc=$aes.CreateEncryptor(); " & _
"$bytes=[Text.Encoding]::UTF8.GetBytes($p); " & _
"$cipher=$enc.TransformFinalBlock($bytes,0,$bytes.Length); " & _
"[Convert]::ToBase64String($cipher)"""
EncryptTextAes = ExecReadAll(ps)
End Function
Public Function DecryptTextAes(ByVal b64 As String, ByVal keyHex As String, ByVal ivHex As String) As String
Dim ps As String
ps = "powershell -NoProfile -Command " & _
"""$c='" & b64 & "'; $k='" & keyHex & "'; $v='" & ivHex & "'; " & _
"$aes=[System.Security.Cryptography.Aes]::Create(); " & _
"$aes.Key=[byte[]]($k -split '([A-Fa-f0-9]{2})' | ? { $_ -match '^[A-Fa-f0-9]{2}$' } | % {[Convert]::ToByte($_,16)}); " & _
"$aes.IV=[byte[]]($v -split '([A-Fa-f0-9]{2})' | ? { $_ -match '^[A-Fa-f0-9]{2}$' } | % {[Convert]::ToByte($_,16)}); " & _
"$dec=$aes.CreateDecryptor(); " & _
"$bytes=[Convert]::FromBase64String($c); " & _
"$plain=$dec.TransformFinalBlock($bytes,0,$bytes.Length); " & _
"[Text.Encoding]::UTF8.GetString($plain)"""
DecryptTextAes = ExecReadAll(ps)
End Function
VB重要ポイントの深掘り
- AESは“鍵とIVの管理”がすべて。鍵はHex(32バイト=256bit)で、安全保管(環境変数・資格情報・秘密管理)を前提に。コード直書きは厳禁。
- モードはCBC+PKCS7のデフォルト。改ざん検知が必要なら、別途HMAC(SHA-256)でタグを付ける設計にしてください。
整合性確認:SHA-256ハッシュで“壊れていない”を証明
ファイルのSHA-256を取得して台帳へ記録
' ModHash_SHA256.bas
Option Explicit
Public Function FileSha256(ByVal path As String) As String
Dim cmd As String
cmd = "powershell -NoProfile -Command ""(Get-FileHash -Algorithm SHA256 -Path '" & Replace(path, "'", "''") & "').Hash"""
FileSha256 = ExecReadAll(cmd)
End Function
Public Sub Demo_FileHash()
Dim f As String: f = ThisWorkbook.FullName
Dim h As String: h = FileSha256(f)
MsgBox "SHA-256: " & h, vbInformation
End Sub
Private Function ExecReadAll(ByVal cmd As String) As String
Dim sh As Object: Set sh = CreateObject("WScript.Shell")
Dim p As Object: Set p = sh.Exec(cmd)
ExecReadAll = Trim$(p.StdOut.ReadAll)
End Function
VB重要ポイントの深掘り
- 暗号化だけでなく“整合性(改ざんなし)”の確認は運用の柱。受け渡し前後でハッシュを記録し、監査に耐える形にします。
- ハッシュ文字列は大文字/小文字は区別不要。改行除去(Trim)して扱います。
Base64エンコード/デコード(暗号化の代わりではない)
文字列をBase64で包む(表での一時隠し)
' ModBase64.bas
Option Explicit
Public Function ToBase64(ByVal s As String) As String
Dim bytes() As Byte: bytes = StrConv(s, vbFromUnicode)
ToBase64 = EncodeBase64(bytes)
End Function
Public Function FromBase64(ByVal b64 As String) As String
Dim bytes() As Byte: bytes = DecodeBase64(b64)
FromBase64 = StrConv(bytes, vbUnicode)
End Function
Private Function EncodeBase64(ByRef bytes() As Byte) As String
Dim xml As Object: Set xml = CreateObject("MSXML2.DOMDocument")
Dim node As Object: Set node = xml.createElement("b64")
node.DataType = "bin.base64": node.nodeTypedValue = bytes
EncodeBase64 = node.Text
End Function
Private Function DecodeBase64(ByVal b64 As String) As Byte()
Dim xml As Object: Set xml = CreateObject("MSXML2.DOMDocument")
Dim node As Object: Set node = xml.createElement("b64")
node.DataType = "bin.base64": node.Text = b64
DecodeBase64 = node.nodeTypedValue
End Function
VB重要ポイントの深掘り
- Base64は“可視化しにくくする”だけ。セキュリティ目的では不十分。ログやCSVでの無害化、一時的な非表示に限って使います。
- 機密なら必ず暗号(DPAPI/AES/ZIP AES)を使ってください。
例題の通し方と検証ポイント
手順
- Report.xlsxをSaveWorkbookEncryptedでパスワード保存し、開けることを確認。
- ログフォルダをZipEncryptWith7zでAES-256暗号ZIP化し、解凍できることを確認。
- 機密文字列をEncryptTextDpapi→DecryptTextDpapiで往復し、PCユーザーが変わると復号できないことを体験。
- 共有が必要な値をEncryptTextAes→DecryptTextAesで確認。鍵はHex32バイト、IVはHex16バイトを用意。
- 配布ファイルのSHA-256を記録し、受け手が同値であることを確認。
確認ポイント
- パス・パスワードのクオート徹底で日本語パスでも成功。
- 戻り値や例外で失敗検知し、必ず“復帰枠”到達(AppLeave)を確認。
- 鍵の扱い方(入力、保管場所、ログ出力禁止)が仕様として固まっている。
共通枠と安全運用のコツ
開始・終了枠(必ず復帰)
' ModApp.bas
Option Explicit
Public Sub AppEnter(Optional ByVal status As String = "")
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.DisplayAlerts = False
If Len(status) > 0 Then Application.StatusBar = status
End Sub
Public Sub AppLeave()
Application.StatusBar = False
Application.DisplayAlerts = True
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
VB重要ポイントの深掘り
- 機密を扱う処理は“失敗しても環境復帰”が最優先。StatusBarや描画抑止を管理し、例外でもAppLeaveへ到達させます。
- ログに機密(平文・鍵)を書かない。テスト時のみダミーデータを使い、本番ではメッセージ最小化。
落とし穴と対策
鍵の直書き・共有の乱れ
鍵をコードやシートに書かない。入力ダイアログや資格情報の保管、環境変数読取に切り替える。共有鍵は配布・ローテーション手順を決める。
DPAPIの“共有不能”を誤用
DPAPIはユーザー固有。共有が必要な場面ではAESへ。逆に機密設定はDPAPIが最適。
完了検知の曖昧さ
外部コマンドは戻り値判定、Shell.NameSpaceは件数監視か外部への切替で“確実な完了”を取る。
Base64の過信
Base64は暗号ではない。必ず暗号方式を併用する。
まとめ:目的に合わせて最短・安全な暗号ルートを選ぶ
- ブック配布はExcelのパスワード保存、フォルダ配布は7-Zip AES。
- テキスト機密はユーザー紐付け(DPAPI)か共有前提AES。
- 整合性はSHA-256で記録。鍵管理・クオート・待機・復帰の徹底で、初心者でも堅実に運用できます。
