fst: implement app id parser
Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
This commit is contained in:
parent
f796622c35
commit
5ea7333431
48
fst/id.go
Normal file
48
fst/id.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package fst
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ID [16]byte
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidLength = errors.New("string representation must have a length of 32")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *ID) String() string {
|
||||||
|
return hex.EncodeToString(a[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAppID(id *ID) error {
|
||||||
|
_, err := rand.Read(id[:])
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseAppID(id *ID, s string) error {
|
||||||
|
if len(s) != 32 {
|
||||||
|
return ErrInvalidLength
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, b := range s {
|
||||||
|
if b < '0' || b > 'f' {
|
||||||
|
return fmt.Errorf("invalid char %q at byte %d", b, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
v := uint8(b)
|
||||||
|
if v > '9' {
|
||||||
|
v = 10 + v - 'a'
|
||||||
|
} else {
|
||||||
|
v -= '0'
|
||||||
|
}
|
||||||
|
if i%2 == 0 {
|
||||||
|
v <<= 4
|
||||||
|
}
|
||||||
|
id[i/2] += v
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
63
fst/id_test.go
Normal file
63
fst/id_test.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package fst_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.ophivana.moe/security/fortify/fst"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseAppID(t *testing.T) {
|
||||||
|
t.Run("bad length", func(t *testing.T) {
|
||||||
|
if err := fst.ParseAppID(new(fst.ID), "meow"); !errors.Is(err, fst.ErrInvalidLength) {
|
||||||
|
t.Errorf("ParseAppID: error = %v, wantErr = %v", err, fst.ErrInvalidLength)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("bad byte", func(t *testing.T) {
|
||||||
|
wantErr := "invalid char '\\n' at byte 15"
|
||||||
|
if err := fst.ParseAppID(new(fst.ID), "02bc7f8936b2af6\n\ne2535cd71ef0bb7"); err == nil || err.Error() != wantErr {
|
||||||
|
t.Errorf("ParseAppID: error = %v, wantErr = %v", err, wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("fuzz 16 iterations", func(t *testing.T) {
|
||||||
|
for i := 0; i < 16; i++ {
|
||||||
|
testParseAppIDWithRandom(t)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzParseAppID(f *testing.F) {
|
||||||
|
for i := 0; i < 16; i++ {
|
||||||
|
id := new(fst.ID)
|
||||||
|
if err := fst.NewAppID(id); err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
f.Add(id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8], id[9], id[10], id[11], id[12], id[13], id[14], id[15])
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Fuzz(func(t *testing.T, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15 byte) {
|
||||||
|
testParseAppID(t, &fst.ID{b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testParseAppIDWithRandom(t *testing.T) {
|
||||||
|
id := new(fst.ID)
|
||||||
|
if err := fst.NewAppID(id); err != nil {
|
||||||
|
t.Fatalf("cannot generate app ID: %v", err)
|
||||||
|
}
|
||||||
|
testParseAppID(t, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testParseAppID(t *testing.T, id *fst.ID) {
|
||||||
|
s := id.String()
|
||||||
|
got := new(fst.ID)
|
||||||
|
if err := fst.ParseAppID(got, s); err != nil {
|
||||||
|
t.Fatalf("cannot parse app ID: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *got != *id {
|
||||||
|
t.Fatalf("ParseAppID(%#v) = \n%#v, want \n%#v", s, got, id)
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +1,2 @@
|
|||||||
// Package fst exports shared fortify types.
|
// Package fst exports shared fortify types.
|
||||||
package fst
|
package fst
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
"encoding/hex"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ID [16]byte
|
|
||||||
|
|
||||||
func (a *ID) String() string {
|
|
||||||
return hex.EncodeToString(a[:])
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewAppID(id *ID) error {
|
|
||||||
_, err := rand.Read(id[:])
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user