Thursday, March 3, 2016

Calculate the entropy of a string (i.e. a password) with PowerShell

As with my other PowerShell stuff, this was made for fun and might make it's way into something later. The details of what the script is for, and the many assumptions it makes are in the code. Short story, this function will give you the bits of entropy in a provided string. Usually such a thing is interesting when trying to determine the "strength" of a password. The larger the number, the stronger the password (because the amount of space that would need to be explored to find the password via brute force is larger...has more entropy). The code notes a link that discusses the topic in MUCH greater detail.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<#
.SYNOPSIS
    Calculate the entropy (in bits) of the provided string
.DESCRIPTION
    Based primarily upon discussion here, https://technet.microsoft.com/en-us/library/cc512609.aspx
    this function will calculate the entropy of the provided string, returning an integer result
    indicating bits of entropy. Numerous assumptions MUST be made in the calculation of this
    number. This function takes the easiest approach, which you can also read as "lazy" at best
    or misleading at worst.

    We need to figure out the "size" of the space from which the symbols in the string are drawn - after
    all the value we're calculating is not absolute in any way, it's relative to some max/min values. We
    make the following assumptions in this function:
    --if there is a lower case letter in the provided string, assume it's possible any lower case letter could
      have been used. Assume the same for upper, numeric, and special chars.
    --by "special characters" we mean the following: ~`!@#$%^&*()_-+={}[]|\:;"'<,>.?/
    --by "letters", we mean just the letters on a U.S. keyboard.
    --no rules regarding which symbols can appear where, e.g. can't start with a number.
    --no rules disallowing runs, e.g. sequential numbers, sequential characters, etc.
    --no rules considering non-normal distribution of symbols, e.g. "e" just as likley to appear as "#"
    The net impact of these assumptions is we are over-calculating the entropy so the best use of this
    function is probably for comparison between strings, not as some arbiter of absolute entropy.
.PARAMETER s
 The string for which to calculate entropy.
.EXAMPLE
 get-StringEntropy -s "JBSWY3DPEHPK3PXP"
.NOTES  
 FileName: get-StringEntropy
 Author: nelsondev1
#>

function get-StringEntropy {
[CmdletBinding()]
Param(
    [String]$s
)

$specialChars = @"
~`!@#$%^&*()_-+={}[]|\:;"'<,>.?/
"@

    $symbolCount = 0 # running count of our symbol space

    if ($s -cmatch "[a-z]+") {
        $symbolCount += 26
        Write-Verbose "$s contains at least one lower case character. Symbol space now $symbolCount"
    }
    if ($s -cmatch "[A-Z]+") {
        $symbolCount += 26
        Write-Verbose "$s contains at least one upper case character. Symbol space now $symbolCount"
    }
    if ($s -cmatch "[0-9]+") {
        $symbolCount += 10
        Write-Verbose "$s contains at least one numeric character. Symbol space now $symbolCount"
    }

    # In the particular use, I found trying to regex/match...challenging. Instead, just going
    # to iterate and look for containment.
    $hasSpecialChars = $false
    foreach ($c in $specialChars.ToCharArray())
    {
        if ($s.Contains($c))
        {
            $hasSpecialChars = $true
        }
    } 
    if ($hasSpecialChars) {
        $symbolCount += $specialChars.Length
        Write-Verbose "$s contains at least one special character. Symbol space now $symbolCount"
    }

    # in a batch mode, we might want to pre-calculate the possible values since log is slow-ish.
    # there wouldn't be many unique options (eg 26, 26+26, 26+10, 26+16, 26+26+10, etc.)
    # ...though in comparison to performing the above regex matches it may not be a big deal.
    # anyway...

    # Entropy-per-symbol is the base 2 log of the symbol space size
    $entroyPerSymbol = [Math]::Log($symbolCount) / [Math]::Log(2)
    Write-Verbose "Bits of entropy per symbol calculated to be $entroyPerSymbol"

    $passwordEntropy = $entroyPerSymbol * $s.Length

    Write-Verbose "Returning value of $passwordEntropy"
    return $passwordEntropy # this is the bits of entropy in the starting string
}

Saturday, February 20, 2016

WeatherClock - Part 3

