Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neil-sabol/3d48308b57f25da59dd6b28b34d9d42e to your computer and use it in GitHub Desktop.
Save neil-sabol/3d48308b57f25da59dd6b28b34d9d42e to your computer and use it in GitHub Desktop.
See https://blog.neilsabol.site/post/yubikey-manager-ykman-powershell-cli-duo-mfa-oath-totp-token/ . This snippet uses the ykman command to generate an OATH-TOTP credential on the Yubikey which can be used with services that require you to supply your own TOTP secret.
# Create an alias for ykman pointing the install location
set-alias ykman "$env:programfiles\Yubico\YubiKey Manager\ykman.exe"
# Get the Yubikey's serial number with ykman
# Not required but will be used to import into Duo later (to test)
$serialNumber = ykman info | where { $_ -like "Serial number:*" } |
%{ $_ -replace "Serial number: ",""}
# Generate a random 40 character hex secret
# See https://codegolf.stackexchange.com/questions/58442/generate-random-uuid - thanks Forty3
# The length of the hex secret must be divisible by 5 to leverage HumanEquivalentUnit's
# byte to base32 conversion code below - I used a 40 digit secret
$hexSecret = (((40)|%{((1..$_)|%{('{0:X}' -f (random(16)))})}) -Join "").ToLower()
# Convert the hex secret key to base32 (with byte array as an intermediary)
# This seemed like the easier path vs. generating a base32 secret and converting back to hex
# First, from hex to bytes
# See https://gist.github.com/jonfriesen/234c7471c3e3199f97d5
# ( function Convert-HexToByteArray ) - thanks Jon Friesen
$byteSecret = $hexSecret -replace '^0x', '' -split "(?<=\G\w{2})(?=\w{2})" |
%{ [Convert]::ToByte( $_, 16 ) }
# Then, from bytes to base32
# See https://humanequivalentunit.github.io/Base32-coding-the-scripting-way/
# Thanks humanequivalentunit
$byteArrayAsBinaryString = -join $byteSecret.ForEach{
[Convert]::ToString($_, 2).PadLeft(8, '0')
}
$base32Secret = [regex]::Replace($byteArrayAsBinaryString, '.{5}', {
param($Match)
'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'[[Convert]::ToInt32($Match.Value, 2)]
}).ToLower()
# Create a new OATH-TOTP credential in the Yubikey for Yubico Authenticator
ykman oath add -o TOTP -d 6 -p 30 "DuoTest" "$base32Secret"
# Write out the TOTP token info in Duo CSV format
# Not required but will be used to import into Duo for testing
write-host "$serialNumber,$hexSecret"
# Clear variables
$serialNumber = ""
$hexSecret = ""
$byteSecret = ""
$base32Secret = ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment