cheat sheet
certutil
The dual-purpose Windows CLI for certificate-store management and as the most reliable built-in tool for file hashing, base64 encoding, and CRL/CTL handling — no install required.
certutil — Certificates, Hashing and Encoding
What it is
certutil.exe is the built-in Windows command-line tool for working with certificates, certificate stores, certificate revocation lists, and — almost by accident — the most reliable built-in utility for SHA-256 hashing and base64 encoding/decoding on a fresh Windows install. It was designed for AD CS (Active Directory Certificate Services) administrators, but every Windows machine since XP ships with it because the certificate-store APIs need a CLI front-end, and that front-end happens to expose -hashfile and -encode/-decode as side effects. On a Windows box with no Git Bash, no PowerShell module installed, and no third-party tooling, certutil is your only way to verify a download's SHA-256 from cmd.exe.
Two distinct workloads dominate real-world use:
- Hashing and encoding — verify installer integrity, base64-encode binary blobs for transport, decode a base64 PEM block back to DER.
- Certificate management — add, remove, view, and verify certificates in the Windows certificate stores, both per-user and machine-wide.
The PowerShell equivalents are Get-FileHash (hashing) and the Cert:\ PSDrive plus Import-Certificate / Export-Certificate (store ops). Both are more idiomatic on modern Windows, but certutil runs everywhere and predates them by 15 years.
Availability
certutil.exe ships as C:\Windows\System32\certutil.exe on Windows XP and later. Most store-modification verbs need elevation; hashing and encoding do not.
certutil -? | findstr /R "^[ ]*\-[a-zA-Z]"
Output:
-dump -- Dump configuration information or files
-hashfile -- Generate and display cryptographic hash over a file
-encode -- Encode file by base64
-decode -- Decode base64-encoded file
-store -- Dump certificate store
-addstore -- Add certificate to store
-delstore -- Delete certificate from store
-verify -- Verify certificate, CRL or chain
-repairstore -- Repair key association or update certificate properties
-urlcache -- Display or delete URL cache entries
...
Syntax
Almost every certutil command follows the pattern certutil [-verb] [args]. Flags are double-letter shortforms (e.g. -f for force) or full word forms (-user to scope to the current user's store rather than the machine).
certutil [-verb] [-flags] <arg1> [arg2 ...]
Output: (none — exits 0 on success)
Essential options
| Switch | Meaning |
|---|---|
-? | Brief help — append a verb for verb-specific help (certutil -hashfile -?) |
-user | Operate on the current user's certificate store (default is local machine) |
-f | Force — overwrite existing entries without prompting |
-silent | Suppress prompts and progress |
-v | Verbose |
-config "ca\name" | Target a specific Certificate Authority |
-enterprise | Target the enterprise (AD-replicated) store |
Hashing files (-hashfile)
certutil -hashfile computes a cryptographic hash of a file. The algorithm is supplied as a positional argument; SHA256 is overwhelmingly the most common for verifying installer downloads.
certutil -hashfile C:\Downloads\setup.exe SHA256
Output:
SHA256 hash of C:\Downloads\setup.exe:
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
CertUtil: -hashfile command completed successfully.
Supported algorithms
The full list of algorithms certutil supports as the second argument to -hashfile:
| Algorithm | Output bits | Notes |
|---|---|---|
MD2 | 128 | Obsolete; do not use |
MD4 | 128 | Obsolete; do not use |
MD5 | 128 | Cryptographically broken, but still common for non-security file fingerprints |
SHA1 | 160 | Deprecated for security use |
SHA256 | 256 | The default choice for download verification |
SHA384 | 384 | Common for code signing |
SHA512 | 512 | Common for archive integrity |
If the algorithm is omitted, certutil -hashfile returns SHA1 (legacy default) — always specify SHA256 explicitly.
rem MD5 fingerprint for cross-referencing legacy mirror lists
certutil -hashfile C:\Downloads\old.zip MD5
rem SHA512 for very-long-lived integrity records
certutil -hashfile C:\Downloads\bigarchive.tar.gz SHA512
Output:
MD5 hash of C:\Downloads\old.zip:
d41d8cd98f00b204e9800998ecf8427e
CertUtil: -hashfile command completed successfully.
SHA512 hash of C:\Downloads\bigarchive.tar.gz:
cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e
CertUtil: -hashfile command completed successfully.
Stripping the surrounding noise
certutil -hashfile prints three lines: a header, the hash, and a "command completed" footer. For scripting, you want just the hash. The middle line is reliably the second of three, so a for /f "skip=1" pull works on every Windows locale.
@echo off
for /f "skip=1 tokens=*" %%H in ('certutil -hashfile setup.exe SHA256') do (
if not defined HASH set "HASH=%%H"
)
echo %HASH%
Output:
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
PowerShell Get-FileHash — when to prefer it
PowerShell's Get-FileHash is cleaner — it returns an object you can compare directly — but adds 50–100 ms of startup time and isn't available in pure cmd.exe or recovery environments.
Get-FileHash setup.exe -Algorithm SHA256 | Select-Object -ExpandProperty Hash
Output:
E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
The hex case differs (Get-FileHash returns upper-case, certutil lower-case); always lowercase both sides before comparing.
Base64 encoding and decoding (-encode / -decode)
certutil -encode wraps a binary file in PEM-style base64 with -----BEGIN CERTIFICATE----- headers. -decode reverses it. Despite the name, both work on any binary file — useful for transporting binaries through systems that mangle non-printable bytes (email, chat, GPO scripts, registry REG_SZ values).
certutil -encode binary.bin binary.b64
Output:
Input Length = 1024
Output Length = 1438
CertUtil: -encode command completed successfully.
certutil -decode binary.b64 binary_restored.bin
fc /b binary.bin binary_restored.bin
Output:
Input Length = 1438
Output Length = 1024
CertUtil: -decode command completed successfully.
Comparing files binary.bin and binary_restored.bin
FC: no differences encountered
Encoded file format
The output of -encode is not raw base64 — it's PEM-style with headers and 64-char line wrapping. This matters when interoperating with non-Windows tools:
-----BEGIN CERTIFICATE-----
MIIDdzCCAl+gAwIBAgIEFhlH...lots of base64...4tlEZQIDAQAB
...
-----END CERTIFICATE-----
For raw, headerless base64, pipe through findstr /v "-----" or use PowerShell:
[Convert]::ToBase64String([IO.File]::ReadAllBytes('binary.bin')) | Set-Content binary.raw.b64
Output: (none — file written)
Hex dump of a binary file
certutil -dump (no verb argument) dumps the contents of certificate-like files in human-readable form. For arbitrary binary, certutil -encodehex produces a clean side-by-side hex+ASCII dump — much faster to type than installing xxd or hexdump. certutil -decodehex reverses it, turning a hex-encoded text file back into binary.
certutil -encodehex binary.bin binary.hex
type binary.hex
Output:
0000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 .ELF............
0010 02 00 3e 00 01 00 00 00 d0 30 40 00 00 00 00 00 ..>......0@.....
0020 40 00 00 00 00 00 00 00 20 19 00 00 00 00 00 00 @....... .......
...
rem Round-trip: encode, then decode back, then compare
certutil -encodehex binary.bin binary.hex
certutil -decodehex binary.hex binary_restored.bin
fc /b binary.bin binary_restored.bin
Output:
CertUtil: -encodehex command completed successfully.
CertUtil: -decodehex command completed successfully.
Comparing files binary.bin and binary_restored.bin
FC: no differences encountered
Certificate stores — overview
Windows organises certificates into named stores — My (user/computer personal certs with private keys), Root (trusted root CAs), CA (intermediate CAs), TrustedPublisher, Disallowed, AuthRoot, plus many others. Each store exists in three scopes:
| Scope | Switch | Path in mmc/regedit |
|---|---|---|
| Local Computer | (default) | Cert:\LocalMachine\* / Computer Account snap-in |
| Current User | -user | Cert:\CurrentUser\* / User Account snap-in |
| Service / Enterprise | -enterprise | AD-replicated, computer-scoped |
rem List names of every store under the local machine
certutil -store -? | findstr /R "^[ ]*\""
Output:
"My"
"Root"
"Trust"
"CA"
"TrustedPublisher"
"Disallowed"
"AuthRoot"
"TrustedPeople"
...
Viewing certificates in a store (-store)
-store <storename> [serialnum|thumb|cn] dumps the contents of a store. With no second argument it lists everything; with an argument, it shows only the matching cert(s).
rem List every trusted root CA on this machine
certutil -store Root | findstr "Subject:"
Output:
Subject: CN=Microsoft Root Certificate Authority 2011, O=Microsoft Corporation
Subject: CN=DigiCert Global Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US
Subject: CN=GlobalSign, O=GlobalSign, OU=GlobalSign Root CA - R3
Subject: CN=USERTrust RSA Certification Authority, O=The USERTRUST Network
...
rem User-scope personal certificates
certutil -user -store My
Output:
My
================ Certificate 0 ================
Serial Number: 4a52b06d000200000017
Issuer: CN=ACME Issuing CA, DC=corp, DC=example
NotBefore: 2025-09-01 14:22
NotAfter: 2026-09-01 14:32
Subject: CN=Alice Dev, CN=Users, DC=corp, DC=example
Non-root Certificate
Cert Hash(sha1): 71 6a 4f 8d 92 a3 ...
Key Container = ...
Provider = Microsoft Strong Cryptographic Provider
Signature test passed
CertUtil: -store command completed successfully.
Looking up a specific cert by serial number, hash, or CN
The second argument to -store is a flexible matcher — serial number, SHA1 thumbprint, common-name substring, all work.
certutil -store Root "DigiCert Global Root CA"
Output:
Root
================ Certificate ... ================
Serial Number: 083be056904246b1a1756ac95991c74a
Issuer: CN=DigiCert Global Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US
NotBefore: 2006-11-10 00:00
NotAfter: 2031-11-10 00:00
Subject: CN=DigiCert Global Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US
Signature matches Public Key
Root Certificate: Subject matches Issuer
Cert Hash(sha1): a8985d3a65e5e5c4b2d7d66d40c6dd2fb19c5436
No key provider information
Cannot find the certificate and private key for decryption.
CertUtil: -store command completed successfully.
Adding and removing certificates (-addstore / -delstore)
-addstore imports a certificate from a .cer, .crt, .p7b, or .sst file into the named store. Requires admin if the target store is machine-scoped.
rem Trust a corporate root CA machine-wide
certutil -addstore Root C:\Certs\acme-root-ca.cer
Output:
Root
Signature matches Public Key
Certificate "CN=ACME Root CA, O=Acme Inc, C=US" added to store.
CertUtil: -addstore command completed successfully.
rem User-scope (no admin needed)
certutil -user -addstore Root C:\Certs\acme-root-ca.cer
Output:
Root "Trusted Root Certification Authorities"
Signature matches Public Key
Certificate "CN=ACME Root CA, O=Acme Inc, C=US" added to store.
CertUtil: -addstore command completed successfully.
-delstore removes by serial number, hash, or substring match against the cert subject.
certutil -delstore Root "ACME Root CA"
Output:
Root "Trusted Root Certification Authorities"
================ Certificate ... ================
...
CertUtil: -delstore command completed successfully.
Verifying a certificate or chain (-verify)
-verify does a full chain build and revocation check. Use it before deploying a new cert to confirm Windows will accept it.
certutil -verify -urlfetch mycert.cer
Output:
Issuer:
CN=ACME Issuing CA
DC=corp, DC=example
Subject:
CN=www.example.com
O=Acme Inc, C=US
CertUtil: -verify command completed successfully.
-urlfetch follows AIA and CRL distribution points online — without it the check is offline-only. A successful build through every link of the chain is reported; any broken link (revoked cert, expired intermediate, untrusted root) prints the failing step.
Common verify failures
| Error | Meaning |
|---|---|
0x80092004 (Cannot find object or property) | Certificate not found in store, or chain missing intermediate |
0x800B0109 (CERT_E_UNTRUSTEDROOT) | Root CA not in trusted-roots store |
0x800B010A (CERT_E_CHAINING) | Cannot build a chain from leaf to a trusted root |
0x80092012 (CRYPT_E_NO_REVOCATION_CHECK) | CRL/OCSP unreachable; revocation check skipped |
0x80092013 (CRYPT_E_REVOKED) | Cert is revoked |
URL cache (-urlcache)
Windows caches CRLs, AIA fetches, and downloaded intermediate certs in a per-user URL cache. Stale entries can cause -verify to falsely report failures. Clear the cache with -urlcache * delete.
rem List cached entries
certutil -urlcache | findstr "URL"
rem Clear all
certutil -urlcache * delete
Output:
URL: http://crl.digicert.com/DigiCertGlobalRootCA.crl
URL: http://ocsp.digicert.com/...
URL: http://crl3.digicert.com/sha2-extended-validation-server-g3.crl
CertUtil: -URLCache command completed successfully.
Personal Information Exchange (PFX/PKCS#12)
.pfx (a.k.a. .p12) files bundle a certificate together with its private key, encrypted with a password. certutil -importpfx adds them to a store; -exportpfx writes them out. The private key handling is what distinguishes PFX from the plain .cer files used in -addstore.
rem Import a PFX with private key into the machine's My store
certutil -p "PFXpassword" -importpfx My C:\Certs\webserver.pfx
Output:
Certificate "CN=www.example.com" added to store.
CertUtil: -importpfx command completed successfully.
rem Export a cert + private key out of the store (must be marked exportable)
certutil -exportpfx -p "newPassword" My "CN=www.example.com" C:\Certs\export.pfx
Output:
================ Certificate 0 ================
...
CertUtil: -exportpfx command completed successfully.
PFX encryption algorithm — CryptoAlgorithm=Aes256-Sha256
By default -exportpfx uses the legacy TripleDES-Sha1 encryption for the PFX payload, which fails to import on systems running in FIPS-restricted mode or on hardened OpenSSL 3.x readers. Pass CryptoAlgorithm=Aes256-Sha256 as an -exportpfx modifier to produce a modern AES-256 / SHA-256 protected PFX that OpenSSL 3.x, .NET 8+, and current macOS Keychain accept without warnings.
rem Modern PFX (AES-256 / SHA-256) — required for FIPS and interop with OpenSSL 3.x
certutil -p "newPassword" -exportpfx My "CN=www.example.com" C:\Certs\export.pfx CryptoAlgorithm=Aes256-Sha256
Output:
================ Certificate 0 ================
...
CertUtil: -exportpfx command completed successfully.
The same modifier is accepted by -importpfx on the way back in, alongside ,Exportable (mark private key as exportable from the destination store) and ,VSM (store the private key in a Virtual Smart Card container).
rem Import with private key marked exportable, into the user My store
certutil -user -p "PFXpassword" -importpfx My C:\Certs\webserver.pfx Exportable
Output:
Certificate "CN=www.example.com" added to store.
CertUtil: -importpfx command completed successfully.
Common pitfalls
- Hash output noise —
certutil -hashfilealways prints three lines, and the hash itself is the second. Don't naive-grep for hex; usefindstr /V ":"orfor /f "skip=1"to pull the hash cleanly. - Localised output — on non-English Windows, the surrounding text ("hash of", "command completed successfully") is translated. The hash line itself is unchanged, but pattern matching for
SHA256 hash ofwill fail. Always anchor on position (second line), not on English strings. - Default algorithm is SHA1 —
certutil -hashfile foo(no algorithm) returns SHA1. Old habits aside, always specify SHA256 explicitly. -encodeproduces PEM, not raw base64 — the output includes-----BEGIN CERTIFICATE-----headers and 64-char line breaks. Tools expecting raw base64 will reject it; strip the wrapper or use PowerShell's[Convert]::ToBase64String.-uservs default machine scope — every store operation needs the right scope. Forgetting-userwhile looking for a user's personal cert is the #1 reason for "I imported it but it's not there".-importpfxrequires the private key be exportable — and modern Windows defaults to non-exportable for security. Pass,Exportableafter the password when importing, or use-cspto pick an exportable provider.- Cached CRLs survive cert deletion — after deleting a CA from the Root store, run
certutil -urlcache * deleteto clear any cached chain data, otherwise-verifymay still pass. - The
Rootstore on a domain machine is GPO-managed — values added with-addstoremay be wiped at next GPO refresh. For permanent corporate trust, use aCertificatesGPO that publishes the cert.
Real-world recipes
Verify an installer matches the publisher's published SHA256
The canonical use case. Always compare in lowercase to avoid case mismatches.
@echo off
set EXPECTED=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
for /f "skip=1 tokens=*" %%H in ('certutil -hashfile setup.exe SHA256') do (
if not defined ACTUAL set "ACTUAL=%%H"
)
if /I "%ACTUAL%" == "%EXPECTED%" (
echo MATCH
) else (
echo MISMATCH
echo Expected: %EXPECTED%
echo Actual: %ACTUAL%
exit /b 1
)
Output:
MATCH
Embed a binary into a batch/PS1 deployment script
Encode the binary at packaging time, store the base64 in the script, decode at runtime — useful for shipping a single self-contained installer file.
rem At packaging time:
certutil -encode payload.exe payload.b64
rem In the deployment script, write the b64 into a temp file and decode:
echo -----BEGIN CERTIFICATE----- > %TEMP%\p.b64
echo MIIDdzC...LOTSOFBASE64...4tlEZ >> %TEMP%\p.b64
echo -----END CERTIFICATE----- >> %TEMP%\p.b64
certutil -decode %TEMP%\p.b64 %TEMP%\payload.exe
%TEMP%\payload.exe /silent
Output:
Input Length = 1438
Output Length = 1024
CertUtil: -decode command completed successfully.
(installer runs)
Trust a corporate root CA on every machine via Group Policy script
Stand-alone machines get the CA via this provisioning script; domain-joined machines should use a GPO instead.
@echo off
if not exist "C:\Certs\acme-root.cer" (
echo Certificate file missing.
exit /b 1
)
certutil -addstore -f Root "C:\Certs\acme-root.cer"
echo Root CA installed. Verifying...
certutil -verify "C:\Certs\acme-root.cer" | findstr /I "successfully"
Output:
Root "Trusted Root Certification Authorities"
Signature matches Public Key
Certificate "CN=ACME Root CA, O=Acme Inc, C=US" added to store.
CertUtil: -addstore command completed successfully.
Root CA installed. Verifying...
CertUtil: -verify command completed successfully.
Audit every trusted root CA on a workstation
Useful in compliance audits — list every root CA, their subject, and their expiry date.
certutil -store Root | findstr /R /C:"Subject:" /C:"NotAfter:"
Output:
Subject: CN=Microsoft Root Certificate Authority 2011
NotAfter: 2036-03-22 23:13
Subject: CN=DigiCert Global Root CA
NotAfter: 2031-11-10 00:00
Subject: CN=ACME Root CA
NotAfter: 2030-01-15 12:00
...
Decode a base64 PEM cert and view it
A .pem file is just -----BEGIN CERTIFICATE----- + base64 + -----END CERTIFICATE-----. certutil -decode turns it into a DER .cer you can then dump or import.
certutil -decode incoming.pem incoming.cer
certutil -dump incoming.cer
Output:
Input Length = 1438
Output Length = 1024
CertUtil: -decode command completed successfully.
X509 Certificate:
Version: 3
Serial Number: 4a52b06d...
Signature Algorithm:
Algorithm ObjectId: 1.2.840.113549.1.1.11 sha256RSA
Issuer:
CN=ACME Issuing CA
NotBefore: 2025-09-01 14:22
NotAfter: 2026-09-01 14:32
Subject:
CN=www.example.com
...
Force a cert chain rebuild (clear caches)
When -verify reports a stale revocation error, clear caches and retry.
certutil -urlcache * delete
certutil -setreg chain\ChainCacheResyncFiletime @now
certutil -verify -urlfetch mycert.cer
Output:
CertUtil: -URLCache command completed successfully.
... (revocation freshly fetched)
CertUtil: -verify command completed successfully.
Compute the SHA256 of every file in a directory
@echo off
for %%F in (*.exe) do (
for /f "skip=1 tokens=*" %%H in ('certutil -hashfile "%%F" SHA256') do (
if not defined H_%%~nF set "H_%%~nF=%%H"
)
)
set H_
Output:
H_setup=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
H_updater=2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae
Sources
Microsoft Learn — certutil command — Authoritative verb reference covering -dump, -dumpPFX, -hashfile, -encode / -decode, -encodehex / -decodehex, store ops (-store, -addstore, -delstore, -enumstore, -importpfx, -exportpfx with the modern CryptoAlgorithm=Aes256-Sha256 modifier), -verify, and CA backup / restore.
Tips
If you need to verify a download but only have
cmd.exe, no PowerShell, and no third-party tools,certutil -hashfile foo SHA256is your tool. It's been there since XP and will be there in WinPE recovery environments.
certutil -dumpaccepts almost any cert-like file —.cer,.crt,.p7b,.pfx,.csr,.crl, even raw DER. Reach for it before guessing a file's format.
For modern automation in PowerShell, prefer
Get-FileHash,Import-PfxCertificate, and theCert:\PSDrive overcertutil. Reservecertutilfor batch scripts, MSI custom actions, and recovery environments where PowerShell isn't guaranteed to be available.