Let's look at the server-side portions first. We'll do this in two parts and this initial one is trivial. We're going to be using the Forecast.IO API at https://developer.forecast.io/ to source our weather data. I'm going to be writing my server portion of this app in .net b/c I like it and I love Azure. It's just super quick and simple. Rather than writing my own wrapper to consume the Forecast.IO service, I'm going to use some lovely code found here: https://github.com/f0xy/forecast.io-csharp . This wrapper is PERFECT for what I need, and only needed two small enhancements.

First, the wrapper as-is does not include Precipitation Type for the minute-by-minute forecast. Easy enough to add, we just PrecipType to MinuteForecast in https://github.com/f0xy/forecast.io-csharp/blob/master/forecast.io/Entities/ForecastIOResponse.cs

Second, the wrapper needs an API key when it calls Forecast.IO. Rather than embedding the key in code, I made the trivial change to have the code pull the API key from my Azure app settings. This is a better solution as it keeps secrets completely removed from the code base.

Ok, that's a description of half our server side. Next post will wrap up the server-side code and provide reference to the full source.

Monday, January 4, 2016

WeatherClock - Part 2


First, the hardware. I got EVERYTHING from Adafruit.com. We have three primary components: An Arduino, a Wifi shield, and 4 1/4-ring Neopixels. I also got all my bits of wire and solder and sundry components from Adafruit as well.

Let's look at the hardware first. Here's what we're building. Note in this diagram the LED ring depicted is NOT the 60 element ring, but I think the idea is pretty clear.

Following the instructions from Adafruit, solder together the 4 Neopixel 1/4-ring pieces into a single ring. http://www.adafruit.com/products/1768. I'll just re-emphasize some of the more salient parts of this. While you DO want all four joints of your ring to have the 5V and ground connections soldered, make sure you DON'T solder together the data pads of the final joint -- you only want that data signal going in one side. I chose to have my power, ground, and data wires all leading off the same joint. I don't think it's necessary, but it looks cleaner to me.

After assembling the ring, it's a good idea to connect your ring to the Arduino and fire up a sketch to exercise the ring. You want to be sure that all the LEDs light as expected, otherwise when stuff doesn't work later you won't know if it's your hardware or your software. That's no fun. Your pre-requisite task for this is to have downloaded and installed the Arduino IDE and downloaded the Neopixel libraries from Adafruit, available on GitHub. There are plenty of tutorials available to walk you through how to use this software, so I won't bother here.  I discovered when I first ran the example sketches that only half my ring lit up, with a couple of odd LEDs here and there turned on for the remainder of the ring. Turns out I had a cold solder joint on the data pads between the second and third rings, so signal wasn't making it through. Better to find these problems now than later!

Some additional notes: I also followed the precautions noted by Adafruit to place a large capacitor across the power supply and put a small resistor inline with the data connection. They know more than me about electronics, so I did it. It works.

Your next step is assemble the WiFi shield, which is nothing more than soldering on the headers so you can attach the shield to the Arduino. As with the ring, I fired up example sketches to be sure that the WiFi shield was working properly. Below is a pic showing the wired up hardware with a trivial Aruduino sketch lighting up the ring with simple colors.



At this point, we have hardware. At the end of this series of posts, I'll provide a complete parts list for what's been built. Now we're ready to write some code to make the hardware do something...

WeatherClock - Part 1

This is first in a series of posts detailing the build and programming for what I'm calling a "Weather Clock." The folks at AccuWeather have nice mobile app that includes a real-time, minute-by-minute forecast of precipitation for the next two hours. What's neat about this is the visualization. They present a ring, with "right now" at the top and the minutes flowing along clockwise, just a like a -- well -- a clock. Each minute on the clock face is colored to represent the type and intensity of precipitation expected for the next two hours. Here's a picture, showing light rain starting in about 26 minutes, heavier rain around 90.



I always liked this visual, and thought it would be fun to build one of these weather clocks and hang it on a wall. You could certainly do this mostly/entirely in software by building an app to run on a tablet, then hang the tablet on the wall. But in this case I wanted to tinker around with actually building dedicated hardware. Like many people drawn to building internet-connected devices, my background is in software -- not hardware -- so I approached this project with a little trepidation. Turns out there wasn't much to fear, this came together pretty well (I think). By the end of this series of posts, I'll have provided links to everything -- the hardware components, the code, etc. I welcome any and all comments about how this could've been done better, or differently, or whatever.
 

