Photo by John Salvino on Unsplash

Microsoft’s Little Secret: Encrypting Passwords and Keys


Are you a cybersecurity professional? If yes, do you know if Windows encrypts your password? If you don’t know, then read on, and let’s look at Microsoft’s little secret.

In the password, Windows used the MD4 hashing method, and which meant that it was fairly easy to crack the password. But with Windows 2000, Microsoft took security seriously and integrated the Data Protection Application Programming Interface (DPAPI). It has since become a core part of many applications including Windows Credential Manager, Internet Explorer, and Outlook. Overall, it provides a simple API to encrypt and decrypt data. These days it is often used to encrypt the master key and the private keys within a public key pair.

A full analysis was performed by Burzstein and Picod [1]:

In terms of the encryption methods, they found that it varied depending on the operating system version:

  • Windows 2000 uses RC4 and HMAC-SHA-1 with one round of PBKDF2. Approximate security strength: 95,000 passwords/second.
  • Window XP uses 3DES and HMAC-SHA-1 with 4000 rounds of PBKDF2. Approximate security strength: 4,000 passwords/second.
  • Windows Vista uses 3DES and HMAC-SHA-1 with 24000 rounds of PBKDF2. Approximate security strength: 12 passwords/second.
  • Windows 7 and Windows 10 uses 256-bit AES-CBC and HMAC-SHA-512 with 5,600 rounds of PBKDF2. Approximate security strength: 10 passwords/second.

We can see that recent versions of Windows generally use PBKDF2 with a number of rounds. The more rounds that we have, generally the longer it will take to crack the password. Most modern versions now use AES encryption with CBC mode, and HMAC-SHA-512 for message authentication.

Basically, DPAPI works by protecting secrets using the user’s login secret. On a domain, we use the domain’s secret. So let’s use Powershell to encrypt a string [here]:

$pwd = 'qwerty123'
$securepwd = ConvertTo-SecureString -String $pwd -AsPlainText -Force
$encryptedpwd = ConvertFrom-SecureString -SecureString $securepwd
"Input: "+ $pwd
"Encrypted: " + $encryptedpwd
$dec = ConvertFrom-SecureString -SecureString $securepwd -AsPlainText
"Decrypted: " + $dec

A sample run shows [here]:

Input: qwerty123
Encrypted: 01000000d08c9ddf0115d1118c7a00c04fc297eb01000000e04794a8b647a145b23d1d0191029caf0000000002000000000010660000000100002000000019e358c8ffef427a6002feba277e5c56846fd6cdc34c0d3f61f1a33744023110000000000e8000000002000020000000031df856aff5e89017b6395edf8117ab90754cac0e391e7e9f42bd5fa42f1690200000009e0e10ffdd971a1eb4ce47a2de65dc1109cf6b2759ef23900f60212458920f644000000046f759f858c03ca2b3245406412a7c2ddc7ff34be74c5ea0a4c5ee501566980d8785d328908f26ae5a0484636d70e69992cc019503dbc34963564478590329df
Decrypted: qwerty123

The magic number of encrypted data is:

01 00 00 00 D0 8C 9D DF 01 15 D1 11 8C 7A 00 C0 4F C2 97 EB

If we parse the encrypted content we get:


If we try again we get:


And we can see that the first elements for the encrypted string does not change.

Overall, Windows has moved on from the poor hashing methods it has used in the past (such as with LMHash and NTHash), and now does proper encryption on the passwords. This includes with 256-bit AES, and where PBKDF2 is used to slow down the cracking of the password.


[1] Burzstein, E., & Picod, J. M. (2010). Recovering Windows Secrets and {EFS} Certificates Offline. In 4th USENIX Workshop on Offensive Technologies (WOOT 10).



Prof Bill Buchanan OBE
ASecuritySite: When Bob Met Alice

Professor of Cryptography. Serial innovator. Believer in fairness, justice & freedom. Based in Edinburgh. Old World Breaker. New World Creator. Building trust.