Skip to content

chgeuer/Windows-DPAPI-with-Zig

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Exploring the Windows Data Protection API (DPAPI) from Zig

This project features a little command line utility which reads encrypted data from stdin and writes to stdout.

The Microsoft Windows Data Protection API (DPAPI) features functions for encrypting/wrapping/protecting and decrypting/unwrapping/unprotecting data, namely CryptProtectData and CryptUnprotectData. These functions are defined in dpapi.h.

Compiling and running

The following command compiles a small CLI application (18kB on Windows):

zig build -Doptimize=ReleaseSmall

Then you pipe the contents of an encrypted file into the executable, and process the output like you wish. For example, on Windows, the Azure CLI stores all management tokens as JSON structure in an encrypted file in my .azure directory. The following pipeline pipes that file into the decryption utility and uses JQ to pretty-print parts of the JSON.

type %USERPROFILE%\.azure\msal_token_cache.bin | .\zig-out\bin\dpapi.exe unwrap  | jq.exe ".RefreshToken"

With the checked-in binaries, you can also do round-trip:

echo Hallo Welt | .\dpapi.exe wrap | .\dpapi.exe unwrap

gives

C:\github\chgeuer\Windows-DPAPI-with-Zig (main -> origin)
λ echo Hallo Welt | .\dpapi.exe wrap | .\dpapi.exe unwrap

Hallo Welt

C:\github\chgeuer\Windows-DPAPI-with-Zig (main -> origin)
λ 

Alternative in NET

The C# version would be along these lines (using System.Security.dll):

using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;

internal class Program
{
    static void Main(string[] args)
    {
        var input = "Hallo, Welt!";
        byte[] wrapped = Encrypt(input);
        File.WriteAllBytes(@"C:\Users\chgeuer\Desktop\zig2\dpapi_encrypted.bin", wrapped);

        Console.WriteLine(Convert.ToBase64String(wrapped));
        Console.WriteLine(Decrypt(wrapped));
    }

    private static byte[] Encrypt(string userData) =>
        ProtectedData.Protect(
            userData: Encoding.UTF8.GetBytes(userData),
            optionalEntropy: null,
            scope: DataProtectionScope.CurrentUser);

    private static string Decrypt(byte[] wrapped) =>
        Encoding.UTF8.GetString(
            ProtectedData.Unprotect(
                encryptedData: wrapped,
                optionalEntropy: null, 
                scope: DataProtectionScope.CurrentUser));
}

Releases

No releases published

Packages

No packages published

Languages