BitLocker recovery key escrow to Crypt Server with full key rotation support.
A native Windows implementation inspired by the Mac Crypt client, built with .NET 10 for escrowing BitLocker recovery keys with automatic key rotation, enterprise logging, and scheduled task integration.
- Escrow BitLocker recovery keys to Crypt Server
- Full key rotation support (create new key, escrow, cleanup old keys)
- Automatic rotation when server requests it
- Verify escrow status via Crypt Server API
- YAML configuration file with environment variable fallback
- Windows scheduled task registration
- Structured logging with Serilog
- Single-file self-contained executable (no .NET runtime required)
- ARM64 and x64 native binaries
- Intune-compatible exit codes
- KeyEscrowInterval: Configurable re-escrow interval (default: 1 hour)
- ValidateKey: Local key validation before escrow
- SkipUsers: Array of users to skip from escrow enforcement
- PostRunCommand: Command to run after error conditions
- Log Rotation: Configurable log retention (default: 30 days)
Download the latest release from GitHub Releases:
checkin-x64.exe- For Intel/AMD systemscheckin-arm64.exe- For ARM64 systems (Surface Pro X, etc.)
Note: The binary is named
checkin(following Mac Crypt convention). When installed via MSI, it is added toPATHascheckin.exeinC:\Program Files\Crypt\.
# Full build with auto-signing (if certificate available)
.\build.ps1
# Build without signing
.\build.ps1 -NoSign
# Build specific architecture
.\build.ps1 -Runtime win-x64# Option A: Set via command
checkin config set server.url https://crypt.example.com
# Option B: Set via environment variable
setx CRYPT_ESCROW_SERVER_URL "https://crypt.example.com" /Mcheckin escrowcheckin verifyEscrows the BitLocker recovery key to the Crypt Server.
checkin escrow [options]
Options:
-s, --server <url> Crypt Server URL
-d, --drive <drive> Drive letter (default: C:)
-f, --force Force escrow even if already escrowed
--skip-cert-check Skip TLS certificate validationRotates the BitLocker recovery key and escrows the new key.
checkin rotate [options]
Options:
-s, --server <url> Crypt Server URL
-d, --drive <drive> Drive letter (default: C:)
-c, --cleanup Remove old protectors (default: true)
--skip-cert-check Skip TLS certificate validationChecks if a key has been escrowed for the current device.
checkin verify [options]
Options:
-s, --server <url> Crypt Server URL
--skip-cert-check Skip TLS certificate validationManage configuration settings.
# Show current configuration
checkin config show
# Set a configuration value
checkin config set server.url https://crypt.example.com
checkin config set escrow.auto_rotate true
checkin config set escrow.key_escrow_interval_hours 2Registers a Windows scheduled task for automated escrow.
checkin register-task [options]
Options:
-s, --server <url> Crypt Server URL
-f, --frequency Task frequency: hourly, daily, weekly, login (default: daily)Configuration is loaded from (in order of precedence):
- Command-line options
- Environment variables
- Registry (CSP/OMA-URI from Intune)
- YAML configuration file
Location: C:\ProgramData\ManagedEncryption\config.yaml
server:
url: https://crypt.example.com
verify_ssl: true
timeout_seconds: 30
retry_attempts: 3
auth:
api_key: your-secret-api-key
api_key_header: X-API-Key
use_mtls: false
certificate_subject: crypt-client.example.com
certificate_store_location: LocalMachine
certificate_store_name: My
escrow:
secret_type: recovery_key
auto_rotate: true
cleanup_old_protectors: true
key_escrow_interval_hours: 1
validate_key: true
post_run_command: null
skip_users:
- admin
- service_account
logging:
level: INFO
retained_days: 30| Variable | Description |
|---|---|
CRYPT_ESCROW_SERVER_URL |
Crypt Server URL |
CRYPT_ESCROW_SKIP_CERT_CHECK |
Skip SSL verification (true/false) |
CRYPT_ESCROW_AUTO_ROTATE |
Auto-rotate on server request |
CRYPT_ESCROW_CLEANUP_OLD_PROTECTORS |
Remove old protectors |
CRYPT_KEY_ESCROW_INTERVAL |
Re-escrow interval in hours |
CRYPT_VALIDATE_KEY |
Validate key locally before escrow |
CRYPT_SKIP_USERS |
Comma-separated list of users to skip |
CRYPT_POST_RUN_COMMAND |
Command to run after errors |
CRYPT_API_KEY |
API key for server authentication |
CRYPT_API_KEY_HEADER |
Custom API key header name (default: X-API-Key) |
CRYPT_USE_MTLS |
Enable mutual TLS authentication (true/false) |
CRYPT_CERT_SUBJECT |
Client certificate subject name for mTLS (Cert Store) |
CRYPT_CERT_THUMBPRINT |
Client certificate thumbprint for mTLS (Cert Store) |
CRYPT_PFX_PATH |
Path to client certificate PFX file for mTLS (preferred file-based option) |
CRYPT_PFX_PASSWORD_CRED |
Name of Windows Credential Manager entry holding the PFX passphrase |
CRYPT_CLIENT_CERT_PATH |
Path to client certificate PEM file for mTLS (least preferred file-based option) |
CRYPT_CLIENT_KEY_PATH |
Path to client private key PEM file (paired with above) |
The client supports API key and mutual TLS (mTLS) authentication.
API Key:
server:
auth:
api_key: your-secret-api-key
api_key_header: X-API-Key # custom header name (default)Or via environment variables: CRYPT_API_KEY and CRYPT_API_KEY_HEADER.
Mutual TLS (mTLS):
Set use_mtls: true (or CRYPT_USE_MTLS=true) and pick one of the three strategies below. They are tried in the order listed — most secure first — and the first one that succeeds wins. If you configure multiple, the higher-ranked strategy is used.
Similar to Mac Crypt's CommonNameForEscrow feature. The private key is protected by DPAPI, can be marked non-exportable at import time, and integrates with the Windows PKI lifecycle. Deployable via Intune / Group Policy.
server:
auth:
use_mtls: true
certificate_subject: crypt-client.example.com # or use certificate_thumbprint
certificate_store_location: LocalMachine # or CurrentUser
certificate_store_name: MyEnvironment variables: CRYPT_CERT_SUBJECT, CRYPT_CERT_THUMBPRINT.
Use when importing into the Cert Store isn't feasible but you still want encrypted-at-rest key material. The passphrase lives in Windows Credential Manager (DPAPI-protected) and is never stored in YAML, environment variables, or the registry.
Provision the passphrase once with cmdkey:
cmdkey /generic:CryptPfxPassword /user:cryptescrow /pass:<pfx-passphrase>Then configure:
server:
auth:
use_mtls: true
pfx_path: C:\ProgramData\ManagedEncryption\client.pfx
pfx_password_credential: CryptPfxPassword # matches the /generic: value aboveEnvironment variables: CRYPT_PFX_PATH, CRYPT_PFX_PASSWORD_CRED. If the PFX has no passphrase, omit pfx_password_credential.
The private key sits in plaintext on disk, protected only by filesystem ACLs. Only use this when the other two options aren't available, and lock the key file down so only SYSTEM (or the service account) can read it:
icacls C:\ProgramData\ManagedEncryption\client.key /inheritance:r /grant:r SYSTEM:Rserver:
auth:
use_mtls: true
client_cert_path: C:\ProgramData\ManagedEncryption\client.pem
client_key_path: C:\ProgramData\ManagedEncryption\client.keyEnvironment variables: CRYPT_CLIENT_CERT_PATH, CRYPT_CLIENT_KEY_PATH.
Enterprise policies can be deployed via Intune CSP/OMA-URI to these registry locations:
Standard Group Policy Path:
HKLM\SOFTWARE\Policies\Crypt\ManagedEncryption
MDM/Intune Path:
HKLM\SOFTWARE\Microsoft\PolicyManager\current\device\Crypt~Policy~ManagedEncryption
| Value Name | Type | Description |
|---|---|---|
ServerUrl |
String | Crypt Server URL (e.g., https://crypt.example.com) |
SkipCertCheck |
String/DWORD | Skip SSL verification (true/1 or false/0) |
AutoRotate |
String/DWORD | Auto-rotate on server request |
CleanupOldProtectors |
String/DWORD | Remove old protectors after escrow |
KeyEscrowIntervalHours |
String/DWORD | Re-escrow interval in hours |
ValidateKey |
String/DWORD | Validate key locally before escrow |
SkipUsers |
String | Comma-separated list of users to skip |
PostRunCommand |
String | Command to run after errors |
ApiKey |
String | API key for server authentication |
ApiKeyHeader |
String | Custom API key header name (default: X-API-Key) |
UseMtls |
String/DWORD | Enable mutual TLS authentication (true/1 or false/0) |
CertificateSubject |
String | Client certificate subject name for mTLS |
CertificateThumbprint |
String | Client certificate thumbprint for mTLS |
PfxPath |
String | Path to client PFX file (preferred file-based mTLS option) |
PfxPasswordCredential |
String | Windows Credential Manager target name holding the PFX passphrase |
ClientCertPath |
String | Path to client certificate PEM file (least preferred file-based mTLS option) |
ClientKeyPath |
String | Path to client private key PEM file (paired with ClientCertPath) |
Intune Custom OMA-URI Example:
- OMA-URI:
./Device/Vendor/MSFT/Registry/HKLM/SOFTWARE/Policies/Crypt/ManagedEncryption/ServerUrl - Data type: String
- Value:
https://crypt.example.com
For Intune proactive remediation compatibility:
| Code | Meaning |
|---|---|
| 0 | Success - key escrowed |
| 1 | BitLocker not enabled |
| 2 | No recovery password protector found |
| 3 | Network/server error (retry-able) |
| 4 | Configuration error |
| 5 | Key rotation failed |
| 6 | Insufficient permissions (requires administrator) |
| 7 | Authentication failed (invalid or missing API key) |
| 10 | Already escrowed, no action needed |
$result = & "C:\Program Files\Crypt\checkin.exe" verify
exit $LASTEXITCODE$result = & "C:\Program Files\Crypt\checkin.exe" escrow
exit $LASTEXITCODE- .NET 10 SDK
- Windows SDK (for code signing, optional)
# Full build with auto-signing
.\build.ps1
# Build without signing
.\build.ps1 -NoSign
# Build with specific certificate
.\build.ps1 -Sign -CertificateName "Your Certificate CN"
.\build.ps1 -Sign -Thumbprint "CERTIFICATE_THUMBPRINT"
# Debug build
.\build.ps1 -Configuration Debug
# Single architecture
.\build.ps1 -Runtime win-x64
.\build.ps1 -Runtime win-arm64The build script automatically detects code signing certificates from the Windows certificate store. For CI/CD pipelines, set:
SIGNTOOL_PATH- Path to signtool.exe- Use
-CertificateNameor-Thumbprintto specify the certificate
Logs are written to C:\ProgramData\CryptEscrow\Logs\CryptEscrow_YYYYMMDD.log
Log rotation is automatic with configurable retention (default: 30 days).
- Windows 10/11 or Windows Server 2016+
- BitLocker enabled on target drive
- Administrator privileges
- Network access to Crypt Server
- Intune CSP/OMA-URI Configuration Guide — detailed Intune setup with OMA-URI examples and PowerShell scripts
- Deployment Guide — Cimian deployment, testing, and monitoring
- Changelog — version history
- Example Configuration — fully commented config template
Inspired by:
- Crypt by Graham Gilbert (Mac client)
- crypt-bde by Bryan Demetris
- bitlocker2crypt by Johnny Ramos
- Crypt-Server by Graham Gilbert
MIT License - see LICENSE for details.