diff --git a/id/id.go b/id/id.go
index d8b602197c9a624332874c059e56fb13fdf9ec1e..4f984e1de952134e05270353d796be0cdb5fe8ff 100644
--- a/id/id.go
+++ b/id/id.go
@@ -220,6 +220,62 @@ func NewIdFromString(idString string, idType Type, x interface{}) *ID {
 	return newID
 }
 
+var (
+	// nonBase64Regex matches any character that are not base 64 compatible
+	// except strings.
+	nonBase64Regex = regexp.MustCompile(`[^a-zA-Z0-9+/\s]+`)
+
+	// whitespaceRegex matches one or more whitespace characters.
+	whitespaceRegex = regexp.MustCompile(`\s+`)
+)
+
+// NewIdFromBase64String creates a new ID that when base 64 encoded, looks like
+// the passed in base64String. This function is for testing purposes only.
+//
+// If the string is longer than the data portion of the base 64 string, then it
+// is truncated. If it is shorter, then the remaining bytes are filled with
+// zeroes. The string is made to be base 64 compatible by replacing one or more
+// consecutive white spaces with a plus "+" and stripping all other invalid
+// characters (any character that is not an upper- and lower-case alphabet
+// character (A–Z, a–z), numeral (0–9), or the plus "+" and slash "/" symbols).
+func NewIdFromBase64String(base64String string, idType Type, x interface{}) *ID {
+	// Ensure that this function is only run in testing environments
+	switch x.(type) {
+	case *testing.T, *testing.M, *testing.B:
+		break
+	default:
+		panic("NewIdFromBase64String can only be used for testing.")
+	}
+
+	// Convert the string to bytes and create new ID from it
+	newID := NewIdFromBytes([]byte{}, x)
+
+	// Set the ID type
+	newID.SetType(idType)
+
+	// Escape ID string to be base 64 compatible by replacing all strings with +
+	// and stripping all other invalid characters
+	base64String = nonBase64Regex.ReplaceAllString(base64String, "")
+	base64String = whitespaceRegex.ReplaceAllString(base64String, "+")
+
+	b64Str := base64.StdEncoding.EncodeToString(newID.Marshal())
+
+	// Trim the string if it is over the max length
+	if len(base64String) > len(b64Str)-1 {
+		base64String = base64String[:len(b64Str)-1]
+	}
+
+	// Concatenate the string with the rest of the generated bytes and type
+	base64String = base64String + b64Str[len(base64String):]
+
+	data, err := base64.StdEncoding.DecodeString(base64String)
+	if err != nil {
+		jww.FATAL.Panicf("Failed to decode string: %+v", err)
+	}
+
+	return NewIdFromBytes(data, x)
+}
+
 // NewIdFromUInt converts the specified uint64 into bytes and returns a new ID
 // based off it with the specified ID type. The remaining space of the array is
 // filled with zeros. This function is for testing purposes only.
diff --git a/id/id_test.go b/id/id_test.go
index a5b27ee9c96a3c4120f729ba6afbec5f285dc91c..d7ff2dceeb116c81ecb677397dd92a450d52902c 100644
--- a/id/id_test.go
+++ b/id/id_test.go
@@ -547,6 +547,73 @@ func TestNewIdFromString_TestError(t *testing.T) {
 	_ = NewIdFromString("test", Generic, nil)
 }
 
+// Tests that NewIdFromBase64String creates an ID, that when base 64 encoded,
+// looks similar to the passed in string.
+func TestNewIdFromBase64String(t *testing.T) {
+	tests := []struct{ base64String, expected string }{
+		{"Test 1", "Test+1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE"},
+		{"[Test  2]", "Test+2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE"},
+		{"$#%[T$%%est $#$ 3]$$%", "Test+3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE"},
+		{"$#%[T$%%est $#$ 4+/]$$%", "Test+4+/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE"},
+		{"Test 55555555555555555555555555555555555555", "Test+55555555555555555555555555555555555555E"},
+		{"Test 66666666666666666666666666666666666666666", "Test+66666666666666666666666666666666666666E"},
+		{"", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE"},
+	}
+
+	for i, tt := range tests {
+		newID := NewIdFromBase64String(tt.base64String, Group, t)
+
+		b64 := base64.StdEncoding.EncodeToString(newID.Marshal())
+		if tt.expected != b64 {
+			t.Errorf("Incorrect base 64 encoding for string %q (%d)."+
+				"\nexpected: %s\nreceived: %s",
+				tt.base64String, i, tt.expected, b64)
+		}
+	}
+	//
+	//
+	// // Test values
+	// expectedIdString := "TestIDStringOfCorrectLength"
+	// expectedType := Group
+	// expectedID := new(ID)
+	// copy(expectedID[:], append([]byte(expectedIdString), byte(expectedType)))
+	//
+	// strs := []string{
+	// 	"test",
+	// 	`"test"`,
+	// 	`Question ?`,
+	// 	`open   angle bracket <`,
+	// 	`close angle bracket >`,
+	// 	`slash /`,
+	// 	`slash \`,
+	// }
+	// for i, str := range strs {
+	// 	escaped := url.QueryEscape(str)
+	// 	escaped = whitespaceRegex.ReplaceAllString(str, "+")
+	// 	escaped = nonBase64Regex.ReplaceAllString(escaped, "")
+	// 	fmt.Printf("%2d. %s\n    %s\n", i, str, escaped)
+	// }
+	//
+	// // Create the ID and check its contents
+	// newID := NewIdFromBase64String(expectedIdString, expectedType, t)
+	//
+	// // Check if the new ID matches the expected ID
+	// if !expectedID.Cmp(newID) {
+	// 	t.Errorf("NewIdFromString() produced an ID with the incorrect data."+
+	// 		"\n\texpected: %v\n\treceived: %v", expectedID[:], newID[:])
+	// }
+	//
+	// // Check if the original string is still in the first 32 bytes
+	// newIdString := string(newID.Bytes()[:ArrIDLen-1])
+	// if expectedIdString != newIdString {
+	// 	t.Errorf("NewIdFromString() did not correctly convert the original "+
+	// 		"string to bytes.\n\texpected string: %#v\n\treceived string: %#v"+
+	// 		"\n\texpected bytes: %v\n\treceived bytes: %v",
+	// 		expectedIdString, newIdString,
+	// 		[]byte(expectedIdString), newID.Bytes()[:ArrIDLen-1])
+	// }
+}
+
 // Tests that NewIdFromUInt() creates a new ID with the correct contents by
 // converting the ID back into a uint and comparing it to the original.
 func TestNewIdFromUInt(t *testing.T) {