Skip to content

Commit

Permalink
Merge pull request #1674 from 0chain/feat/encryption-key
Browse files Browse the repository at this point in the history
Use private signing key for encryption
  • Loading branch information
dabasov authored Nov 21, 2024
2 parents eed527d + 396230d commit 87fe666
Show file tree
Hide file tree
Showing 18 changed files with 242 additions and 64 deletions.
27 changes: 14 additions & 13 deletions wasmsdk/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,19 +203,20 @@ func main() {
if !(sdk.IsNull() || sdk.IsUndefined()) {
jsbridge.BindAsyncFuncs(sdk, map[string]interface{}{
//sdk
"init": initSDKs,
"setWallet": setWallet,
"setWalletMode": setWalletMode,
"getPublicEncryptionKey": zcncore.GetPublicEncryptionKey,
"hideLogs": hideLogs,
"showLogs": showLogs,
"getUSDRate": getUSDRate,
"isWalletID": isWalletID,
"getVersion": getVersion,
"getLookupHash": getLookupHash,
"createThumbnail": createThumbnail,
"makeSCRestAPICall": makeSCRestAPICall,
"wasmType": getWasmType,
"init": initSDKs,
"setWallet": setWallet,
"setWalletMode": setWalletMode,
"getPublicEncryptionKey": zcncore.GetPublicEncryptionKey,
"getPublicEncryptionKeyV2": zcncore.GetPublicEncryptionKeyV2,
"hideLogs": hideLogs,
"showLogs": showLogs,
"getUSDRate": getUSDRate,
"isWalletID": isWalletID,
"getVersion": getVersion,
"getLookupHash": getLookupHash,
"createThumbnail": createThumbnail,
"makeSCRestAPICall": makeSCRestAPICall,
"wasmType": getWasmType,

//blobber
"delete": Delete,
Expand Down
19 changes: 19 additions & 0 deletions winsdk/sdk.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,25 @@ func GetPublicEncryptionKey(mnemonics *C.char) *C.char {
return WithJSON(zcncore.GetPublicEncryptionKey(m))
}

// GetPublicEncryptionKeyV2 get public encryption key by public key
//
// return
// {
// "error":"",
// "result":"xxxx",
// }
//
//export GetPublicEncryptionKeyV2
func GetPublicEncryptionKeyV2(publicKey *C.char) *C.char {
defer func() {
if r := recover(); r != nil {
log.Error("win: crash ", r)
}
}()
pk := C.GoString(publicKey)
return WithJSON(zcncore.GetPublicEncryptionKeyV2(pk))
}

// GetLookupHash get lookup hash with allocation id and path
// ## Inputs:
// - allocationID
Expand Down
1 change: 1 addition & 0 deletions zboxcore/fileref/fileref.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ type FileRef struct {
EncryptedKeyPoint string `json:"encrypted_key_point" mapstructure:"encrypted_key_point"`
Collaborators []Collaborator `json:"collaborators" mapstructure:"collaborators"`
SignatureVersion int `json:"signature_version" mapstructure:"signature_version"`
EncryptionVersion int `json:"encryption_version" mapstructure:"encryption_version"`
}

func (fRef *FileRef) MetaID() string {
Expand Down
27 changes: 14 additions & 13 deletions zboxcore/marker/authticket.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,28 @@ package marker
import (
"fmt"

"github.com/0chain/gosdk/core/encryption"
"github.com/0chain/gosdk/core/client"
"github.com/0chain/gosdk/core/encryption"
)

// AuthTicket authentication ticket for file sharing.
// AuthTicket is used to provide access to a file or directory by non-owner clients.
// It's generated by the owner client and signed with their wallet's private key.
// Then shared with the non-owner client to be able to access the shared file or directory.
type AuthTicket struct {
ClientID string `json:"client_id"`
OwnerID string `json:"owner_id"`
AllocationID string `json:"allocation_id"`
FilePathHash string `json:"file_path_hash"`
ActualFileHash string `json:"actual_file_hash"`
FileName string `json:"file_name"`
RefType string `json:"reference_type"`
Expiration int64 `json:"expiration"`
Timestamp int64 `json:"timestamp"`
ReEncryptionKey string `json:"re_encryption_key,omitempty"`
Encrypted bool `json:"encrypted"`
Signature string `json:"signature"`
ClientID string `json:"client_id"`
OwnerID string `json:"owner_id"`
AllocationID string `json:"allocation_id"`
FilePathHash string `json:"file_path_hash"`
ActualFileHash string `json:"actual_file_hash"`
FileName string `json:"file_name"`
RefType string `json:"reference_type"`
Expiration int64 `json:"expiration"`
Timestamp int64 `json:"timestamp"`
ReEncryptionKey string `json:"re_encryption_key,omitempty"`
Encrypted bool `json:"encrypted"`
Signature string `json:"signature"`
EncryptionPublicKey string `json:"encryption_public_key"`
}

// NewAuthTicket returns the MPT hash of the AuthTicket
Expand Down
19 changes: 18 additions & 1 deletion zboxcore/sdk/allocation.go
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,7 @@ func (a *Allocation) RepairFile(file sys.File, remotepath string, statusCallback
WithStatusCallback(statusCallback),
WithEncryptedPoint(ref.EncryptedKeyPoint),
WithChunkNumber(RepairBlocks),
WithEncryptionVersion(ref.EncryptionVersion),
}
} else {
opts = []ChunkedUploadOption{
Expand Down Expand Up @@ -1367,14 +1368,23 @@ func (a *Allocation) generateDownloadRequest(
return nil, noBLOBBERS
}

downloadReq := &DownloadRequest{Consensus: Consensus{RWMutex: &sync.RWMutex{}}}
downloadReq := &DownloadRequest{Consensus: Consensus{RWMutex: &sync.RWMutex{}}, storageVersion: a.StorageVersion}
downloadReq.maskMu = &sync.Mutex{}
downloadReq.allocationID = a.ID
downloadReq.allocationTx = a.Tx
downloadReq.allocOwnerID = a.Owner
downloadReq.sig = a.sig
downloadReq.allocOwnerPubKey = a.OwnerPublicKey
downloadReq.allocOwnerSigningPubKey = a.OwnerSigningPublicKey
if len(a.privateSigningKey) == 0 {
sk, err := generateOwnerSigningKey(client.PublicKey(), client.Id())
if err != nil {
return nil, err
}
downloadReq.allocOwnerSigningPrivateKey = sk
} else {
downloadReq.allocOwnerSigningPrivateKey = a.privateSigningKey
}
downloadReq.ctx, downloadReq.ctxCncl = context.WithCancel(a.ctx)
downloadReq.fileHandler = fileHandler
downloadReq.localFilePath = localFilePath
Expand Down Expand Up @@ -2341,6 +2351,7 @@ func (a *Allocation) GetAuthTicket(path, filename string,
ctx: a.ctx,
remotefilepath: path,
remotefilename: filename,
signingPrivateKey: a.privateSigningKey,
}

if referenceType == fileref.DIRECTORY {
Expand Down Expand Up @@ -2809,6 +2820,12 @@ func (a *Allocation) downloadFromAuthTicket(fileHandler sys.File, authTicket str
downloadReq.allocOwnerID = a.Owner
downloadReq.allocOwnerPubKey = a.OwnerPublicKey
downloadReq.allocOwnerSigningPubKey = a.OwnerSigningPublicKey
//for auth ticket set your own signing key
sk, err := generateOwnerSigningKey(client.PublicKey(), client.Id())
if err != nil {
return err
}
downloadReq.allocOwnerSigningPrivateKey = sk
downloadReq.ctx, downloadReq.ctxCncl = context.WithCancel(a.ctx)
downloadReq.fileHandler = fileHandler
downloadReq.localFilePath = localFilePath
Expand Down
5 changes: 4 additions & 1 deletion zboxcore/sdk/allocation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"context"
"encoding/hex"
"encoding/json"
"github.com/0chain/gosdk/zboxcore/mocks"
"io"
"io/fs"
"log"
Expand All @@ -17,6 +16,8 @@ import (
"testing"
"time"

"github.com/0chain/gosdk/zboxcore/mocks"

"github.com/0chain/gosdk/dev/blobber"
"github.com/0chain/gosdk/dev/blobber/model"
"github.com/0chain/gosdk/zboxcore/encryption"
Expand Down Expand Up @@ -47,6 +48,7 @@ const (
mockLookupHash = "mock lookup hash"
mockAllocationRoot = "mock allocation root"
mockFileRefName = "mock file ref name"
mockMnemonic = "mock mnemonic"
numBlobbers = 4
)

Expand Down Expand Up @@ -1386,6 +1388,7 @@ func TestAllocation_GetAuthTicket(t *testing.T) {
client.SetWallet(zcncrypto.Wallet{
ClientID: mockClientId,
ClientKey: mockClientKey,
Mnemonic: mockMnemonic,
})

require := require.New(t)
Expand Down
33 changes: 24 additions & 9 deletions zboxcore/sdk/chunked_upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,11 +172,12 @@ func CreateChunkedUpload(
encryptOnUpload: false,
webStreaming: false,

consensus: consensus, //nolint
uploadTimeOut: DefaultUploadTimeOut,
commitTimeOut: DefaultUploadTimeOut,
maskMu: &sync.Mutex{},
opCode: opCode,
consensus: consensus, //nolint
uploadTimeOut: DefaultUploadTimeOut,
commitTimeOut: DefaultUploadTimeOut,
maskMu: &sync.Mutex{},
opCode: opCode,
encryptionVersion: -1,
}

// su.ctx, su.ctxCncl = context.WithCancel(allocationObj.ctx)
Expand Down Expand Up @@ -292,7 +293,7 @@ func CreateChunkedUpload(

su.chunkReader = cReader

su.formBuilder = CreateChunkedUploadFormBuilder(su.allocationObj.StorageVersion, su.allocationObj.privateSigningKey)
su.formBuilder = CreateChunkedUploadFormBuilder(su.allocationObj.StorageVersion, su.encryptionVersion, su.allocationObj.privateSigningKey)

su.isRepair = isRepair
uploadWorker, uploadRequest := calculateWorkersAndRequests(su.allocationObj.DataShards, len(su.blobbers), su.chunkNumber)
Expand Down Expand Up @@ -383,11 +384,25 @@ func (su *ChunkedUpload) createEncscheme() encryption.EncryptionScheme {
return nil
}
} else {
mnemonic := client.Mnemonic()
if mnemonic == "" {
var entropy string
switch su.encryptionVersion {
case -1:
if len(su.allocationObj.privateSigningKey) == 0 {
entropy = client.Mnemonic()
su.encryptionVersion = 0
} else {
entropy = hex.EncodeToString(su.allocationObj.privateSigningKey)
su.encryptionVersion = 1
}
case 0:
entropy = client.Mnemonic()
case 1:
entropy = hex.EncodeToString(su.allocationObj.privateSigningKey)
}
if entropy == "" {
return nil
}
privateKey, err := encscheme.Initialize(mnemonic)
privateKey, err := encscheme.Initialize(entropy)
if err != nil {
return nil
}
Expand Down
5 changes: 4 additions & 1 deletion zboxcore/sdk/chunked_upload_form_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,17 @@ type ChunkedUploadFormMetadata struct {
}

// CreateChunkedUploadFormBuilder create ChunkedUploadFormBuilder instance
func CreateChunkedUploadFormBuilder(storageVersion int, privateSigningKey ed25519.PrivateKey) ChunkedUploadFormBuilder {
func CreateChunkedUploadFormBuilder(storageVersion, encryptionVersion int, privateSigningKey ed25519.PrivateKey) ChunkedUploadFormBuilder {
return &chunkedUploadFormBuilder{
storageVersion,
encryptionVersion,
privateSigningKey,
}
}

type chunkedUploadFormBuilder struct {
storageVersion int
encryptionVersion int
privateSigningKey ed25519.PrivateKey
}

Expand Down Expand Up @@ -98,6 +100,7 @@ func (b *chunkedUploadFormBuilder) Build(
EncryptedKeyPoint: encryptedKeyPoint,
EncryptedKey: encryptedKey,
CustomMeta: fileMeta.CustomMeta,
EncryptionVersion: b.encryptionVersion,
}

if b.privateSigningKey != nil {
Expand Down
2 changes: 1 addition & 1 deletion zboxcore/sdk/chunked_upload_form_builder_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func BenchmarkChunkedUploadFormBuilder(b *testing.B) {

for i := 0; i < b.N; i++ {

builder := CreateChunkedUploadFormBuilder(0, nil)
builder := CreateChunkedUploadFormBuilder(0, 0, nil)

isFinal := false

Expand Down
18 changes: 10 additions & 8 deletions zboxcore/sdk/chunked_upload_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ type ChunkedUpload struct {
// shardUploadedThumbnailSize how much thumbnail bytes a shard has. it is original size
shardUploadedThumbnailSize int64
// size of shard
shardSize int64
shardSize int64
encryptionVersion int

// statusCallback trigger progress on StatusCallback
statusCallback StatusCallback
Expand Down Expand Up @@ -166,13 +167,14 @@ type UploadFormData struct {
EncryptedKey string `json:"encrypted_key,omitempty"`
EncryptedKeyPoint string `json:"encrypted_key_point,omitempty"`

IsFinal bool `json:"is_final,omitempty"` // all of chunks are uploaded
ChunkStartIndex int `json:"chunk_start_index,omitempty"` // start index of chunks.
ChunkEndIndex int `json:"chunk_end_index,omitempty"` // end index of chunks. all chunks MUST be uploaded one by one because of streaming merkle hash
ChunkSize int64 `json:"chunk_size,omitempty"` // the size of a chunk. 64*1024 is default
UploadOffset int64 `json:"upload_offset,omitempty"` // It is next position that new incoming chunk should be append to
Size int64 `json:"size"` // total size of shard
SignatureVersion int `json:"signature_version,omitempty"`
IsFinal bool `json:"is_final,omitempty"` // all of chunks are uploaded
ChunkStartIndex int `json:"chunk_start_index,omitempty"` // start index of chunks.
ChunkEndIndex int `json:"chunk_end_index,omitempty"` // end index of chunks. all chunks MUST be uploaded one by one because of streaming merkle hash
ChunkSize int64 `json:"chunk_size,omitempty"` // the size of a chunk. 64*1024 is default
UploadOffset int64 `json:"upload_offset,omitempty"` // It is next position that new incoming chunk should be append to
Size int64 `json:"size"` // total size of shard
SignatureVersion int `json:"signature_version,omitempty"`
EncryptionVersion int `json:"encryption_version,omitempty"`
}

// UploadProgress progress of upload
Expand Down
16 changes: 11 additions & 5 deletions zboxcore/sdk/chunked_upload_option.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"github.com/klauspost/reedsolomon"
)

// ChunkedUploadOption Generic type for chunked upload option functions
// ChunkedUploadOption Generic type for chunked upload option functions
type ChunkedUploadOption func(su *ChunkedUpload)

// WithThumbnail add thumbnail. stream mode is unnecessary for thumbnail
Expand All @@ -38,7 +38,7 @@ func WithThumbnail(buf []byte) ChunkedUploadOption {
}

// WithThumbnailFile add thumbnail from file. stream mode is unnecessary for thumbnail.
// - fileName: file name of the thumbnail, which will be read and uploaded
// - fileName: file name of the thumbnail, which will be read and uploaded
func WithThumbnailFile(fileName string) ChunkedUploadOption {

buf, _ := os.ReadFile(fileName)
Expand All @@ -47,7 +47,7 @@ func WithThumbnailFile(fileName string) ChunkedUploadOption {
}

// WithChunkNumber set the number of chunks should be upload in a request. ignore if size <=0
// - num: number of chunks
// - num: number of chunks
func WithChunkNumber(num int) ChunkedUploadOption {
return func(su *ChunkedUpload) {
if num > 0 {
Expand All @@ -57,15 +57,15 @@ func WithChunkNumber(num int) ChunkedUploadOption {
}

// WithEncrypt turn on/off encrypt on upload. It is turn off as default.
// - on: true to turn on, false to turn off
// - on: true to turn on, false to turn off
func WithEncrypt(on bool) ChunkedUploadOption {
return func(su *ChunkedUpload) {
su.encryptOnUpload = on
}
}

// WithStatusCallback return a wrapper option function to set status callback of the chunked upload instance, which is used to track upload progress
// - callback: StatusCallback instance
// - callback: StatusCallback instance
func WithStatusCallback(callback StatusCallback) ChunkedUploadOption {
return func(su *ChunkedUpload) {
su.statusCallback = callback
Expand Down Expand Up @@ -120,3 +120,9 @@ func WithFileHasher(h Hasher) ChunkedUploadOption {
su.fileHasher = h
}
}

func WithEncryptionVersion(version int) ChunkedUploadOption {
return func(su *ChunkedUpload) {
su.encryptionVersion = version
}
}
Loading

0 comments on commit 87fe666

Please sign in to comment.