Jump to content

Simple PIN - Algorithm Exercise

Recommended Posts

I was reading an FAQ article about Microsoft's Hello 4 Business and there was a question about if H4B prevents the usage of simple PINs. 


They described the method they used to evaluate the delta between the PIN digit values to prevent constant deltas.  I thought the "problem" was interesting and sought out to code an algorithm to accomplish this.  It was a fun exercise in logic.  I tried to make it a efficient as I could think of and designed it to support PINs of variable lengths (>= 4) and thought I'd share what I came up with.  I am interested if anyone has any thoughts on performance or efficiency improvements.

;Inspiring Article - https://docs.microsoft.com/en-us/windows/security/identity-protection/hello-for-business/hello-faq#does-windows-hello-for-business-prevent-the-use-of-simple-pins

#include <StringConstants.au3>
#include <Array.au3>

Func _PINDeltas(ByRef $sPIN)
    ;Quick Error check to Ensure PIN is Numeric Only
    If Not StringIsDigit($sPIN) Then Return SetError(1, 0, -1)

    ;Quck Error Check to Verify PIN is at least four digits
    If StringLen($sPIN) <= 3 Then Return SetError(2, 0, -1)

    ;Setup PIN values Array and Delta values Array
    Local $aPIN = StringSplit($sPIN,"",$STR_NOCOUNT)
    Local $aDeltas[UBound($aPIN)-1]

    ;Setup Variables for Delta algorithm: Delta array index tracker, Current PIN value and Delta value tracker
    Local $iDeltaIndex = 0
    Local $iPINValue = $aPIN[$iDeltaIndex]
    Local $iDeltaCounter = 0

    ;Delta Algorithm
        ;If Current PIN position value + Delta > next PIN value, overflow to zero
        If $iPINValue + $iDeltaCounter > $aPIN[$iDeltaIndex + 1] Then $iPINValue -= 10
        ;If Current PIN position value + Delta = next PIN value, save Delta value and move to next PIN position
        If $iPINValue + $iDeltaCounter = $aPIN[$iDeltaIndex + 1] Then
            ;Save Delta value
            $aDeltas[$iDeltaIndex] = $iDeltaCounter
            ;Reset Delta value
            $iDeltaCounter = 0
            ;Increment Delta array index tracker
            $iDeltaIndex += 1
            ;Get next PIN value
            $iPINValue = $aPIN[$iDeltaIndex]
        ;Else increment Delta tracker value
            ;Increment Delta value
            $iDeltaCounter += 1
    ;Do until last Delta index is complete
    Until $iDeltaIndex > UBound($aDeltas)-1

    ;Return the Delta array
    Return $aDeltas

Func _PINIsSimple(ByRef $aDeltas)
    ;If ArrayUnique returns a single index Delta array, then the PIN is simple
    Return (UBound(_ArrayUnique($aDeltas,0,0,0,$ARRAYUNIQUE_NOCOUNT))=1) ? 1 : 0

;Generate PIN list using the examples on the MS article
Local $aPINs[]=["1111","1234","1357","9630","1593","7036","1231","1872"]
For $sPIN in $aPINs


;Generate 5 digit PINs
Local $aPINs[]=["11111","12345","13579","96307","15937","70369","12312","18723"]
For $sPIN in $aPINs

Func _IsPINSimple($sPIN)
    Local $aDeltas = _PINDeltas($sPIN)
    Local $sDeltas = "(" & _ArrayToString($aDeltas,",") & ")"
    Local $sMsg = (_PINIsSimple($aDeltas)=1) ? "has a constant delta of " & $sDeltas & ", so it is not allowed." : "does not have a constant delta " & $sDeltas & ", so it is allowed."
    ConsoleWrite("The PIN " & $sPIN & " " & $sMsg & @CRLF)


Edited by spudw2k
Link to post
Share on other sites
Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Create New...