Skip to content

windowsadmins/crypt-escrow

Repository files navigation

Crypt for Windows

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.

Features

  • 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

Mac Crypt-Inspired Features

  • 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)

Installation

Download Release

Download the latest release from GitHub Releases:

  • checkin-x64.exe - For Intel/AMD systems
  • checkin-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 to PATH as checkin.exe in C:\Program Files\Crypt\.

Build from Source

# Full build with auto-signing (if certificate available)
.\build.ps1

# Build without signing
.\build.ps1 -NoSign

# Build specific architecture
.\build.ps1 -Runtime win-x64

Quick Start

1. Configure the Server URL

# 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" /M

2. Escrow the BitLocker Key

checkin escrow

3. Verify Escrow Status

checkin verify

Commands

escrow

Escrows 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 validation

rotate

Rotates 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 validation

verify

Checks 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 validation

config

Manage 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 2

register-task

Registers 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

Configuration is loaded from (in order of precedence):

  1. Command-line options
  2. Environment variables
  3. Registry (CSP/OMA-URI from Intune)
  4. YAML configuration file

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

Environment Variables

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)

Authentication

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.

1. Windows Certificate Store (preferred)

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: My

Environment variables: CRYPT_CERT_SUBJECT, CRYPT_CERT_THUMBPRINT.

2. PFX file + Credential Manager passphrase

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 above

Environment variables: CRYPT_PFX_PATH, CRYPT_PFX_PASSWORD_CRED. If the PFX has no passphrase, omit pfx_password_credential.

3. PEM + .key file (least preferred)

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:R
server:
  auth:
    use_mtls: true
    client_cert_path: C:\ProgramData\ManagedEncryption\client.pem
    client_key_path:  C:\ProgramData\ManagedEncryption\client.key

Environment variables: CRYPT_CLIENT_CERT_PATH, CRYPT_CLIENT_KEY_PATH.

Registry Configuration (CSP/OMA-URI)

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

Exit Codes

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

Intune Proactive Remediation

Detection Script

$result = & "C:\Program Files\Crypt\checkin.exe" verify
exit $LASTEXITCODE

Remediation Script

$result = & "C:\Program Files\Crypt\checkin.exe" escrow
exit $LASTEXITCODE

Building

Prerequisites

  • .NET 10 SDK
  • Windows SDK (for code signing, optional)

Build Commands

# 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-arm64

Code Signing

The build script automatically detects code signing certificates from the Windows certificate store. For CI/CD pipelines, set:

  • SIGNTOOL_PATH - Path to signtool.exe
  • Use -CertificateName or -Thumbprint to specify the certificate

Logging

Logs are written to C:\ProgramData\CryptEscrow\Logs\CryptEscrow_YYYYMMDD.log

Log rotation is automatic with configurable retention (default: 30 days).

Requirements

  • Windows 10/11 or Windows Server 2016+
  • BitLocker enabled on target drive
  • Administrator privileges
  • Network access to Crypt Server

Additional Documentation

Credits

Inspired by:

License

MIT License - see LICENSE for details.

About

BitLocker recovery key escrow to Crypt Server with key rotation support

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors