mirror of
https://github.com/rwinkhart/go-winio.git
synced 2026-08-28 04:46:50 -04:00
guid: Add V5 GUID support
Signed-off-by: Kevin Parsons <kevpar@microsoft.com>
This commit is contained in:
@@ -7,6 +7,7 @@ package guid
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"encoding"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
@@ -59,6 +60,29 @@ func NewV4() (GUID, error) {
|
||||
return g, nil
|
||||
}
|
||||
|
||||
// NewV5 returns a new version 5 (generated from a string via SHA-1 hashing)
|
||||
// GUID, as defined by RFC 4122. The RFC is unclear on the encoding of the name,
|
||||
// and the sample code treats it as a series of bytes, so we do the same here.
|
||||
//
|
||||
// Some implementations, such as those found on Windows, treat the name as a
|
||||
// big-endian UTF16 stream of bytes. If that is desired, the string can be
|
||||
// encoded as such before being passed to this function.
|
||||
func NewV5(namespace GUID, name []byte) (GUID, error) {
|
||||
b := sha1.New()
|
||||
namespaceBytes := namespace.ToArray()
|
||||
b.Write(namespaceBytes[:])
|
||||
b.Write(name)
|
||||
|
||||
a := [16]byte{}
|
||||
copy(a[:], b.Sum(nil))
|
||||
|
||||
g := FromArray(a)
|
||||
g.setVersion(5) // Version 5 means generated from a string.
|
||||
g.setVariant(VariantRFC4122)
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func fromArray(b [16]byte, order binary.ByteOrder) GUID {
|
||||
var g GUID
|
||||
g.Data1 = order.Uint32(b[0:4])
|
||||
|
||||
@@ -14,6 +14,14 @@ func mustNewV4(t *testing.T) GUID {
|
||||
return g
|
||||
}
|
||||
|
||||
func mustNewV5(t *testing.T, namespace GUID, name []byte) GUID {
|
||||
g, err := NewV5(namespace, name)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return g
|
||||
}
|
||||
|
||||
func mustFromString(t *testing.T, s string) GUID {
|
||||
g, err := FromString(s)
|
||||
if err != nil {
|
||||
@@ -112,6 +120,53 @@ func Test_V4HasCorrectVersionAndVariant(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_V5HasCorrectVersionAndVariant(t *testing.T) {
|
||||
namespace := mustFromString(t, "f5cbc1a9-4cba-45a0-bfdd-b6761fc7dcc0")
|
||||
g := mustNewV5(t, namespace, []byte("Foo"))
|
||||
if g.Version() != 5 {
|
||||
t.Fatalf("Version is not 5: %s", g)
|
||||
}
|
||||
if g.Variant() != VariantRFC4122 {
|
||||
t.Fatalf("Variant is not RFC4122: %s", g)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_V5KnownValues(t *testing.T) {
|
||||
type testCase struct {
|
||||
ns GUID
|
||||
name string
|
||||
g GUID
|
||||
}
|
||||
testCases := []testCase{
|
||||
{
|
||||
mustFromString(t, "6ba7b810-9dad-11d1-80b4-00c04fd430c8"),
|
||||
"www.sample.com",
|
||||
mustFromString(t, "4e4463eb-b0e8-54fa-8c28-12d1ab1d45b3"),
|
||||
},
|
||||
{
|
||||
mustFromString(t, "6ba7b811-9dad-11d1-80b4-00c04fd430c8"),
|
||||
"https://www.sample.com/test",
|
||||
mustFromString(t, "9e44625a-0d85-5e0a-99bc-8e8a77df5ea2"),
|
||||
},
|
||||
{
|
||||
mustFromString(t, "6ba7b812-9dad-11d1-80b4-00c04fd430c8"),
|
||||
"1.3.6.1.4.1.343",
|
||||
mustFromString(t, "6aab0456-7392-582a-b92a-ba5a7096945d"),
|
||||
},
|
||||
{
|
||||
mustFromString(t, "6ba7b814-9dad-11d1-80b4-00c04fd430c8"),
|
||||
"CN=John Smith, ou=People, o=FakeCorp, L=Seattle, S=Washington, C=US",
|
||||
mustFromString(t, "badff8dd-c869-5b64-a260-00092e66be00"),
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
g := mustNewV5(t, tc.ns, []byte(tc.name))
|
||||
if g != tc.g {
|
||||
t.Fatalf("GUIDs are not equal.\nExpected: %s\nActual: %s", tc.g, g)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_ToArray(t *testing.T) {
|
||||
g := mustFromString(t, "73c39589-192e-4c64-9acf-6c5d0aa18528")
|
||||
b := g.ToArray()
|
||||
|
||||
Reference in New Issue
Block a user