Friday, December 4, 2015

Mapping Java WebSphere Cipher Suite Names to IBM Host Cipher Suites

We recently went through an issue at work that required digging into the cipher suite negotiation between a WebSphere client and a web service exposed via CICS. The trickiness of this was based on how these two side expose their cipher suites to admins. On the Host side, the cipher suites are presented as a string of hex codes identifying the unique cipher IDs. On the WebSphere side, the suites are listed by name -- but the WebSphere cipher suite names do not match up with the cipher suite names in host documentation. I tried for a bit to find a cross reference somewhere on web but gave up. So I made my own which I present below. I did this by looking at openJDK's CipherSuite.java which maps the java cipher suite names to cipher IDs. Then I matched those cipher IDs to the Host cipher suite names. Trival. This is not a complete list of all available ciphers on these platforms -- it was what we needed for our current problem.
 
As a final bit of fun with names, note that depending on the particular Java you are using, the JAVA names may interchange the three-letter acronyms TLS and SSL. For example, the IBMJSSE2 suite does this. Refer to documentation here: https://www-01.ibm.com/support/knowledgecenter/SSYKE2_7.0.0/com.ibm.java.security.component.71.doc/security-component/jsse2Docs/ciphersuites.html

Hope this helps someone.


CIPHER ID
CICS NAME
JAVA Name
35
TLS1_RSA_WITH_AES_256_SHA
TLS_RSA_WITH_AES_256_CBC_SHA
36
TLS1_DH_DSS_WITH_AES_256_SHA
N/A WEBSPHERE
37
TLS1_DH_RSA_WITH_AES_256_SHA
N/A WEBSPHERE
38
TLS1_DHE_DSS_WITH_AES_256_SHA
TLS_DHE_DSS_WITH_AES_256_CBC_SHA
39
TLS1_DHE_RSA_WITH_AES_256_SHA
TLS_DHE_RSA_WITH_AES_256_CBC_SHA
2F
TLS1_RSA_WITH_AES_128_SHA
TLS_RSA_WITH_AES_128_CBC_SHA
30
TLS1_DH_DSS_WITH_AES_128_SHA
N/A WEBSPHERE
31
TLS1_DH_RSA_WITH_AES_128_SHA
N/A WEBSPHERE
32
TLS1_DHE_DSS_WITH_AES_128_SHA
TLS_DHE_DSS_WITH_AES_128_CBC_SHA
33
TLS1_DHE_RSA_WITH_AES_128_SHA
TLS_DHE_RSA_WITH_AES_128_CBC_SHA
0A
SSL3_RSA_DES_192_CBC3_SHA
SSL_RSA_WITH_3DES_EDE_CBC_SHA
16
SSL3_EDH_RSA_DES_192_CBC3_SHA
SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
13
SSL3_EDH_DSS_DES_192_CBC3_SHA
SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
10
SSL3_DH_RSA_DES_192_CBC3_SHA
SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA
0D
SSL3_DH_DSS_DES_192_CBC3_SHA
SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA
09
SSL3_RSA_DES_64_CBC_SHA
SSL_RSA_WITH_DES_CBC_SHA
15
SSL3_EDH_RSA_DES_64_CBC_SHA
SSL_DHE_RSA_WITH_DES_CBC_SHA
12
SSL3_EDH_DSS_DES_64_CBC_SHA
SSL_DHE_DSS_WITH_DES_CBC_SHA
0F
SSL3_DH_RSA_DES_64_CBC_SHA
SSL_DH_RSA_WITH_DES_CBC_SHA
0C
SSL3_DH_DSS_DES_64_CBC_SHA
SSL_DH_DSS_WITH_DES_CBC_SHA

Friday, November 20, 2015

When read-only is too much -- how to obtain programmatic access to EMC RSA Data Protection Manager crypto keys.

The audience for this post is quite limited - not many folks (relatively) use EMC's RSA DPM product. I'm gonna make NO effort to really describe how the RSA DPM system works. If you know the system, this will all make sense. If you do not, it probably won't though the general color and ideas should resonate. In addition, what I'm about to show is a known behavior -- the developer guides for the RSA DPM (at least for java) recommend the steps necessary to mitigate what I'm showing here. The c# and c++ guides make no mention of this that I could find, but the same behavior exists on those frameworks as well. What's not really called out clearly is what the risk entails.

