Skip to content

Instantly share code, notes, and snippets.

@JPRuskin
Created January 17, 2022 11:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JPRuskin/8992e5665a3a73316bba3089de074078 to your computer and use it in GitHub Desktop.
Save JPRuskin/8992e5665a3a73316bba3089de074078 to your computer and use it in GitHub Desktop.
Converts a string to an RFC 4122 compatible UUID.
function SwapBytes {
<#
.SYNOPSIS
Simply switches two bytes in an array of bytes
#>
param(
[Parameter(Mandatory)]
[byte[]]$Guid,
[Parameter(Mandatory)]
[int]$Left,
[Parameter(Mandatory)]
[int]$Right
)
$Guid[$Left], $Guid[$Right] = $Guid[$Right], $Guid[$Left]
}
function SwapByteOrder {
<#
.SYNOPSIS
Convert between Local and Network order
#>
param(
[byte[]]$Guid
)
SwapBytes $Guid 0 3
SwapBytes $Guid 1 2
SwapBytes $Guid 4 5
SwapBytes $Guid 6 7
}
function ConvertTo-Guid {
<#
.Synopsis
Converts a string (or bytes) into a deterministic GUID, based on a specific namespace
.Link
https://www.ietf.org/rfc/rfc4122.txt
RFC
.Link
https://github.com/Faithlife/FaithlifeUtility/blob/master/src/Faithlife.Utility/GuidUtility.cs
Original by Bradley Grainger
.Example
ConvertTo-Guid 'env.CCR_Api_Key'
#>
[CmdletBinding(DefaultParameterSetName="FromString")]
param(
[Parameter(Mandatory, Position=0, ParameterSetName = "FromString")]
[string]$String,
[Parameter(Mandatory, ParameterSetName = "FromBytes")]
[byte[]]$Bytes = $([System.Text.Encoding]::UTF8.GetBytes($String)),
[ValidateSet(
"6ba7b810-9dad-11d1-80b4-00c04fd430c8", # DnsNamespace
"6ba7b811-9dad-11d1-80b4-00c04fd430c8", # UrlNamespace
"6ba7b812-9dad-11d1-80b4-00c04fd430c8", # IsoOidNamespace
"361E6D51-FAEC-444A-9079-341386DA8E2E" # Ansible, should be v5
)]
[guid]$NamespaceId = "361E6D51-FAEC-444A-9079-341386DA8E2E",
[ValidateSet(3,5)]
$Version = 5
)
process {
# Convert the namespace UUID to network order (step 3)
$NamespaceBytes = $NamespaceId.ToByteArray()
SwapByteOrder $NamespaceBytes
# Compute the hash of the namespace ID concatenated with the name (step 4)
$Data = $NamespaceBytes + $Bytes
[byte[]]$Hash = switch ($Version) {
3 { [System.Security.Cryptography.MD5]::Create().ComputeHash($Data) }
5 { [System.Security.Cryptography.SHA1]::Create().ComputeHash($Data) }
}
$NewGuid = [byte[]]$Hash[0..15]
# Set the four most significant bits (bits 12 through 15) of the time_hi_and_version field
# to the appropriate 4-bit version number from Section 4.1.3 (step 8)
$NewGuid[6] = $NewGuid[6] -band 0x0F -bor $Version -shl 4
# Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to
# zero and one, respectively (step 10)
$NewGuid[8] = $NewGuid[8] -band 0x3F -bor 0x80
SwapByteOrder($NewGuid)
[Guid]$NewGuid
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment