Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -362,4 +362,5 @@ MigrationBackup/
# Fody - auto-generated XML schema
FodyWeavers.xsd
/.vscode/launch.json
/powershellYK.psd1
/powershellYK.psd1
/.cursorrules
20 changes: 17 additions & 3 deletions Module/Cmdlets/OTP/SetYubikeyOTP.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@
/// Set-YubiKeyOTP -Slot ShortPress -HOTP -Base32Secret "QRFJ7DTIVASL3PNYXWFIQAQN5RKUJD4U" -AppendCarriageReturn
///
/// .EXAMPLE
/// # Configure HOTP with hex encoded secret and carriage return
/// Set-YubiKeyOTP -Slot ShortPress -HOTP -HexSecret "0102030405060708090a0b0c0d0e0f1011121314" -AppendCarriageReturn
///
/// .EXAMPLE
/// # Configure HOTP with TAB before OTP code for easier form navigation
/// Set-YubiKeyOTP -Slot ShortPress -HOTP -Base32Secret "QRFJ7DTIVASL3PNYXWFIQAQN5RKUJD4U" -SendTabFirst
///
Expand Down Expand Up @@ -158,6 +162,10 @@ public class SetYubikeyOTPCommand : PSCmdlet
[Parameter(Mandatory = false, ValueFromPipeline = false, HelpMessage = "Base32 encoded secret key for HOTP", ParameterSetName = "HOTP")]
public string? Base32Secret { get; set; }

// Hex encoded secret key for HOTP mode
[Parameter(Mandatory = false, ValueFromPipeline = false, HelpMessage = "Hex encoded secret key for HOTP", ParameterSetName = "HOTP")]
public string? HexSecret { get; set; }

// Use 8 digits instead of 6 for HOTP mode
[Parameter(Mandatory = false, ValueFromPipeline = false, HelpMessage = "Use 8 digits instead of 6 for HOTP", ParameterSetName = "HOTP")]
public SwitchParameter Use8Digits { get; set; }
Expand Down Expand Up @@ -326,12 +334,18 @@ protected override void ProcessRecord()
Memory<byte> _HOTPsecretKey = new Memory<byte>(new byte[20]);
ConfigureHotp configureHOTP = otpSession.ConfigureHotp(Slot);

// Handle Secret Key configuration
// Handle Secret Key configuration using Base32
if (Base32Secret != null)
{
_HOTPsecretKey = powershellYK.support.Base32.Decode(Base32Secret);
configureHOTP = configureHOTP.UseKey(_HOTPsecretKey);
}
// Handle Secret Key configuration using Hex
else if (HexSecret != null)
{
_HOTPsecretKey = powershellYK.support.Hex.Decode(HexSecret);
configureHOTP = configureHOTP.UseKey(_HOTPsecretKey);
}
else if (SecretKey is null)
{
configureHOTP = configureHOTP.GenerateKey(_HOTPsecretKey);
Expand Down Expand Up @@ -362,10 +376,10 @@ protected override void ProcessRecord()

configureHOTP.Execute();

// Return both raw and Base32 representations of the key
// Return both Hex and Base32 representations of the key
WriteObject(new
{
SecretKey = _HOTPsecretKey.ToArray(),
HexSecret = powershellYK.support.Hex.Encode(_HOTPsecretKey.ToArray()),
Base32Secret = powershellYK.support.Base32.Encode(_HOTPsecretKey.ToArray())
});
break;
Expand Down
59 changes: 59 additions & 0 deletions Module/support/Hex.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/// <summary>
/// Utility class for hex encoding and decoding.
/// Provides methods to convert between byte arrays and hex strings.
///
/// .EXAMPLE
/// # Encode a byte array to hex
/// $bytes = [byte[]]@(1,2,3,4,5)
/// $hex = [powershellYK.support.Hex]::Encode($bytes)
///
/// .EXAMPLE
/// # Decode a hex string to bytes
/// $hex = "0102030405"
/// $bytes = [powershellYK.support.Hex]::Decode($hex)
/// </summary>

using System;
using System.Linq;

namespace powershellYK.support
{
public static class Hex
{
// Encodes a byte array to a hex string
public static string Encode(byte[] data)
{
if (data == null)
throw new ArgumentNullException(nameof(data));

if (data.Length == 0)
return string.Empty;

return string.Concat(data.Select(b => b.ToString("x2")));
}

// Decodes a hex string to a byte array
public static byte[] Decode(string hexString)
{
if (string.IsNullOrEmpty(hexString))
return Array.Empty<byte>();

// Remove any whitespace and convert to lowercase
hexString = hexString.Replace(" ", "").ToLower();

// Ensure the string has an even length
if (hexString.Length % 2 != 0)
throw new ArgumentException("Hex string must have an even length");

// Convert each pair of hex characters to a byte
byte[] result = new byte[hexString.Length / 2];
for (int i = 0; i < result.Length; i++)
{
string hexPair = hexString.Substring(i * 2, 2);
result[i] = Convert.ToByte(hexPair, 16);
}

return result;
}
}
}