The RSA DPM is a cryptography and key management solution for enterprises. The server-side manages cryptography keys, and clients obtain the keys when needed to perform crypto operations locally on the client. The clients do this by importing the necessary library files, and "registering" themselves with the server. The registration process essentially sets up a certificate-based authentication mechanism between client and server. Once registration is completed, a certificate and some "fingerprint" files are generated. At run-time, the client requests keys from the server over the authenticated channel using the certificate. The "fingerprint" files do some magic to ensure that the client system has not been changed in some way that might indicate compromise or movement of the client.

Here's the "weakness". If the "bad-guy" has read-only access to these registration files, it is a TRIVIAL matter to copy the files to another location on the same system and use the files to make perfectly valid calls to the RSA DPM server via a small custom application, accessing all the crypto keys that should (by intent) only be accessible to the orignal client application.

The example below is in java. You can do the same for c# or c++. The idea/approach is equally valid there. Our outline of activity:
1) Copy RSA DPM registration files to a new location on the original client that is write-able by the user.
2) Use a custom application making reference to these copied registration files to pull crypto keys from the RSA DPM server. This is NOT hard -- the RSA DPM client modules come pre-packaged with sample applications to help developers learn how to use the client. We'll just use one of these sample programs.
3) ??? Well, you now have crypto keys. That's not good for whoever the keys belong to. How you approach mitigating this is up to you and probably depends on how your business operates. It should be NO surprise that the "fix" for this problem is:
4) Lock down read access to the original client registration files. Only the application using these files needs access to them, so nothing/no one else should be able to read them. Basic security principles here. Lock. Down. Access.

Here is the process and minimal code samples that walk through the steps to access crypto keys. Whatever system you are on will almost certainly differ in the details, primarily paths and file names. But this should be enough to get the idea across. We're going to be demonstrating this on a *nix system running WebSphere that has an app incorporating the EMC RSA DPM. This assumes (as I've described above) that the bad guy has read access to the application files, and write/execute access to some path, somewhere, on the same server.

1) Copy all the "registration files" to a new writeable location. These files are (assuming the app developers follow the nomenclature of the RSA DPM examples).
*.p12
*.bin
*.cache
Optionally, copy the RSA DPM client jar files, too. You can always just reference them in their existing location when you run your app later to extract keys.

