title: How to programatically get the Enforce Password History group policy setting?
body: <p>How can i programatically get the <a href="https://technet.microsoft.com/en-us/library/cc758950%28v=ws.10%29.aspx?f=255&amp;MSPPError=-2147217396" rel="nofollow"><strong>Enforce Password History</strong></a> group policy setting?</p>
  
  <h2>Research Effort</h2>
  
  <p>You can find the Group Policy option under:</p>
  
  <blockquote>
    <p>**Computer Configuration\Windows Settings\Security Settings\Account Policies\Password Policy**</p>
    
    <p>Enforce password history</p>
    
    <p>This security setting determines the number of unique new passwords that have to be associated with a user account before an old password can be reused. The value must be between 0 and 24 passwords.</p>
    
    <p>This policy enables administrators to enhance security by ensuring that old passwords are not reused continually.</p>
  </blockquote>
  
  <p>Like all group policy options, it is stored in the registry. Unfortunately it is stored in an undocumented registry location:</p>
  
  <blockquote>
    <p>HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account\F</p>
  </blockquote>
  
  <p>In an <a href="http://www.beginningtoseethelight.org/ntsecurity/index.htm#BB4F910C0FFA1E43" rel="nofollow">undocumented binary blob format</a>.</p>
  
  <p>There <strong><em>is</em></strong> a WMI class <a href="https://msdn.microsoft.com/en-us/library/aa375062.aspx" rel="nofollow"><strong>RSOP_SecuritySettingBoolean</strong></a>, but without any context, it's just a name hanging out there - which i have no idea how to read through COM/native.</p>
  
  <h2>NetValidatePasswordPolicy</h2>
  
  <p>Windows does provide an <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa370661%28v=vs.85%29.aspx?f=255&amp;MSPPError=-2147217396" rel="nofollow"><code>NetValidatePasswordPolicy</code> API</a> that will allow it to validate your password for things like:</p>
  
  <ul>
  <li>too many bad attempts</li>
  <li>account lockout</li>
  <li>lockout automatic reset</li>
  <li>minimum password age</li>
  <li>maximum password age</li>
  <li>password reuse</li>
  </ul>
  
  <p>and it will do all these things following the group policy in effect on the computer. And it all works great, except for password history.</p>
  
  <p>The function requires you to pass a list of password hashes, e.g.:</p>
  
  <ul>
  <li><code>$2a$14$mACnM5lzNigHMaf7O1py1OLCBgGL4tYUF0N/4rS9CwDsI7ytwL4D6</code></li>
  <li><code>$2a$14$mACnM5lzNigHMaf7O1py1O3vlf6.BA8k8x3IoJ.Tq3IB/2e7g61Km</code></li>
  <li><code>$2a$12$.TtQJ4Jr6isd4Hp.mVfZeuh6Gws4rOQ/vdBczhDx.19NFK0Y84Dle</code></li>
  <li><code>$2a$12$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm</code></li>
  </ul>
  
  <p>as well as the hash of the new candidate password, e.g.:</p>
  
  <ul>
  <li><code>$2a$10$1JsBs47iuMNsV166PKV.u.56hlT5/tRe9V5t5FIdfA0axpDSQuNN</code></li>
  </ul>
  
  <p>This will cause <strong>NetValidatePasswordPolicy</strong> to check if your current hash matches any of the existing hashes. Unfortunately, the entire concept of checking previous password hashes only works when you use a weak password algorithm (<a href="http://www.passcape.com/index.php?section=docsys&amp;cmd=details&amp;id=28#41" rel="nofollow">such as PBKDF2 that Windows uses</a>).</p>
  
  <p>Because i use a modern, <em>expensive</em>, <strong>salted</strong>, password hashing algorithm (BCrypt/SCrypt), a hash cannot be deterministically generated from a password alone - i can't simply check the old list. I would have to rehash the user's new password against <strong>every</strong> previously stored salt. </p>
  
  <ul>
  <li>not only is this an expensive operation; potentially taking 12 seconds to check all 24 stored hashes</li>
  <li>i don't know when to stop, because i don't know the Password History group policy value (e.g. i would be checking all 24 stored hashes, when i only need to check zero).</li>
  </ul>
  
  <p>I have considered calling <code>NetValidatePasswordPolicy</code> with a dummy list of 24 stored password hashes, e.g.:</p>
  
  <ul>
  <li><code>a</code></li>
  <li><code>b</code></li>
  <li><code>c</code></li>
  <li><code>d</code></li>
  <li>...</li>
  <li><code>v</code></li>
  <li><code>w</code></li>
  <li><code>x</code></li>
  </ul>
  
  <p>The API will then tell me that it password has did not match any in the <code>n</code> history. But the API is also designed to return to you what you have to keep. It <em>might</em> then return:</p>
  
  <ul>
  <li><code>$2a$10$1JsBs47iuMNsV166PKV.u.56hlT5/tRe9V5t5FIdfA0axpDSQuNN</code></li>
  <li><code>a</code></li>
  <li><code>b</code></li>
  <li><code>c</code></li>
  </ul>
  
  <p>And from that i might be able to infer that the password history length is <strong>four</strong>.</p>
  
  <p>But i've not gotten there yet.</p>
  
  <p>I'm three days into this, and losing patience.</p>
  
  <ul>
  <li>why did Microsoft obfuscate the group policy?</li>
  <li>why did Microsoft not allow people to read it?</li>
  <li>why is it undocumented?</li>
  <li>how do i get it all the same?</li>
  </ul>