mask

package module
v0.0.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 20, 2024 License: MIT Imports: 9 Imported by: 0

README

go-mask

Documentation Go Tests codecov Go Report Card

go-mask is a simple, customizable Go library for masking sensitive information.

Features

  • You can mask any field of a structure using the struct's tags. (example → How to use)
  • It is also possible to mask using field names or map keys without using tags. (example → field name / map key)
  • Users can make use of their own custom-created masking functions. (example → custom mask function)
  • The masked object is a copied object, so it does not overwrite the original data before masking(although it's not perfect...)
    • Private fields are not copied
    • It is moderately fast in performing deep copies.

Installation

go get github.com/showa-93/go-mask

Mask Tags

go-mask does not provide many tags by default.
This is because it is believed that users should create their own necessary masking functions.

tag type description
mask:"filled" string Masks the string with the same number of masking characters.
mask:"filledXXX" string XXX = number of masking characters. Masks with a fixed number of characters. mask:"filled3"***
mask:"fixed" string Masks with a fixed number of characters. *******
mask:"hash" string Masks the string by converting it to a value using sha1.
mask:"randomXXX" int / float64 XXX = numeric value. Masks with a random value in the range of 0 to the XXX.
mask:"zero" any It can be applied to any type, masking it with the zero value of that type.

How to use

string
package main

import (
	"fmt"

	mask "github.com/showa-93/go-mask"
)

func main() {
	{
		maskValue, _ := mask.String(mask.MaskTypeFixed, "Hello World!!")
		fmt.Println(maskValue)
	}
	{
		value := struct {
			Title string   `mask:"filled"`
			Casts []string `mask:"fixed"`
		}{
			Title: "Catch Me If You Can",
			Casts: []string{
				"Thomas Jeffrey \"Tom\" Hanks",
				"Leonardo Wilhelm DiCaprio",
			},
		}
		masker := mask.NewMasker()
		masker.SetMaskChar("-")
		masker.RegisterMaskStringFunc(mask.MaskTypeFilled, masker.MaskFilledString)
		masker.RegisterMaskStringFunc(mask.MaskTypeFixed, masker.MaskFixedString)

		maskValue, _ := mask.Mask(value)
		maskValue2, _ := masker.Mask(value)

		fmt.Printf("%+v\n", value)
		fmt.Printf("%+v\n", maskValue)
		fmt.Printf("%+v\n", maskValue2)
	}
}
********
{Title:Catch Me If You Can Casts:[Thomas Jeffrey "Tom" Hanks Leonardo Wilhelm DiCaprio]}
{Title:******************* Casts:[******** ********]}
{Title:------------------- Casts:[-------- --------]}
int / float64 / uint
package main

import (
	"fmt"

	mask "github.com/showa-93/go-mask"
)

func main() {
	{
		maskValue, _ := mask.Int("random100", 10)
		fmt.Println(maskValue)
	}
	{
		maskValue, _ := mask.Float64("random100.2", 12.3)
		fmt.Println(maskValue)
	}

	{
		value := struct {
			Price   int     `mask:"random1000"`
			Percent float64 `mask:"random1.3"`
		}{
			Price:   300,
			Percent: 0.80,
		}
		masker := mask.NewMasker()
		masker.RegisterMaskIntFunc(mask.MaskTypeRandom, masker.MaskRandomInt)
		masker.RegisterMaskFloat64Func(mask.MaskTypeRandom, masker.MaskRandomFloat64)

		maskValue, _ := mask.Mask(value)
		maskValue2, _ := masker.Mask(value)

		fmt.Printf("%+v\n", maskValue)
		fmt.Printf("%+v\n", maskValue2)
	}
}
29
50.45
{Price:917 Percent:0.183}
{Price:733 Percent:0.241}
slice / array
package main

import (
	"fmt"

	"github.com/showa-93/go-mask"
)

type Value struct {
	Name string `mask:"filled"`
	Type int    `mask:"random10"`
}

func main() {
	values := []Value{
		{
			Name: "Thomas Jeffrey \"Tom\" Hanks",
			Type: 1,
		},
		{
			Name: "Leonardo Wilhelm DiCaprio",
			Type: 2,
		},
	}
	masker := mask.NewMasker()
	masker.SetMaskChar("+")
	masker.RegisterMaskStringFunc(mask.MaskTypeFilled, masker.MaskFilledString)
	masker.RegisterMaskIntFunc(mask.MaskTypeRandom, masker.MaskRandomInt)

	maskValues, _ := mask.Mask(values)
	maskValues2, _ := masker.Mask(values)

	fmt.Printf("%+v\n", values)
	fmt.Printf("%+v\n", maskValues)
	fmt.Printf("%+v\n", maskValues2)
}
[{Name:Thomas Jeffrey "Tom" Hanks Type:1} {Name:Leonardo Wilhelm DiCaprio Type:2}]
[{Name:************************** Type:8} {Name:************************* Type:9}]
[{Name:++++++++++++++++++++++++++ Type:4} {Name:+++++++++++++++++++++++++ Type:8}]
map
package main

import (
	"fmt"

	"github.com/showa-93/go-mask"
)

type Value struct {
	Name string `mask:"filled"`
	Type int    `mask:"random10"`
}

func main() {
	values := map[string]Value{
		"one": {
			Name: "Thomas Jeffrey \"Tom\" Hanks",
			Type: 1,
		},
		"two": {
			Name: "Leonardo Wilhelm DiCaprio",
			Type: 2,
		},
	}
	masker := mask.NewMasker()
	masker.SetMaskChar("")
	masker.RegisterMaskStringFunc(mask.MaskTypeFilled, masker.MaskFilledString)
	masker.RegisterMaskIntFunc(mask.MaskTypeRandom, masker.MaskRandomInt)

	maskValues, _ := mask.Mask(values)
	maskValues2, _ := masker.Mask(values)

	fmt.Printf("%+v\n", values)
	fmt.Printf("%+v\n", maskValues)
	fmt.Printf("%+v\n", maskValues2)
}
map[one:{Name:Thomas Jeffrey "Tom" Hanks Type:1} two:{Name:Leonardo Wilhelm DiCaprio Type:2}]
map[one:{Name:************************** Type:8} two:{Name:************************* Type:6}]
map[one:{Name: Type:6} two:{Name: Type:2}]
JSON
package main

import (
	"encoding/json"
	"fmt"

	mask "github.com/showa-93/go-mask"
)

func main() {
	masker := mask.NewMasker()
	masker.RegisterMaskStringFunc(mask.MaskTypeFilled, masker.MaskFilledString)
	masker.RegisterMaskField("S", "filled4")

	v := `{
		"S": "Hello world",
		"I": 1,
		"O": {
			"S": "Second",
			"S2": "豚汁"
		}
	}`
	var target any
	json.Unmarshal([]byte(v), &target)
	masked, _ := masker.Mask(target)
	mv, _ := json.Marshal(masked)
	fmt.Println(string(mv))
}
{"I":1,"O":{"S":"****","S2":"豚汁"},"S":"****"}
nested struct
package main

import (
	"fmt"

	"github.com/showa-93/go-mask"
)

type Node struct {
	Value string `mask:"filled"`
	Next  *Node
}

func main() {
	node := Node{
		Value: "first",
		Next: &Node{
			Value: "second",
			Next: &Node{
				Value: "third",
			},
		},
	}

	masker := mask.NewMasker()
	masker.SetMaskChar("🤗")
	masker.RegisterMaskStringFunc(mask.MaskTypeFilled, masker.MaskFilledString)

	maskNode, _ := mask.Mask(node)
	maskNode2, _ := masker.Mask(node)

	fmt.Printf("first=%+v,second=%+v,third=%+v\n", node, node.Next, node.Next.Next)
	fmt.Printf("first=%+v,second=%+v,third=%+v\n", maskNode, maskNode.Next, maskNode.Next.Next)
	fmt.Printf("first=%+v,second=%+v,third=%+v\n", maskNode2.(Node), maskNode2.(Node).Next, maskNode2.(Node).Next.Next)
}
first={Value:first Next:0xc000010048},second=&{Value:second Next:0xc000010060},third=&{Value:third Next:<nil>}
first={Value:***** Next:0xc0000100a8},second=&{Value:****** Next:0xc0000100c0},third=&{Value:***** Next:<nil>}
first={Value:🤗🤗🤗🤗🤗 Next:0xc000010120},second=&{Value:🤗🤗🤗🤗🤗🤗 Next:0xc000010138},third=&{Value:🤗🤗🤗🤗🤗 Next:<nil>}
field name / map key
package main

import (
	"fmt"

	mask "github.com/showa-93/go-mask"
)

type User struct {
	ID      string // no tag
	Name    string
	Gender  string
	Age     int
	ExtData map[string]string
}

func main() {
	masker := mask.NewMasker()

	masker.RegisterMaskStringFunc(mask.MaskTypeFilled, masker.MaskFilledString)
	masker.RegisterMaskIntFunc(mask.MaskTypeRandom, masker.MaskRandomInt)

	// registered field name
	masker.RegisterMaskField("Name", "filled4")
	masker.RegisterMaskField("Animal", "filled6")
	masker.RegisterMaskField("Age", mask.MaskTypeRandom+"100")

	u := User{
		ID:     "1",
		Name:   "タマ",
		Gender: "Male",
		Age:    4,
		ExtData: map[string]string{
			"Animal": "Cat",
		},
	}
	maskedUser, _ := masker.Mask(u)
	fmt.Printf("%+v", maskedUser)
}
{ID:1 Name:**** Gender:Male Age:10 ExtData:map[Animal:******]}
custom mask function
package main

import (
	"fmt"
	"regexp"
	"strings"

	mask "github.com/showa-93/go-mask"
)

func init() {
	maskTypeRegExp := "regexp"
	mask.RegisterMaskStringFunc(maskTypeRegExp, MaskRegExp)
}

// MaskRegExp is sample to add a custom mask function
func MaskRegExp(arg, value string) (string, error) {
	var (
		reg *regexp.Regexp
		err error
	)
	reg, err = regexp.Compile(arg)
	if err != nil {
		return "", err
	}

	indexes := reg.FindStringSubmatchIndex(value)
	if len(indexes) >= 4 && indexes[2] >= 0 && indexes[3] >= 0 {
		var sb strings.Builder
		sb.WriteString(value[:indexes[2]])
		sb.WriteString(mask.MaskChar())
		sb.WriteString(value[indexes[3]:])
		return sb.String(), nil
	}

	return value, nil
}

func main() {
	mask.SetMaskChar("cat")
	type Hachiware struct {
		Message string `mask:"regexp(gopher)."`
	}

	input := Hachiware{Message: "I love gopher!"}
	got, _ := mask.Mask(input)
	fmt.Printf("%+v\n", input)
	fmt.Printf("%+v\n", got)

	// The Masker initialized with NewMasker does not have
	// any custom masking functions registered, so no masking will occur
	masker := mask.NewMasker()
	got2, _ := masker.Mask(input)
	fmt.Printf("%+v\n", got2)
}
{Message:I love gopher!}
{Message:I love cat!}
{Message:I love gopher!}

Documentation

Overview

Example
rand.Seed(12345)
type Address struct {
	PostCode string `mask:"zero"`
}
type User struct {
	ID      string
	Name    string `mask:"filled"`
	Age     int    `mask:"random100"`
	Address Address
}

user := User{
	ID:   "123456",
	Name: "Usagi",
	Age:  3,
	Address: Address{
		PostCode: "123-4567",
	},
}
maskUser, err := Mask(user)
if err != nil {
	fmt.Println(err)
	return
}
fmt.Printf("%+v", maskUser)
Output:

{ID:123456 Name:***** Age:83 Address:{PostCode:}}
Example (CustomMaskFunc)
package main

import (
	"fmt"
	"regexp"
	"strings"
	"unicode/utf8"

	mask "github.com/vvlgo/go-mask"
)

func init() {
	maskTypeRegExp := "regexp"
	mask.RegisterMaskStringFunc(maskTypeRegExp, MaskRegExp)
}

// MaskRegExp is sample to add a custom mask function
func MaskRegExp(arg, value string) (string, error) {
	var (
		reg *regexp.Regexp
		err error
	)
	reg, err = regexp.Compile(arg)
	if err != nil {
		return "", err
	}

	indexes := reg.FindStringSubmatchIndex(value)
	if len(indexes) >= 4 && indexes[2] >= 0 && indexes[3] >= 0 {
		var sb strings.Builder
		sb.WriteString(value[:indexes[2]])
		sb.WriteString(strings.Repeat(mask.MaskChar(), utf8.RuneCountInString(value[indexes[2]:indexes[3]])))
		sb.WriteString(value[indexes[3]:])
		return sb.String(), nil
	}

	return value, nil
}

func main() {
	mask.SetMaskChar("■")
	type Hachiware struct {
		Message string `mask:"regexp(最高)."`
	}

	input := Hachiware{Message: "これって…最高じゃん"}
	got, _ := mask.Mask(input)
	fmt.Printf("\"%s\", Hachiware says\n", got.Message)

}
Output:

"これって…■■じゃん", Hachiware says

Index

Examples

Constants

View Source
const (
	MaskTypeFilled = "filled"
	MaskTypeFixed  = "fixed"
	MaskTypeRandom = "random"
	MaskTypeHash   = "hash"
	MaskTypeZero   = "zero"
)

Default tag that can be specified as a mask

View Source
const TagName = "mask"

Tag name of the field in the structure when masking

Variables

This section is empty.

Functions

func Float64

func Float64(tag string, value float64) (float64, error)

Float64 masks the given argument float64 from default masker.

func Int

func Int(tag string, value int) (int, error)

Int masks the given argument int from default masker.

func Mask

func Mask[T any](target T) (ret T, err error)

Mask returns an object with the mask applied to any given object. The function's argument can accept any type, including pointer, map, and slice types, in addition to struct. from default masker.

func MaskChar

func MaskChar() string

MaskChar returns the current character used for masking. from default masker.

func RegisterMaskAnyFunc

func RegisterMaskAnyFunc(maskType string, maskFunc MaskAnyFunc)

RegisterMaskAnyFunc registers a masking function that can be applied to any type. The function will be applied when the string set in the first argument is assigned as a tag to a field in the structure. from default masker.

func RegisterMaskField

func RegisterMaskField(fieldName, maskType string)

RegisterMaskField allows you to register a mask tag to be applied to the value of a struct field or map key that matches the fieldName. If a mask tag is set on the struct field, it will take precedence. from default masker.

Example
rand.Seed(12345)
type User2 struct {
	ID      string
	Name    string
	Age     int
	ExtData map[string]string
}
user := User2{
	ID:   "123456",
	Name: "Usagi",
	Age:  3,
	ExtData: map[string]string{
		"ID":       "123456",
		"Favorite": "Cat",
	},
}

RegisterMaskField("ID", "zero")
RegisterMaskField("Age", "random100")
RegisterMaskField("Name", "filled4")
RegisterMaskField("Favorite", "filled6")
maskUser, err := Mask(user)
if err != nil {
	fmt.Println(err)
	return
}
fmt.Printf("%+v", maskUser)
Output:

{ID: Name:**** Age:83 ExtData:map[Favorite:****** ID:]}

func RegisterMaskFloat64Func

func RegisterMaskFloat64Func(maskType string, maskFunc MaskFloat64Func)

RegisterMaskFloat64Func registers a masking function for float64 values. The function will be applied when the string set in the first argument is assigned as a tag to a field in the structure. from default masker.

func RegisterMaskIntFunc

func RegisterMaskIntFunc(maskType string, maskFunc MaskIntFunc)

RegisterMaskIntFunc registers a masking function for int values. The function will be applied when the string set in the first argument is assigned as a tag to a field in the structure. from default masker.

func RegisterMaskStringFunc

func RegisterMaskStringFunc(maskType string, maskFunc MaskStringFunc)

RegisterMaskStringFunc registers a masking function for string values. The function will be applied when the string set in the first argument is assigned as a tag to a field in the structure. from default masker.

func RegisterMaskUintFunc

func RegisterMaskUintFunc(maskType string, maskFunc MaskUintFunc)

RegisterMaskUintFunc registers a masking function for uint values. The function will be applied when the string set in the first argument is assigned as a tag to a field in the structure. from default masker.

func SetMaskChar

func SetMaskChar(s string)

SetMaskChar changes the character used for masking from default masker.

func String

func String(tag, value string) (string, error)

String masks the given argument string from default masker.

func Uint

func Uint(tag string, value uint) (uint, error)

Uint masks the given argument int from default masker.

Types

type MaskAnyFunc

type MaskAnyFunc func(arg string, value any) (any, error)

Function type that must be satisfied to add a custom mask

type MaskFloat64Func

type MaskFloat64Func func(arg string, value float64) (float64, error)

Function type that must be satisfied to add a custom mask

type MaskIntFunc

type MaskIntFunc func(arg string, value int) (int, error)

Function type that must be satisfied to add a custom mask

type MaskStringFunc

type MaskStringFunc func(arg string, value string) (string, error)

Function type that must be satisfied to add a custom mask

type MaskUintFunc

type MaskUintFunc func(arg string, value uint) (uint, error)

Function type that must be satisfied to add a custom mask

type Masker

type Masker struct {
	// contains filtered or unexported fields
}

Masker is a struct that defines the masking process.

func NewMasker

func NewMasker() *Masker

NewMasker initializes a Masker.

func (*Masker) Cache

func (m *Masker) Cache(enable bool)

Cache can be toggled to cache the type information of the struct. default true

func (*Masker) Float64

func (m *Masker) Float64(tag string, value float64) (float64, error)

Float64 masks the given argument float64

func (*Masker) Int

func (m *Masker) Int(tag string, value int) (int, error)

Int masks the given argument int

func (*Masker) Mask

func (m *Masker) Mask(target any) (ret any, err error)

Mask returns an object with the mask applied to any given object. The function's argument can accept any type, including pointer, map, and slice types, in addition to struct.

func (*Masker) MaskChar

func (m *Masker) MaskChar() string

MaskChar returns the current character used for masking.

func (*Masker) MaskFilledString

func (m *Masker) MaskFilledString(arg, value string) (string, error)

MaskFilledString masks the string length of the value with the same length. If you pass a number like "2" to arg, it masks with the length of the number.(**)

func (*Masker) MaskFixedString

func (m *Masker) MaskFixedString(arg, value string) (string, error)

MaskFixedString masks with a fixed length (8 characters).

func (*Masker) MaskHashString

func (m *Masker) MaskHashString(arg, value string) (string, error)

MaskHashString masks and hashes (sha1) a string.

func (*Masker) MaskRandomFloat64

func (m *Masker) MaskRandomFloat64(arg string, value float64) (float64, error)

MaskRandomFloat64 converts a float64 to a random number. For example, if you pass "100.3" to arg, it sets a random number in the range of 0.000 to 99.999.

func (*Masker) MaskRandomInt

func (m *Masker) MaskRandomInt(arg string, value int) (int, error)

MaskRandomInt converts an integer (int) into a random number. For example, if you pass "100" as the arg, it sets a random number in the range of 0-99.

func (*Masker) MaskZero

func (m *Masker) MaskZero(arg string, value any) (any, error)

MaskZero converts the value to its type's zero value.

func (*Masker) RegisterMaskAnyFunc

func (m *Masker) RegisterMaskAnyFunc(maskType string, maskFunc MaskAnyFunc)

RegisterMaskAnyFunc registers a masking function that can be applied to any type. The function will be applied when the string set in the first argument is assigned as a tag to a field in the structure.

func (*Masker) RegisterMaskField

func (m *Masker) RegisterMaskField(fieldName, maskType string)

RegisterMaskField allows you to register a mask tag to be applied to the value of a struct field or map key that matches the fieldName. If a mask tag is set on the struct field, it will take precedence.

func (*Masker) RegisterMaskFloat64Func

func (m *Masker) RegisterMaskFloat64Func(maskType string, maskFunc MaskFloat64Func)

RegisterMaskFloat64Func registers a masking function for float64 values. The function will be applied when the string set in the first argument is assigned as a tag to a field in the structure.

func (*Masker) RegisterMaskIntFunc

func (m *Masker) RegisterMaskIntFunc(maskType string, maskFunc MaskIntFunc)

RegisterMaskIntFunc registers a masking function for int values. The function will be applied when the string set in the first argument is assigned as a tag to a field in the structure.

func (*Masker) RegisterMaskStringFunc

func (m *Masker) RegisterMaskStringFunc(maskType string, maskFunc MaskStringFunc)

RegisterMaskStringFunc registers a masking function for string values. The function will be applied when the string set in the first argument is assigned as a tag to a field in the structure.

func (*Masker) RegisterMaskUintFunc

func (m *Masker) RegisterMaskUintFunc(maskType string, maskFunc MaskUintFunc)

RegisterMaskUintFunc registers a masking function for uint values. The function will be applied when the uint slice set in the first argument is assigned as a tag to a field in the structure.

func (*Masker) SetMaskChar

func (m *Masker) SetMaskChar(s string)

SetMaskChar changes the character used for masking

func (*Masker) SetTagName

func (m *Masker) SetTagName(s string)

SetTagName allows you to change the tag name from "mask" to something else.

func (*Masker) String

func (m *Masker) String(tag, value string) (string, error)

String masks the given argument string

func (*Masker) Uint

func (m *Masker) Uint(tag string, value uint) (uint, error)

Uint masks the given argument uint

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL