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:
alexvanin 2020-01-16 17:32:57 +03:00
parent f1418ef79d
commit 81cdfcc502
3 changed files with 64 additions and 15 deletions

View file

@ -1,4 +1,5 @@
package object
// todo: all extensions must be transferred to the separate util library
import "github.com/nspcc-dev/neofs-proto/storagegroup"

View file

@ -68,24 +68,30 @@ func (m Object) Verify() error {
var (
err error
checksum []byte
pubkey []byte
)
// Prepare structures
_, vh := m.LastHeader(HeaderType(VerifyHdr))
if vh == nil {
return ErrHeaderNotFound
}
verify := vh.Value.(*Header_Verify).Verify
_, ih := m.LastHeader(HeaderType(IntegrityHdr))
if ih == nil {
ind, ih := m.LastHeader(HeaderType(IntegrityHdr))
if ih == nil || ind != len(m.Headers) - 1{
return ErrHeaderNotFound
}
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
err = m.verifySignature(verify.PublicKey, integrity)
err = m.verifySignature(pubkey, integrity)
if err != nil {
return errors.Wrapf(err, "public key: %x", verify.PublicKey)
return errors.Wrapf(err, "public key: %x", pubkey)
}
// Verify checksum of header

View file

@ -56,7 +56,7 @@ func TestObject_Verify(t *testing.T) {
obj.SetPayload(payload)
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()
require.EqualError(t, err, ErrHeaderNotFound.Error())
})
@ -83,12 +83,25 @@ func TestObject_Verify(t *testing.T) {
}
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) {
err = obj.Verify()
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) {
err = obj.Verify()
@ -96,10 +109,39 @@ func TestObject_Verify(t *testing.T) {
})
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()
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)
})
}