Skip to content

Commit

Permalink
Merge pull request #1378 from 0chain/hotfix/download-sig
Browse files Browse the repository at this point in the history
verify client in download handler
  • Loading branch information
dabasov committed Feb 10, 2024
2 parents cce361c + 9f54632 commit d1f396d
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 48 deletions.
6 changes: 4 additions & 2 deletions code/go/0chain.net/blobbercore/handler/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ type Context struct {
// AllocationId optional. allocation id in request
AllocationId string
// Signature optional. signature in request
Signature string
Signature string
SignatureV2 string

Allocation *allocation.Allocation

Expand Down Expand Up @@ -163,6 +164,7 @@ func WithTxHandler(handler func(ctx *Context) (interface{}, error)) func(w http.
ctx.ClientKey = r.Header.Get(common.ClientKeyHeader)
ctx.AllocationId = r.Header.Get(common.AllocationIdHeader)
ctx.Signature = r.Header.Get(common.ClientSignatureHeader)
ctx.SignatureV2 = r.Header.Get(common.ClientSignatureHeaderV2)

ctx, err := WithVerify(ctx, r)
statusCode = ctx.StatusCode
Expand Down Expand Up @@ -222,7 +224,7 @@ func WithVerify(ctx *Context, r *http.Request) (*Context, error) {

publicKey := alloc.OwnerPublicKey

valid, err := verifySignatureFromRequest(allocationTx, ctx.Signature, publicKey)
valid, err := verifySignatureFromRequest(allocationTx, ctx.Signature, ctx.SignatureV2, publicKey)

if !valid {
ctx.StatusCode = http.StatusBadRequest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type DownloadRequestHeader struct {
VerifyDownload bool
DownloadMode string
ConnectionID string
Version string
}

func FromDownloadRequest(allocationID string, req *http.Request, isRedeem bool) (*DownloadRequestHeader, error) {
Expand Down Expand Up @@ -103,6 +104,7 @@ func (dr *DownloadRequestHeader) Parse(isRedeem bool) error {

dr.DownloadMode = dr.Get("X-Mode")
dr.VerifyDownload = dr.Get("X-Verify-Download") == "true"
dr.Version = dr.Get("X-Version")
return nil
}

Expand Down
11 changes: 8 additions & 3 deletions code/go/0chain.net/blobbercore/handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,8 @@ func setupHandlerContext(ctx context.Context, r *http.Request) context.Context {

// signature is not requered for all requests, but if header is empty it won`t affect anything
ctx = context.WithValue(ctx, constants.ContextKeyClientSignatureHeaderKey, r.Header.Get(common.ClientSignatureHeader))
// signature V2
ctx = context.WithValue(ctx, constants.ContextKeyClientSignatureHeaderV2Key, r.Header.Get(common.ClientSignatureHeaderV2))
return ctx
}

Expand Down Expand Up @@ -806,8 +808,9 @@ func RevokeShare(ctx context.Context, r *http.Request) (interface{}, error) {
}

sign := r.Header.Get(common.ClientSignatureHeader)
signV2 := r.Header.Get(common.ClientSignatureHeaderV2)

valid, err := verifySignatureFromRequest(allocationTx, sign, allocationObj.OwnerPublicKey)
valid, err := verifySignatureFromRequest(allocationTx, sign, signV2, allocationObj.OwnerPublicKey)
if !valid || err != nil {
return nil, common.NewError("invalid_signature", "Invalid signature")
}
Expand Down Expand Up @@ -867,8 +870,9 @@ func InsertShare(ctx context.Context, r *http.Request) (interface{}, error) {
}

sign := r.Header.Get(common.ClientSignatureHeader)
signV2 := r.Header.Get(common.ClientSignatureHeaderV2)

valid, err := verifySignatureFromRequest(allocationTx, sign, allocationObj.OwnerPublicKey)
valid, err := verifySignatureFromRequest(allocationTx, sign, signV2, allocationObj.OwnerPublicKey)
if !valid || err != nil {
return nil, common.NewError("invalid_signature", "Invalid signature")
}
Expand Down Expand Up @@ -958,8 +962,9 @@ func ListShare(ctx context.Context, r *http.Request) (interface{}, error) {
}

sign := r.Header.Get(common.ClientSignatureHeader)
signV2 := r.Header.Get(common.ClientSignatureHeaderV2)

valid, err := verifySignatureFromRequest(allocationTx, sign, allocationObj.OwnerPublicKey)
valid, err := verifySignatureFromRequest(allocationTx, sign, signV2, allocationObj.OwnerPublicKey)
if !valid || err != nil {
return nil, common.NewError("invalid_signature", "Invalid signature")
}
Expand Down
15 changes: 8 additions & 7 deletions code/go/0chain.net/blobbercore/handler/handler_download_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ func TestHandlers_Download(t *testing.T) {
// setupEncryptionScheme()

router, handlers := setupDownloadHandlers()
signScheme := "bls0chain"

sch := zcncrypto.NewSignatureScheme("bls0chain")
//sch.Mnemonic = "expose culture dignity plastic digital couple promote best pool error brush upgrade correct art become lobster nature moment obtain trial multiply arch miss toe"
Expand Down Expand Up @@ -222,7 +223,7 @@ func TestHandlers_Download(t *testing.T) {
}

hash := encryption.Hash(alloc.Tx)
sign, err := sch.Sign(hash)
sign, err := ownerClient.Sign(hash, signScheme)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -291,7 +292,7 @@ func TestHandlers_Download(t *testing.T) {
t.Fatal(err)
}
hash := encryption.Hash(alloc.Tx)
sign, err := sch.Sign(hash)
sign, err := ownerClient.Sign(hash, signScheme)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -472,7 +473,7 @@ func TestHandlers_Download(t *testing.T) {
t.Fatal(err)
}
hash := encryption.Hash(alloc.Tx)
sign, err := sch.Sign(hash)
sign, err := guestClient.Sign(hash, signScheme)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -554,7 +555,7 @@ func TestHandlers_Download(t *testing.T) {
t.Fatal(err)
}
hash := encryption.Hash(alloc.Tx)
sign, err := sch.Sign(hash)
sign, err := guestClient.Sign(hash, signScheme)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -667,7 +668,7 @@ func TestHandlers_Download(t *testing.T) {
}

hash := encryption.Hash(alloc.Tx)
sign, err := sch.Sign(hash)
sign, err := guestClient.Sign(hash, signScheme)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -787,7 +788,7 @@ func TestHandlers_Download(t *testing.T) {
}

hash := encryption.Hash(alloc.Tx)
sign, err := sch.Sign(hash)
sign, err := guestClient.Sign(hash, signScheme)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -906,7 +907,7 @@ func TestHandlers_Download(t *testing.T) {
}

hash := encryption.Hash(alloc.Tx)
sign, err := sch.Sign(hash)
sign, err := guestClient.Sign(hash, signScheme)
if err != nil {
t.Fatal(err)
}
Expand Down
42 changes: 27 additions & 15 deletions code/go/0chain.net/blobbercore/handler/object_operation_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,15 +267,16 @@ func (fsh *StorageHandler) DownloadFile(ctx context.Context, r *http.Request) (i
// get client and allocation ids

var (
clientID = ctx.Value(constants.ContextKeyClient).(string)
allocationTx = ctx.Value(constants.ContextKeyAllocation).(string)
allocationID = ctx.Value(constants.ContextKeyAllocationID).(string)
alloc *allocation.Allocation
blobberID = node.Self.ID
quotaManager = getQuotaManager()
clientID = ctx.Value(constants.ContextKeyClient).(string)
clientPublicKey = ctx.Value(constants.ContextKeyClientKey).(string)
allocationTx = ctx.Value(constants.ContextKeyAllocation).(string)
allocationID = ctx.Value(constants.ContextKeyAllocationID).(string)
alloc *allocation.Allocation
blobberID = node.Self.ID
quotaManager = getQuotaManager()
)

if clientID == "" {
if clientID == "" || clientPublicKey == "" {
return nil, common.NewError("download_file", "invalid client")
}

Expand Down Expand Up @@ -320,6 +321,12 @@ func (fsh *StorageHandler) DownloadFile(ctx context.Context, r *http.Request) (i
if dr.AuthToken == "" {
return nil, common.NewError("invalid_authticket", "authticket is required")
}
if dr.Version == "v2" {
valid, err := verifySignatureFromRequest(allocationTx, r.Header.Get(common.ClientSignatureHeader), r.Header.Get(common.ClientSignatureHeaderV2), clientPublicKey)
if !valid || err != nil {
return nil, common.NewError("invalid_signature", "Invalid signature")
}
}
authTokenString, err := base64.StdEncoding.DecodeString(dr.AuthToken)
if err != nil {
return nil, common.NewError("invalid_authticket", err.Error())
Expand All @@ -343,6 +350,13 @@ func (fsh *StorageHandler) DownloadFile(ctx context.Context, r *http.Request) (i
return nil, common.NewErrorf("download_file", "the file is not available until: %v", shareInfo.AvailableAt.UTC().Format("2006-01-02T15:04:05"))
}

} else {
if dr.Version == "v2" {
valid, err := verifySignatureFromRequest(allocationTx, r.Header.Get(common.ClientSignatureHeader), r.Header.Get(common.ClientSignatureHeaderV2), alloc.OwnerPublicKey)
if !valid || err != nil {
return nil, common.NewError("invalid_signature", "Invalid signature")
}
}
}

isReadFree := alloc.IsReadFree(blobberID)
Expand Down Expand Up @@ -464,7 +478,7 @@ func (fsh *StorageHandler) CreateConnection(ctx context.Context, r *http.Request
return nil, common.NewError("invalid_operation", "Operation needs to be performed by the owner or the payer of the allocation")
}

valid, err := verifySignatureFromRequest(allocationTx, r.Header.Get(common.ClientSignatureHeader), allocationObj.OwnerPublicKey)
valid, err := verifySignatureFromRequest(allocationTx, r.Header.Get(common.ClientSignatureHeader), r.Header.Get(common.ClientSignatureHeaderV2), allocationObj.OwnerPublicKey)
if !valid || err != nil {
return nil, common.NewError("invalid_signature", "Invalid signature")
}
Expand Down Expand Up @@ -766,8 +780,7 @@ func (fsh *StorageHandler) RenameObject(ctx context.Context, r *http.Request) (i

clientID := ctx.Value(constants.ContextKeyClient).(string)
_ = ctx.Value(constants.ContextKeyClientKey).(string)

valid, err := verifySignatureFromRequest(allocationTx, r.Header.Get(common.ClientSignatureHeader), allocationObj.OwnerPublicKey)
valid, err := verifySignatureFromRequest(allocationTx, r.Header.Get(common.ClientSignatureHeader), r.Header.Get(common.ClientSignatureHeaderV2), allocationObj.OwnerPublicKey)
if !valid || err != nil {
return nil, common.NewError("invalid_signature", "Invalid signature")
}
Expand Down Expand Up @@ -848,7 +861,7 @@ func (fsh *StorageHandler) CopyObject(ctx context.Context, r *http.Request) (int
return nil, common.NewError("prohibited_allocation_file_options", "Cannot copy data from this allocation.")
}

valid, err := verifySignatureFromRequest(allocationTx, r.Header.Get(common.ClientSignatureHeader), allocationObj.OwnerPublicKey)
valid, err := verifySignatureFromRequest(allocationTx, r.Header.Get(common.ClientSignatureHeader), r.Header.Get(common.ClientSignatureHeaderV2), allocationObj.OwnerPublicKey)
if !valid || err != nil {
return nil, common.NewError("invalid_signature", "Invalid signature")
}
Expand Down Expand Up @@ -957,8 +970,7 @@ func (fsh *StorageHandler) MoveObject(ctx context.Context, r *http.Request) (int
return nil, common.NewError("prohibited_allocation_file_options", "Cannot move data in this allocation.")
}

valid, err := verifySignatureFromRequest(
allocationTx, r.Header.Get(common.ClientSignatureHeader), allocationObj.OwnerPublicKey)
valid, err := verifySignatureFromRequest(allocationTx, r.Header.Get(common.ClientSignatureHeader), r.Header.Get(common.ClientSignatureHeaderV2), allocationObj.OwnerPublicKey)
if !valid || err != nil {
return nil, common.NewError("invalid_signature", "Invalid signature")
}
Expand Down Expand Up @@ -1109,7 +1121,7 @@ func (fsh *StorageHandler) CreateDir(ctx context.Context, r *http.Request) (*all
return nil, common.NewError("invalid_parameters", "Invalid allocation id passed."+err.Error())
}

valid, err := verifySignatureFromRequest(allocationTx, r.Header.Get(common.ClientSignatureHeader), allocationObj.OwnerPublicKey)
valid, err := verifySignatureFromRequest(allocationTx, r.Header.Get(common.ClientSignatureHeader), r.Header.Get(common.ClientSignatureHeaderV2), allocationObj.OwnerPublicKey)
if !valid || err != nil {
return nil, common.NewError("invalid_signature", "Invalid signature")
}
Expand Down Expand Up @@ -1240,7 +1252,7 @@ func (fsh *StorageHandler) WriteFile(ctx context.Context, r *http.Request) (*all
st = time.Now()
publicKey := allocationObj.OwnerPublicKey

valid, err := verifySignatureFromRequest(allocationTx, r.Header.Get(common.ClientSignatureHeader), publicKey)
valid, err := verifySignatureFromRequest(allocationTx, r.Header.Get(common.ClientSignatureHeader), r.Header.Get(common.ClientSignatureHeaderV2), publicKey)

if !valid || err != nil {
return nil, common.NewError("invalid_signature", "Invalid signature")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"net/http/httptest"
"time"

"github.com/0chain/blobber/code/go/0chain.net/core/encryption"
"github.com/0chain/blobber/code/go/0chain.net/core/transaction"

"github.com/0chain/blobber/code/go/0chain.net/blobbercore/reference"
Expand Down Expand Up @@ -114,6 +115,8 @@ func TestDownloadFile(t *testing.T) {
req.Header.Set("X-Block-Num", fmt.Sprintf("%d", p.inData.blockNum))
req.Header.Set("X-Num-Blocks", fmt.Sprintf("%d", p.inData.numBlocks))
req.Header.Set(common.AllocationIdHeader, mockAllocationId)
sign, _ := client.Sign(encryption.Hash(mockAllocationTx))
req.Header.Set("X-App-Client-Signature", sign)

if p.useAuthTicket {
authTicket := &marker.AuthTicket{
Expand Down
45 changes: 30 additions & 15 deletions code/go/0chain.net/blobbercore/handler/storage_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/0chain/blobber/code/go/0chain.net/core/common"
"github.com/0chain/blobber/code/go/0chain.net/core/encryption"
. "github.com/0chain/blobber/code/go/0chain.net/core/logging"
"github.com/0chain/blobber/code/go/0chain.net/core/node"
)

const (
Expand Down Expand Up @@ -136,7 +137,7 @@ func (fsh *StorageHandler) GetFileMeta(ctx context.Context, r *http.Request) (in
if isOwner {
publicKey := alloc.OwnerPublicKey

valid, err := verifySignatureFromRequest(allocationTx, r.Header.Get(common.ClientSignatureHeader), publicKey)
valid, err := verifySignatureFromRequest(allocationTx, r.Header.Get(common.ClientSignatureHeader), r.Header.Get(common.ClientSignatureHeaderV2), publicKey)
if !valid || err != nil {
return nil, common.NewError("invalid_signature", "Invalid signature")
}
Expand Down Expand Up @@ -180,7 +181,7 @@ func (fsh *StorageHandler) GetFilesMetaByName(ctx context.Context, r *http.Reque
if isOwner {
publicKey := alloc.OwnerPublicKey

valid, err := verifySignatureFromRequest(allocationTx, r.Header.Get(common.ClientSignatureHeader), publicKey)
valid, err := verifySignatureFromRequest(allocationTx, r.Header.Get(common.ClientSignatureHeader), r.Header.Get(common.ClientSignatureHeaderV2), publicKey)
if !valid || err != nil {
return nil, common.NewError("invalid_signature", "Invalid signature")
}
Expand Down Expand Up @@ -223,7 +224,8 @@ func (fsh *StorageHandler) GetFileStats(ctx context.Context, r *http.Request) (i
allocationID := allocationObj.ID

clientSign, _ := ctx.Value(constants.ContextKeyClientSignatureHeaderKey).(string)
valid, err := verifySignatureFromRequest(allocationTx, clientSign, allocationObj.OwnerPublicKey)
clientSignV2, _ := ctx.Value(constants.ContextKeyClientSignatureHeaderV2Key).(string)
valid, err := verifySignatureFromRequest(allocationTx, clientSign, clientSignV2, allocationObj.OwnerPublicKey)
if !valid || err != nil {
return nil, common.NewError("invalid_signature", "Invalid signature")
}
Expand Down Expand Up @@ -431,8 +433,8 @@ func (fsh *StorageHandler) GetLatestWriteMarker(ctx context.Context, r *http.Req

clientSign, _ := ctx.Value(constants.ContextKeyClientSignatureHeaderKey).(string)
publicKey := allocationObj.OwnerPublicKey

valid, err := verifySignatureFromRequest(allocationTx, clientSign, publicKey)
clientSignV2 := ctx.Value(constants.ContextKeyClientSignatureHeaderV2Key).(string)
valid, err := verifySignatureFromRequest(allocationTx, clientSign, clientSignV2, publicKey)
if !valid || err != nil {
return nil, common.NewError("invalid_signature", "could not verify the allocation owner")
}
Expand Down Expand Up @@ -513,7 +515,8 @@ func (fsh *StorageHandler) getReferencePath(ctx context.Context, r *http.Request

publicKey := allocationObj.OwnerPublicKey

valid, err := verifySignatureFromRequest(allocationTx, clientSign, publicKey)
clientSignV2 := ctx.Value(constants.ContextKeyClientSignatureHeaderV2Key).(string)
valid, err := verifySignatureFromRequest(allocationTx, clientSign, clientSignV2, publicKey)
if !valid || err != nil {
errCh <- common.NewError("invalid_signature", "could not verify the allocation owner or collaborator")
return
Expand Down Expand Up @@ -575,7 +578,8 @@ func (fsh *StorageHandler) GetObjectTree(ctx context.Context, r *http.Request) (
allocationID := allocationObj.ID

clientSign, _ := ctx.Value(constants.ContextKeyClientSignatureHeaderKey).(string)
valid, err := verifySignatureFromRequest(allocationTx, clientSign, allocationObj.OwnerPublicKey)
clientSignV2 := ctx.Value(constants.ContextKeyClientSignatureHeaderV2Key).(string)
valid, err := verifySignatureFromRequest(allocationTx, clientSign, clientSignV2, allocationObj.OwnerPublicKey)
if !valid || err != nil {
return nil, common.NewError("invalid_signature", "Invalid signature")
}
Expand Down Expand Up @@ -644,8 +648,8 @@ func (fsh *StorageHandler) GetRecentlyAddedRefs(ctx context.Context, r *http.Req
}

clientSign := ctx.Value(constants.ContextKeyClientSignatureHeaderKey).(string)

valid, err := verifySignatureFromRequest(allocationTx, clientSign, allocationObj.OwnerPublicKey)
clientSignV2 := ctx.Value(constants.ContextKeyClientSignatureHeaderV2Key).(string)
valid, err := verifySignatureFromRequest(allocationTx, clientSign, clientSignV2, allocationObj.OwnerPublicKey)
if !valid || err != nil {
return nil, common.NewError("invalid_signature", "Invalid signature or invalid access")
}
Expand Down Expand Up @@ -731,7 +735,8 @@ func (fsh *StorageHandler) GetRefs(ctx context.Context, r *http.Request) (*blobb

clientSign, _ := ctx.Value(constants.ContextKeyClientSignatureHeaderKey).(string)

valid, err := verifySignatureFromRequest(allocationTx, clientSign, publicKey)
clientSignV2 := ctx.Value(constants.ContextKeyClientSignatureHeaderV2Key).(string)
valid, err := verifySignatureFromRequest(allocationTx, clientSign, clientSignV2, publicKey)
if !valid || err != nil {
return nil, common.NewError("invalid_signature", "Invalid signature")
}
Expand Down Expand Up @@ -896,14 +901,24 @@ func (fsh *StorageHandler) GetRefs(ctx context.Context, r *http.Request) (*blobb
}

// verifySignatureFromRequest verifies signature passed as common.ClientSignatureHeader header.
func verifySignatureFromRequest(alloc, sign, pbK string) (bool, error) {
sign = encryption.MiraclToHerumiSig(sign)

func verifySignatureFromRequest(alloc, signV1, signV2, pbK string) (bool, error) {
var (
sign string
hashData string
hash string
)
if signV2 != "" {
sign = encryption.MiraclToHerumiSig(signV2)
hashData = alloc + node.Self.GetURLBase()
hash = encryption.Hash(hashData)
} else {
sign = encryption.MiraclToHerumiSig(signV1)
hashData = alloc
hash = encryption.Hash(hashData)
}
if len(sign) < 64 {
return false, nil
}

hash := encryption.Hash(alloc)
return encryption.Verify(pbK, sign, hash)
}

Expand Down
Loading

0 comments on commit d1f396d

Please sign in to comment.