forked from TrueCloudLab/frostfs-api-go
object: Update verify routine
Verify routine now supports public key field to check if integrity header contains correct signature of object header. Verify also have strict check that integrity header is last header in the list of headers.
This commit is contained in:
parent
f1418ef79d
commit
81cdfcc502
3 changed files with 64 additions and 15 deletions
|
@ -1,4 +1,5 @@
|
||||||
package object
|
package object
|
||||||
|
// todo: all extensions must be transferred to the separate util library
|
||||||
|
|
||||||
import "github.com/nspcc-dev/neofs-proto/storagegroup"
|
import "github.com/nspcc-dev/neofs-proto/storagegroup"
|
||||||
|
|
||||||
|
|
|
@ -68,24 +68,30 @@ func (m Object) Verify() error {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
checksum []byte
|
checksum []byte
|
||||||
|
pubkey []byte
|
||||||
)
|
)
|
||||||
// Prepare structures
|
ind, ih := m.LastHeader(HeaderType(IntegrityHdr))
|
||||||
_, vh := m.LastHeader(HeaderType(VerifyHdr))
|
if ih == nil || ind != len(m.Headers) - 1{
|
||||||
if vh == nil {
|
|
||||||
return ErrHeaderNotFound
|
|
||||||
}
|
|
||||||
verify := vh.Value.(*Header_Verify).Verify
|
|
||||||
|
|
||||||
_, ih := m.LastHeader(HeaderType(IntegrityHdr))
|
|
||||||
if ih == nil {
|
|
||||||
return ErrHeaderNotFound
|
return ErrHeaderNotFound
|
||||||
}
|
}
|
||||||
integrity := ih.Value.(*Header_Integrity).Integrity
|
integrity := ih.Value.(*Header_Integrity).Integrity
|
||||||
|
|
||||||
|
// Prepare structures
|
||||||
|
_, vh := m.LastHeader(HeaderType(VerifyHdr))
|
||||||
|
if vh == nil {
|
||||||
|
_, pkh := m.LastHeader(HeaderType(PublicKeyHdr))
|
||||||
|
if pkh == nil {
|
||||||
|
return ErrHeaderNotFound
|
||||||
|
}
|
||||||
|
pubkey = pkh.Value.(*Header_PublicKey).PublicKey.Value
|
||||||
|
} else {
|
||||||
|
pubkey = vh.Value.(*Header_Verify).Verify.PublicKey
|
||||||
|
}
|
||||||
|
|
||||||
// Verify signature
|
// Verify signature
|
||||||
err = m.verifySignature(verify.PublicKey, integrity)
|
err = m.verifySignature(pubkey, integrity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "public key: %x", verify.PublicKey)
|
return errors.Wrapf(err, "public key: %x", pubkey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify checksum of header
|
// Verify checksum of header
|
||||||
|
|
|
@ -56,7 +56,7 @@ func TestObject_Verify(t *testing.T) {
|
||||||
obj.SetPayload(payload)
|
obj.SetPayload(payload)
|
||||||
obj.SetHeader(&Header{Value: &Header_PayloadChecksum{[]byte("incorrect checksum")}})
|
obj.SetHeader(&Header{Value: &Header_PayloadChecksum{[]byte("incorrect checksum")}})
|
||||||
|
|
||||||
t.Run("error no integrity header", func(t *testing.T) {
|
t.Run("error no integrity header and pubkey", func(t *testing.T) {
|
||||||
err = obj.Verify()
|
err = obj.Verify()
|
||||||
require.EqualError(t, err, ErrHeaderNotFound.Error())
|
require.EqualError(t, err, ErrHeaderNotFound.Error())
|
||||||
})
|
})
|
||||||
|
@ -83,12 +83,25 @@ func TestObject_Verify(t *testing.T) {
|
||||||
}
|
}
|
||||||
obj.SetVerificationHeader(vh)
|
obj.SetVerificationHeader(vh)
|
||||||
|
|
||||||
|
// validation header is not last
|
||||||
|
t.Run("error validation header is not last", func(t *testing.T) {
|
||||||
|
err = obj.Verify()
|
||||||
|
require.EqualError(t, err, ErrHeaderNotFound.Error())
|
||||||
|
})
|
||||||
|
|
||||||
|
obj.Headers = obj.Headers[:len(obj.Headers)-2]
|
||||||
|
obj.SetVerificationHeader(vh)
|
||||||
|
obj.SetHeader(&Header{Value: &Header_Integrity{ih}})
|
||||||
|
|
||||||
t.Run("error invalid header checksum", func(t *testing.T) {
|
t.Run("error invalid header checksum", func(t *testing.T) {
|
||||||
err = obj.Verify()
|
err = obj.Verify()
|
||||||
require.EqualError(t, err, ErrVerifyHeader.Error())
|
require.EqualError(t, err, ErrVerifyHeader.Error())
|
||||||
})
|
})
|
||||||
|
|
||||||
require.NoError(t, obj.Sign(sessionkey))
|
obj.Headers = obj.Headers[:len(obj.Headers)-1]
|
||||||
|
genIH, err := CreateIntegrityHeader(obj, sessionkey)
|
||||||
|
require.NoError(t, err)
|
||||||
|
obj.SetHeader(genIH)
|
||||||
|
|
||||||
t.Run("error invalid payload checksum", func(t *testing.T) {
|
t.Run("error invalid payload checksum", func(t *testing.T) {
|
||||||
err = obj.Verify()
|
err = obj.Verify()
|
||||||
|
@ -96,10 +109,39 @@ func TestObject_Verify(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
obj.SetHeader(&Header{Value: &Header_PayloadChecksum{obj.PayloadChecksum()}})
|
obj.SetHeader(&Header{Value: &Header_PayloadChecksum{obj.PayloadChecksum()}})
|
||||||
require.NoError(t, obj.Sign(sessionkey))
|
|
||||||
|
|
||||||
t.Run("correct", func(t *testing.T) {
|
obj.Headers = obj.Headers[:len(obj.Headers)-1]
|
||||||
|
genIH, err = CreateIntegrityHeader(obj, sessionkey)
|
||||||
|
require.NoError(t, err)
|
||||||
|
obj.SetHeader(genIH)
|
||||||
|
|
||||||
|
t.Run("correct with vh", func(t *testing.T) {
|
||||||
err = obj.Verify()
|
err = obj.Verify()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
pkh := Header{Value: &Header_PublicKey{&PublicKey{
|
||||||
|
Value: crypto.MarshalPublicKey(&key.PublicKey),
|
||||||
|
}}}
|
||||||
|
// replace vh with pkh
|
||||||
|
obj.Headers[len(obj.Headers)-2] = pkh
|
||||||
|
// re-sign object
|
||||||
|
obj.Sign(sessionkey)
|
||||||
|
|
||||||
|
|
||||||
|
t.Run("incorrect with bad public key", func(t *testing.T) {
|
||||||
|
err = obj.Verify()
|
||||||
|
require.Error(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
obj.SetHeader(&Header{Value: &Header_PublicKey{&PublicKey{
|
||||||
|
Value: dataPK,
|
||||||
|
}}})
|
||||||
|
obj.Sign(sessionkey)
|
||||||
|
|
||||||
|
t.Run("correct with good public key", func(t *testing.T) {
|
||||||
|
err = obj.Verify()
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue