diff --git a/hasher/hasher_test.go b/hasher/hasher_test.go index a334dff..97ccab5 100644 --- a/hasher/hasher_test.go +++ b/hasher/hasher_test.go @@ -61,9 +61,9 @@ func TestSHA256Hasher(t *testing.T) { t.Parallel() tests := []struct { - name string - in []byte - out string + name string + in []byte + expected string }{ {"empty", []byte(""), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}, {"abc", []byte("abc"), "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"}, @@ -77,7 +77,7 @@ func TestSHA256Hasher(t *testing.T) { result, _ := h.Hash(test.in) - assert.Equal(t, test.out, hex.EncodeToString(result)) + assert.Equal(t, test.expected, hex.EncodeToString(result)) }) } } diff --git a/kv/kv.go b/kv/kv.go index 178d9a2..6a5e5cb 100644 --- a/kv/kv.go +++ b/kv/kv.go @@ -9,7 +9,6 @@ type KeyValue struct { Key []byte // Value is the serialized representation of the value. Value []byte - // ModRevision is the revision number of the last modification to this key. ModRevision int64 } diff --git a/marshaller/marshaller.go b/marshaller/marshaller.go index 83702b4..9ec6f14 100644 --- a/marshaller/marshaller.go +++ b/marshaller/marshaller.go @@ -17,7 +17,7 @@ var ErrUnmarshall = errors.New("failed to unmarshal") // implements one time for all objects. // Required for `integrity.Storage` to set marshalling format for any type object // and as recommendation for developers of `Storage` wrappers. -type DefaultMarshaller interface { +type DefaultMarshaller interface { //nolint:iface Marshal(data any) ([]byte, error) Unmarshal(data []byte, out any) error } @@ -25,8 +25,8 @@ type DefaultMarshaller interface { // Marshallable - custom object serialization, implements for each object. // Required for `integrity.Storage` type to set marshalling format to specific object // and as recommendation for developers of `Storage` wrappers. -type Marshallable interface { - Marshal() ([]byte, error) +type Marshallable interface { //nolint:iface + Marshal(data any) ([]byte, error) Unmarshal(data []byte, out any) error } @@ -34,7 +34,7 @@ type Marshallable interface { type YAMLMarshaller struct{} // NewYamlMarshaller creates new NewYamlMarshaller object. -func NewYamlMarshaller() YAMLMarshaller { +func NewYamlMarshaller() Marshallable { return YAMLMarshaller{} } diff --git a/namer/key.go b/namer/key.go new file mode 100644 index 0000000..8b2fd4e --- /dev/null +++ b/namer/key.go @@ -0,0 +1,59 @@ +package namer + +// KeyType represents key types. +type KeyType int + +const ( + // KeyTypeValue represents data type. + KeyTypeValue KeyType = iota + 1 + // KeyTypeHash represents hash of the data type. + KeyTypeHash + // KeyTypeSignature represents signature of the data type. + KeyTypeSignature +) + +// Key defines the minimal interface required by keys. +type Key interface { + Name() string // Get object name. + Type() KeyType // Get key type. + Property() string // Get metadata (e.g., algorithm version). + Build() string // Reconstruct raw key string. +} + +// DefaultKey implements default realization. +type DefaultKey struct { + name string // Object identifier. + keyType KeyType // Type of object (hash/signature/value). + property string // Additional metadata (version/algorithm). + raw string // Raw key string. +} + +// NewDefaultKey returns new Key object. +func NewDefaultKey(name string, keytype KeyType, property string, raw string) DefaultKey { + return DefaultKey{ + name: name, + keyType: keytype, + property: property, + raw: raw, + } +} + +// Name returns name of the key. +func (k DefaultKey) Name() string { + return k.name +} + +// Type returns type of the key. +func (k DefaultKey) Type() KeyType { + return k.keyType +} + +// Property returns property of the key. +func (k DefaultKey) Property() string { + return k.property +} + +// Build reconstructs key string. +func (k DefaultKey) Build() string { + return k.raw +} diff --git a/namer/namer.go b/namer/namer.go index f272a00..5968b07 100644 --- a/namer/namer.go +++ b/namer/namer.go @@ -2,41 +2,249 @@ package namer import ( - "github.com/tarantool/go-storage/kv" + "fmt" + "iter" + "strings" ) -// KeyType represents key types. -type KeyType int - const ( - // KeyTypeValue represents data type. - KeyTypeValue KeyType = iota + 1 - // KeyTypeHash represents hash of the data type. - KeyTypeHash - // KeyTypeSignature represents signature of the data type. - KeyTypeSignature + hashName = "hash" + signatureName = "sig" ) -// Key implements internal realization. -type Key struct { - Name string // Object identificator. - Type KeyType // Type of the object. - Property string // Additional information (version/algorithm). +type InvalidKeyError struct { + Key string + Problem string +} + +func (e InvalidKeyError) Error() string { + return fmt.Sprintf("invalid key '%s': %s", e.Key, e.Problem) +} + +func errInvalidKey(key string, problem string) error { + return InvalidKeyError{ + Key: key, + Problem: problem, + } +} + +type InvalidNameError struct { + Name string + Problem string +} + +func (e InvalidNameError) Error() string { + return fmt.Sprintf("invalid name '%s': %s", e.Name, e.Problem) +} + +func errInvalidName(name string, problem string) error { + return InvalidNameError{ + Name: name, + Problem: problem, + } +} + +// Results represents Namer working result. +type Results struct { + isSingle bool // True if result contains only one object name. + isSingleName string // Cached name when isSingle=true. + result map[string][]Key // Grouped keys: object name -> key list. +} + +func getFirstFromMap(m map[string][]Key) string { + for name := range m { + return name + } + return "" +} + +func NewResults(initial map[string][]Key) Results { + return Results{ + isSingle: len(initial) == 1, + isSingleName: getFirstFromMap(initial), + result: initial, + } +} + +// SelectSingle gets keys for single-name case (if applicable). +func (r *Results) SelectSingle() ([]Key, bool) { + if r.isSingle { + return r.result[r.isSingleName], true + } + + return nil, false +} + +// Items return iterator over all name->keys groups. +func (r *Results) Items() iter.Seq2[string, []Key] { + return func(yield func(str string, res []Key) bool) { + for i, v := range r.result { + if !yield(i, v) { + return + } + } + } +} + +func (r *Results) Result() map[string][]Key { + return r.result } -// Namer represents keys naming strategy. -type Namer interface { - GenerateNames(name string) []string // Object's keys generation. - ParseNames(names []string) []Key // Convert names into keys. +// Select gets keys for a specific object name. +func (r *Results) Select(name string) ([]Key, bool) { + if i, ok := r.result[name]; ok { + return i, true + } + + return nil, false +} + +// Len returns the number of unique object names. +func (r *Results) Len() int { + return len(r.result) +} + +// DefaultNamer represents default namer. +type DefaultNamer struct { + prefix string // Key prefix (e.g., "storage/"). + hashNames []string + sigNames []string +} + +// NewDefaultNamer returns new DefaultNamer object with hash/signature names configuration. +func NewDefaultNamer(prefix string, hashNames []string, sigNames []string) *DefaultNamer { + return &DefaultNamer{ + prefix: strings.Trim(prefix, "/"), + hashNames: hashNames, + sigNames: sigNames, + } +} + +// GenerateNames all keys for an object name. +func (n *DefaultNamer) GenerateNames(name string) ([]Key, error) { + switch { + case name == "": + return nil, errInvalidName(name, "should not be empty") + case strings.HasSuffix(name, "/"): + return nil, errInvalidName(name, "should not be prefix") + } + + name = strings.TrimPrefix(name, "/") + + out := make([]Key, 0, len(n.hashNames)+len(n.sigNames)+1) + + out = append(out, + NewDefaultKey( + name, + KeyTypeValue, + "", + fmt.Sprintf("/%s/%s", n.prefix, name), + )) + + for _, hash := range n.hashNames { + out = append(out, + NewDefaultKey( + name, + KeyTypeHash, + hash, + fmt.Sprintf("/%s/%s/%s/%s", n.prefix, hashName, hash, name), + ), + ) + } + + for _, sig := range n.sigNames { + out = append(out, + NewDefaultKey( + name, + KeyTypeSignature, + sig, + fmt.Sprintf("/%s/%s/%s/%s", n.prefix, signatureName, sig, name), + ), + ) + } + + return out, nil } -// Generator generates signer K/V pairs. -// Implementation should use `generic` and will used for strong typing of the solution. -type Generator[T any] interface { - Generate(name string, value T) ([]kv.KeyValue, error) +func (n *DefaultNamer) ParseKey(name string) (DefaultKey, error) { + originalName := name + + name, found := strings.CutPrefix(strings.TrimPrefix(name, "/"), n.prefix) + if !found { + return DefaultKey{}, errInvalidKey(originalName, "prefix not found") + } + + name = strings.TrimPrefix(name, "/") + nameParts := strings.SplitN(name, "/", 3) + + switch { + case len(nameParts) <= 0 || len(nameParts) > 3: + panic("illegal state") // Unreachable. + + case nameParts[0] == signatureName: + switch { + case len(nameParts) != 3: + return DefaultKey{}, errInvalidKey(originalName, "found sig prefix, but key name is incomplete") + case len(nameParts[1]) == 0: + return DefaultKey{}, errInvalidKey(originalName, "found sig prefix, but hash name is invalid") + case len(nameParts[2]) == 0: + return DefaultKey{}, errInvalidKey(originalName, "found sig prefix, but key name is invalid") + case strings.HasSuffix(nameParts[2], "/"): + return DefaultKey{}, errInvalidKey(originalName, "found hash prefix, but key name is prefix") + } + + return NewDefaultKey( + nameParts[2], + KeyTypeSignature, + nameParts[1], + originalName, + ), nil + case nameParts[0] == hashName: + switch { + case len(nameParts) != 3: + return DefaultKey{}, errInvalidKey(originalName, "found hash prefix, but key name is incomplete") + case len(nameParts[1]) == 0: + return DefaultKey{}, errInvalidKey(originalName, "found hash prefix, but hash name is invalid") + case len(nameParts[2]) == 0: + return DefaultKey{}, errInvalidKey(originalName, "found hash prefix, but key name is invalid") + case strings.HasSuffix(nameParts[2], "/"): + return DefaultKey{}, errInvalidKey(originalName, "found hash prefix, but key name is prefix") + } + + return NewDefaultKey( + nameParts[2], + KeyTypeHash, + nameParts[1], + originalName, + ), nil + default: + if strings.HasSuffix(name, "/") { + return DefaultKey{}, errInvalidKey(originalName, "key name should not be prefix") + } + + return NewDefaultKey( + name, + KeyTypeValue, + "", + originalName, + ), nil + } } -// Validator validates and build the object from K/V. -type Validator[T any] interface { - Validate(pairs []kv.KeyValue) (T, error) +// ParseKeys combine multiple raw keys into grouped results. +func (n *DefaultNamer) ParseKeys(names []string, ignoreError bool) (Results, error) { + out := map[string][]Key{} + + for _, name := range names { + key, err := n.ParseKey(name) + switch { + case err != nil && ignoreError: + continue + case err != nil: + return Results{}, err + } + out[key.name] = append(out[key.name], key) + } + + return NewResults(out), nil } diff --git a/namer/namer_test.go b/namer/namer_test.go new file mode 100644 index 0000000..89f2093 --- /dev/null +++ b/namer/namer_test.go @@ -0,0 +1,413 @@ +package namer_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/tarantool/go-storage/namer" +) + +func TestDefaultNamer_GenerateNames_Invalid_Empty(t *testing.T) { + t.Parallel() + + dn := namer.NewDefaultNamer("/storage", nil, nil) + _, err := dn.GenerateNames("") + assert.Error(t, err) +} + +func TestDefaultNamer_GenerateNames_Invalid_Prefix(t *testing.T) { + t.Parallel() + + dn := namer.NewDefaultNamer("/storage", nil, nil) + _, err := dn.GenerateNames("123/") + assert.Error(t, err) +} + +func TestDefaultNamer_GenerateNames_Success(t *testing.T) { + t.Parallel() + + tests := []struct { + prefix string + name string + hashNames []string + sigNames []string + expected []namer.Key + }{ + { + "/storage", + "all", + []string{"sha256"}, + []string{"RSAPSS"}, + []namer.Key{ + namer.NewDefaultKey( + "all", + namer.KeyTypeValue, + "", + "/storage/all", + ), + namer.NewDefaultKey( + "all", + namer.KeyTypeHash, + "sha256", + "/storage/hash/sha256/all", + ), + namer.NewDefaultKey( + "all", + namer.KeyTypeSignature, + "RSAPSS", + "/storage/sig/RSAPSS/all", + ), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + dn := namer.NewDefaultNamer(tt.prefix, tt.hashNames, tt.sigNames) + + result, err := dn.GenerateNames(tt.name) + require.NoError(t, err) + assert.Equal(t, tt.expected, result) + }) + } +} + +func TestDefaultNamer_ParseKey_Success(t *testing.T) { + t.Parallel() + prefix := "/storage" + + tests := []struct { + input string + name string + tp namer.KeyType + property string + }{ + { + input: "/storage/all", + name: "all", + tp: namer.KeyTypeValue, + property: "", + }, + { + input: "/storage/hash/sha256/all", + name: "all", + tp: namer.KeyTypeHash, + property: "sha256", + }, + { + input: "/storage/sig/rsa/all", + name: "all", + tp: namer.KeyTypeSignature, + property: "rsa", + }, + } + + for _, tt := range tests { + t.Run("case:"+tt.input, func(t *testing.T) { + t.Parallel() + + dn := namer.NewDefaultNamer(prefix, nil, nil) + + key, err := dn.ParseKey(tt.input) + require.NoError(t, err) + assert.Equal(t, tt.name, key.Name()) + assert.Equal(t, tt.tp, key.Type()) + assert.Equal(t, tt.property, key.Property()) + assert.Equal(t, tt.input, key.Build()) + }) + } +} + +func TestDefaultNamer_ParseKey_Failed(t *testing.T) { + t.Parallel() + prefix := "/storage" + + tests := []string{ + "/not-storage/value", + "/storage/hash", + "/storage/hash/sha256", + "/storage/hash//all", + "/storage/hash/sha256/", + "/storage/hash/sha256/suffix/", + "/storage/sig", + "/storage/sig/rsa", + "/storage/sig//all", + "/storage/sig/rsa/", + "/storage/sig/rsa/suffix/", + "/storage/value-suffix/", + } + + for _, tt := range tests { + t.Run("case:"+tt, func(t *testing.T) { + t.Parallel() + + dn := namer.NewDefaultNamer(prefix, nil, nil) + _, err := dn.ParseKey(tt) + require.Error(t, err) + }) + } +} + +func TestDefaultNamer_ParseKeys_Success(t *testing.T) { + t.Parallel() + prefix := "/storage" + + tests := []struct { + name string + input []string + countMap map[string]int + singleName string + }{ + { + name: "non empty + single", + input: []string{ + "/storage/value", + "/storage/sig/signame/value", + "/storage/hash/hashname/value", + }, + countMap: map[string]int{"value": 3}, + singleName: "value", + }, + { + name: "non empty + multiple", + input: []string{ + "/storage/key1", + "/storage/sig/rsa/key1", + "/storage/hash/sha256/key1", + "/storage/key2", + "/storage/sig/rsa/key2", + "/storage/hash/sha256/key2", + }, + countMap: map[string]int{"key1": 3, "key2": 3}, + singleName: "", + }, + { + name: "empty", + input: []string{}, + countMap: map[string]int{}, + singleName: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + dn := namer.NewDefaultNamer(prefix, nil, nil) + + result, err := dn.ParseKeys(tt.input, false) + require.NoError(t, err) + require.Len(t, result.Result(), len(tt.countMap)) + + for k, v := range tt.countMap { + require.Contains(t, result.Result(), k) + assert.Len(t, result.Result()[k], v) + } + + if tt.singleName != "" { + _, ok := result.SelectSingle() + assert.True(t, ok) + } else { + _, ok := result.SelectSingle() + assert.False(t, ok) + } + }) + } +} + +func TestDefaultNamer_ParseKeys_Fail(t *testing.T) { + t.Parallel() + prefix := "/storage" + + t.Run("ignoreError = false", func(t *testing.T) { + t.Parallel() + + dn := namer.NewDefaultNamer(prefix, nil, nil) + _, err := dn.ParseKeys([]string{"/non-storage/value"}, false) + require.Error(t, err) + }) + + t.Run("ignoreError = true, skip all", func(t *testing.T) { + t.Parallel() + + dn := namer.NewDefaultNamer(prefix, nil, nil) + results, err := dn.ParseKeys([]string{"/non-storage/value"}, true) + require.NoError(t, err) + assert.Len(t, results.Result(), 0) + }) + + t.Run("ignoreError = true", func(t *testing.T) { + t.Parallel() + + dn := namer.NewDefaultNamer(prefix, nil, nil) + results, err := dn.ParseKeys([]string{ + "/non-storage/value", + "/storage/value-1", + }, true) + require.NoError(t, err) + assert.Len(t, results.Result(), 1) + assert.Contains(t, results.Result(), "value-1") + }) +} + +func TestInvalidNameError(t *testing.T) { + t.Parallel() + + err := namer.InvalidNameError{Name: "name", Problem: "problem"} + assert.Equal(t, err.Error(), "invalid name 'name': problem") +} + +func TestNewResults(t *testing.T) { + t.Parallel() + + require.NotNil(t, namer.NewResults(map[string][]namer.Key{})) +} + +func TestResults_SelectSingle(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + results map[string][]namer.Key + isSingleResult bool + }{ + { + name: "single", + results: map[string][]namer.Key{"key": {}}, + isSingleResult: true, + }, + { + name: "multiple", + results: map[string][]namer.Key{"key1": {}, "key2": {}}, + isSingleResult: false, + }, + { + name: "empty", + results: map[string][]namer.Key{}, + isSingleResult: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + r := namer.NewResults(tt.results) + _, ok := r.SelectSingle() + require.Equal(t, ok, tt.isSingleResult) + }) + } +} + +func TestResults_Len(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + results map[string][]namer.Key + len int + }{ + { + name: "single", + results: map[string][]namer.Key{"key": {}}, + len: 1, + }, + { + name: "multiple", + results: map[string][]namer.Key{"key1": {}, "key2": {}}, + len: 2, + }, + { + name: "empty", + results: map[string][]namer.Key{}, + len: 0, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + r := namer.NewResults(tt.results) + resultsLen := r.Len() + require.Equal(t, resultsLen, tt.len) + }) + } +} + +func TestResults_Items(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + results map[string][]namer.Key + oneOf []string + }{ + { + name: "single", + results: map[string][]namer.Key{"key": {}}, + oneOf: []string{"key"}, + }, + { + name: "multiple", + results: map[string][]namer.Key{"key1": {}, "key2": {}}, + oneOf: []string{"key1", "key2"}, + }, + { + name: "empty", + results: map[string][]namer.Key{}, + oneOf: []string{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cnt := 0 + r := namer.NewResults(tt.results) + for name := range r.Items() { + cnt++ + assert.Contains(t, tt.oneOf, name) + } + assert.Equal(t, len(tt.oneOf), cnt) + }) + } +} + +func TestResults_Select(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + results map[string][]namer.Key + oneOf []string + }{ + { + name: "single", + results: map[string][]namer.Key{"key": {}}, + oneOf: []string{"key"}, + }, + { + name: "multiple", + results: map[string][]namer.Key{"key1": {}, "key2": {}}, + oneOf: []string{"key1", "key2"}, + }, + { + name: "empty", + results: map[string][]namer.Key{}, + oneOf: []string{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + r := namer.NewResults(tt.results) + for _, name := range tt.oneOf { + _, ok := r.Select(name) + assert.True(t, ok) + } + + _, ok := r.Select("not-presented") + assert.False(t, ok) + }) + } +} diff --git a/crypto/interfaces.go b/verification/interfaces.go similarity index 88% rename from crypto/interfaces.go rename to verification/interfaces.go index 0dcbab3..f9acfe8 100644 --- a/crypto/interfaces.go +++ b/verification/interfaces.go @@ -1,5 +1,5 @@ -// Package crypto implements crypto interfaces. -package crypto +// Package verification implements verification interfaces. +package verification // Signer implements high-level API for package signing. type Signer interface { diff --git a/crypto/rsa.go b/verification/rsapss.go similarity index 89% rename from crypto/rsa.go rename to verification/rsapss.go index 0f2234e..bdcc3dd 100644 --- a/crypto/rsa.go +++ b/verification/rsapss.go @@ -1,4 +1,4 @@ -package crypto +package verification import ( "crypto" @@ -29,12 +29,12 @@ func NewRSAPSS(privKey rsa.PrivateKey, pubKey rsa.PublicKey) RSAPSS { } // Name implements SignerVerifier interface. -func (r *RSAPSS) Name() string { +func (r RSAPSS) Name() string { return "RSASSA-PSS" } // Sign generates SHA-256 digest and signs it using RSASSA-PSS. -func (r *RSAPSS) Sign(data []byte) ([]byte, error) { +func (r RSAPSS) Sign(data []byte) ([]byte, error) { digest, err := r.hasher.Hash(data) if err != nil { return []byte{}, fmt.Errorf("failed to get hash: %w", err) @@ -52,7 +52,7 @@ func (r *RSAPSS) Sign(data []byte) ([]byte, error) { } // Verify compares data with signature. -func (r *RSAPSS) Verify(data []byte, signature []byte) error { +func (r RSAPSS) Verify(data []byte, signature []byte) error { digest, err := r.hasher.Hash(data) if err != nil { return fmt.Errorf("failed to get hash: %w", err) diff --git a/crypto/rsa_test.go b/verification/rsapss_test.go similarity index 81% rename from crypto/rsa_test.go rename to verification/rsapss_test.go index 3645f35..091f305 100644 --- a/crypto/rsa_test.go +++ b/verification/rsapss_test.go @@ -1,4 +1,4 @@ -package crypto_test +package verification_test import ( "crypto/rand" @@ -6,13 +6,14 @@ import ( "testing" "github.com/stretchr/testify/require" - "github.com/tarantool/go-storage/crypto" + + "github.com/tarantool/go-storage/verification" ) func TestRsaWithoutKeys(t *testing.T) { t.Parallel() - rsapss := crypto.NewRSAPSS(rsa.PrivateKey{}, rsa.PublicKey{}) //nolint:exhaustruct + rsapss := verification.NewRSAPSS(rsa.PrivateKey{}, rsa.PublicKey{}) //nolint:exhaustruct require.NotNil(t, rsapss, "rsapss must be returned") data := []byte("abc") @@ -31,7 +32,7 @@ func TestRsaOnlyPrivateKey(t *testing.T) { privateKey, err := rsa.GenerateKey(rand.Reader, 2048) require.NoError(t, err) - rsapss := crypto.NewRSAPSS(*privateKey, rsa.PublicKey{}) //nolint:exhaustruct + rsapss := verification.NewRSAPSS(*privateKey, rsa.PublicKey{}) //nolint:exhaustruct require.NotNil(t, rsapss, "rsapss must be returned") data := []byte("abc") @@ -50,7 +51,7 @@ func TestRsaOnlyPublicKey(t *testing.T) { privateKey, err := rsa.GenerateKey(rand.Reader, 2048) require.NoError(t, err) - rsapss := crypto.NewRSAPSS(rsa.PrivateKey{}, privateKey.PublicKey) //nolint:exhaustruct + rsapss := verification.NewRSAPSS(rsa.PrivateKey{}, privateKey.PublicKey) //nolint:exhaustruct require.NotNil(t, rsapss, "rsapss must be returned") data := []byte("abc") @@ -60,7 +61,7 @@ func TestRsaOnlyPublicKey(t *testing.T) { require.Nil(t, sig, "signature must be nil") // Re-create to have a valid sign. - rsapss = crypto.NewRSAPSS(*privateKey, privateKey.PublicKey) + rsapss = verification.NewRSAPSS(*privateKey, privateKey.PublicKey) require.NotNil(t, rsapss, "rsapss must be returned") sign, err := rsapss.Sign(data) @@ -77,7 +78,7 @@ func TestRsaSignVerify(t *testing.T) { privateKey, err := rsa.GenerateKey(rand.Reader, 2048) require.NoError(t, err) - rsapss := crypto.NewRSAPSS(*privateKey, privateKey.PublicKey) + rsapss := verification.NewRSAPSS(*privateKey, privateKey.PublicKey) require.NotNil(t, rsapss, "rsapss must be returned") data := []byte("abc")