2) Do some environment setup. Nothing fancy here, we're essentially just setting ourselves up for running java
export Java_Home=/apps/websphere/java/jre
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/apps/websphere/java/jre/bin:/apps/websphere/java/jre/bin/classic:/apps/websphere/java/jre/bin
export CLASSPATH=/home/usr/me/rsadpm/*.*

3) Execute one of the sample RSA DPM client apps, specifying the copied registration files.  Note that I'm being a little obtuse here and NOT showing the small modifications made to the demo EncryptAndDecryptData code -- the changes from how this file is delivered from EMC are minor. Just change the path references, and update the the config file to reference the files you copied in step 1.
/apps/websphere/java/jre/bin/java -cp /home/usr/me/rsadpm:/home/usr/me/rsadpm/certj.jar:/home/usr/me/rsadpm/cryptoj.jar:/home/usr/me/rsadpm/cryptojFIPS.jar:/home/usr/me/rsadpm/kmsclient.jar:/home/usr/me/rsadpm/LB.jar:/home/usr/me/rsadpm/LBImpl.jar:/home/usr/me/rsadpm/log4j-1.2.15.jar:/home/usr/me/rsadpm/sslj.jar rkmjc.simpleapi.EncryptAndDecryptData

 4) Here's what output looks like. In this, I'm simply encrypting/decrypting a hard-coded value using a key obtained from the server. It'd be just as easy to export the key to file or do whatever else you wanted.

Running Sample EncryptAndDecryptData
Plain Text:
  0000: 31 32 33 34 31 32 33 34 31 32 33 34 31 32 33 34 [1234123412341234]

Cipher Text:
  0000: 52 4b 4d 43 32 31 30 00 ff ff ff ff 00 00 00 05 [RKMC210.........]
  0010: 75 75 69 64 00 00 00 00 10 16 68 f2 8c 96 ca 4a [uuid......h....J]
  0020: 86 9c f4 f0 83 30 f6 9a db ff ff ff ff 00 00 00 [.....0..........]
  0030: 05 6f 72 69 64 00 00 00 00 20 0b 76 58 dc 76 07 [.orid.... .vX.v.]
  0040: 59 7e c5 9d f3 ba 66 cd f9 20 a2 fb 82 8f fd 2b [Y~....f.. .....+]
  0050: 88 fe 1b 05 2e a8 a2 6c 63 2b ff ff ff ff 00 00 [.......lc+......]
  0060: 00 05 63 73 75 6d 00 00 00 00 20 9f e4 86 dd 57 [..csum.... ....W]
  0070: 2a 72 fa 9f cb 08 e6 d5 e8 79 14 89 3d a9 05 17 [*r.......y..=...]
  0080: bd 03 94 b7 ea 9d 73 8a 07 3e f8 ce d8 18 71 e8 [......s..>....q.]
  0090: 69 c3 02 16 90 65 56 ff 28 8f 29 d8 c3 63 85 6c [i....eV.(.)..c.l]
  00a0: 30 1a c9 72 7a b3 15 d8 fe c6 5c                [0..rz.....\     ]

Recovered Plain Text:
  0000: 31 32 33 34 31 32 33 34 31 32 33 34 31 32 33 34 [1234123412341234]

Successful Ending EncryptAndDecryptData


So, what's the takeaway here? If you are using the EMC RSA DPM client, please be sure to lock down access to the DPM files -- NOTHING should be able to get to them that doesn't absolutely need them. Otherwise you open yourself to exfiltration of keys.


Google Authenticator One Time Passwords with PowerShell

I like two-factor authentication. Hopefully you do, too. Google Authenticator's OTP is a very popular app for using 2FA. The code below implements one-time passwords and is entirely interoperable with Google Authenticator. Details for use are in the function headers, and I should point out here that the bulk of the smarts in this code are simply translated from a javascript implementation I found online (and credit in the code). Why would you want this in PowerShell? No idea! But isn't in fun to know/see how this stuff works?




  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
<#
.SYNOPSIS

 Implementation of the Time-based One-time Password Algorithm used by Google Authenticator.



.DESCRIPTION

 As described in http://tools.ietf.org/id/draft-mraihi-totp-timebased-06.html, the script generates a one-time password based on a shared secret key and time value.

 This script generates output identical to that of the Google Authenticator application, but is NOT INTENDED FOR PRODUCTION USE as no effort has been made to code securely or protect the key. For demonstration-use only.

 Script code is essentially a transation of a javascript implementation found at http://jsfiddle.net/russau/uRCTk/

 Output is a PSObject that includes the generated OTP, the values of intermediate calculations, and a URL leading to a QR code that can be used to generate a corresponding OTP in Google Authenticator applications.
 
 The generated QR code contains a URL that takes the format "otpauth://totp/<email_address_here>?secret=<secret_here>", for example: otpauth://totp/tester@test.com?secret=JBSWY3DPEHPK3PXP

 The generated OTP is (obviously) time-based, so this script outptu will only match Google Authenticator output if the clocks on both systems are (nearly) in sync.

 The acceptable alphabet of a base32 string is ABCDEFGHIJKLMNOPQRSTUVWXYZ234567.

 Virtually no parm checking is done in this script. Caveat Emptor.



.PARAMETER sharedSecretKey

 A random, base32 string shared by both the challenge and reponse side of the autheticating pair. This script mandates a string length of 16.



.EXAMPLE

 .\Get-OTP.ps1 -sharedSecret "JBSWY3DPEHPK3PXP" | Select SharedSecret, Key, Time, HMAC, URL, OTP


.NOTES
  
 FileName: Get-OTP.ps1
 Author: Jim Nelson nelsondev1

#>
[CmdletBinding()]
param
(
 [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
 [ValidateLength(16,16)]
 [string]$sharedSecret
)



#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# Converts the supplied Int64 value to hexadecimal.
#------------------------------------------------------------------------------
function Convert-DecimalToHex($in)
{
 return ([String]("{0:x}" -f [Int64]$in)).ToUpper()
}

#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# Converts the supplied hexadecimal value Int64.
#------------------------------------------------------------------------------
function Convert-HexToDecimal($in)
{
 return [Convert]::ToInt64($in,16)
}

#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# Converts the supplied hexadecimal string to a byte array.
#------------------------------------------------------------------------------
function Convert-HexStringToByteArray($String)
{
 return $String -split '([A-F0-9]{2})' | foreach-object { if ($_) {[System.Convert]::ToByte($_,16)}}
}

#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# Converts the supplied base32 string to a hexadecimal string
#------------------------------------------------------------------------------
function Convert-Base32ToHex([String]$base32)
{
 $base32 = $base32.ToUpper()
 $base32chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
 $bits = ""
 $hex = ""

 # convert char-by-char of input into 5-bit chunks of binary
 foreach ($char in $base32.ToCharArray())
 {
  $tmp = $base32chars.IndexOf($char)
  $bits = $bits + (([Convert]::ToString($tmp,2))).PadLeft(5,"0")
 }
 
 # leftpad bits with 0 until length is a multiple of 4
 while ($bits.Length % 4 -ne 0)
 {
  $bits = "0" + $bits
 }
 
 # convert binary chunks of 4 into hex
 for (($tmp = $bits.Length -4); $tmp -ge 0; $tmp = $tmp - 4)
 {
  $chunk = $bits.Substring($tmp, 4);
  $dec = [Convert]::ToInt32($chunk,2)
  $h = Convert-DecimalToHex $dec
  $hex = $h + $hex  
 }

 return $hex
}


#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# Get the currentUnix epoch (div 30) in hex, left-padded with 0 to 16 chars
#------------------------------------------------------------------------------
function Get-EpochHex()
{
 # this line from http://shafiqissani.wordpress.com/2010/09/30/how-to-get-the-current-epoch-time-unix-timestamp/
 $unixEpoch = ([DateTime]::Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000
 $h = Convert-DecimalToHex ([Math]::Floor($unixEpoch / 30))
 return $h.PadLeft(16,"0")
}

#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# Get the HMAC signature for the supplied key and time values.
#------------------------------------------------------------------------------
function Get-HMAC($key, $time)
{
 $hashAlgorithm = New-Object System.Security.Cryptography.HMACSHA1
 $hashAlgorithm.key = Convert-HexStringToByteArray $key
 $signature = $hashAlgorithm.ComputeHash((Convert-HexStringToByteArray $time))
 $result = [string]::join("", ($signature | % {([int]$_).toString('x2')}))
 $result = $result.ToUpper()
 return $result
}

#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# Get the OTP based on the supplied HMAC
#------------------------------------------------------------------------------
function Get-OTPFromHMAC($hmac)
{
 $offset = Convert-HexToDecimal($hmac.Substring($hmac.Length -1))
 $p1 = Convert-HexToDecimal($hmac.Substring($offset*2,8))
 $p2 = Convert-HexToDecimal("7fffffff")
 [string]$otp = $p1 -band $p2
 $otp =  $otp.Substring($otp.Length - 6, 6)
 return $otp
}

# -------------------------------------------------------------------------------------------------------
# -------------------------------------------------------------------------------------------------------
# -------------------------------------------------------------------------------------------------------
# MAIN PROGRAM
# -------------------------------------------------------------------------------------------------------
# -------------------------------------------------------------------------------------------------------
$reportObject = New-Object PSObject –Property @{'SharedSecret' = "";
                                      'Key'   = "";
            'Time'   = "";
            'HMAC'   = "";
            'OTP'   = "";
            'URL'   = "";
                                     }

#google can generate a QR code of the secret for their authenticator app at this url...
$email = "look@that.com"
$url = "https://chart.googleapis.com/chart?chs=200x200&cht=qr&chl=200x200&chld=M|0&cht=qr&chl=otpauth://totp/" + $email + "%3Fsecret%3D" + $sharedSecret

$key  = Convert-Base32ToHex $sharedSecret
$time = Get-EpochHex
$hmac = Get-HMAC $key $time
$otp  = Get-OTPFromHMAC $hmac

$reportObject.SharedSecret = $sharedSecret
$reportObject.Key = $key
$reportObject.Time = $time
$reportObject.HMAC = $hmac
$reportObject.OTP = $otp
$reportObject.URL = $url

$reportObject