Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 83 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,83 @@
# filecoin-encrypted-data-storage
Encrypted Data Storage CLI for Filecoin
# Encloud

Encloud is a toolkit for making sensitive data useful for Web3. The Encloud CLI enables clients to easily on-board
sensitive data to the Filecoin network.

Encloud CLI is a lightweight utility that allows clients to

- Generate their RSA encryption keys
- Manage file and encryption metadata in a local or remote KV store
- Upload encrypted files to Filecoin
- Retrieve encrypted files from Filecoin and decrypt them
- Share encrypted files by transferring the DEK to a specified email

Encloud currently uses the [Estuary](https://estuary.tech/) API to upload and retrieve data from Filecoin. This allows clients to interact with the
Filecoin network without needing to deal with crypto wallets, tokens or deal making with Filecoin storage providers as
Estuary manages this in the background.

We plan to add more flows to enable clients to control their deal making with specific Storage Providers.
To this end we want to integrate with Singularity and its deal preparation module to generate encrypted CAR files and make deals
with specific storage providers.

## Prerequisites
- Golang 1.18 or higher

## CLI Setup

```bash
# go module sync
go mod tidy

# enable encloud cli command
go install .
```
## Configuration
The default required configuration are in **config.yaml** file under the project root. You can modify any property set in the config file as per your requirements.

## Command reference
1) Generate RSA 2048 key pair (key encryption key or KEK) to encrypt & decrypt the AES-256 keys (data encryption key or DEK). Run below command from the root of the project to the RSA key pair
> encloud generate-key-pair

2) Upload encrypted data to Filecoin. This command encrypts the specified file using a newly generated DEK. The DEK is encrypted using the KEK and the metadata is stored on the local KV store.

> encloud upload -p `<KEK_PUBLIC_KEY>` -f `<UPLOAD_FILE_PATH>`

Read the KEK public key from a file path instead of raw text.

> encloud upload -p `<KEK_PUBLIC_KEY_FILE_PATH>` -f `<UPLOAD_FILE_PATH>` -r true
3) List uploaded files and associated metadata. Metadata is used to query and retrieve the files from Filecoin.

> encloud list -p `<KEK_PUBLIC_KEY>`

Read the KEK public key from a file path instead of raw text.

> encloud list -p `<KEK_PUBLIC_KEY_FILE_PATH>` -r true
4) Retrieve data from Filecoin with a specific CID. This command decrypts encrypted data on Filecoin using the relevant DEK. The DEK is stored in encrypted form in the metadata and is itself decrypted first using the KEK Private Key.

> encloud retrieve-by-cid -p `<KEK_PUBLIC_KEY>` -k `<KEK_PRIVATE_KEY>` -u `<UUID>`

Read the KEK public and private keys from a file path instead of raw text. For KEK public key pass `r` flag with `true` and for private key pass `o` flag with `true`

> encloud retrieve-by-cid -p `<KEK_PUBLIC_KEY_FILE_PATH>` -k `<KEK_PRIVATE_KEY_PATH>` -u `<UUID>` -r true -o true

1) Share your files with other users using the CID and DEK.

> encloud share -e `<EMAIL>` -p `<KEK_PUBLIC_KEY>` -k `<KEK_PRIVATE_KEY>` -u `<UUID>`

Read the KEK public and private keys from a file path instead of raw text. For KEK public key pass `r` flag with `true` and for private key pass `o` flag with `true`

> encloud share -e `<EMAIL>` -p `<KEK_PUBLIC_KEY_PATH>` -k `<KEK_PRIVATE_KEY_PATH>` -u `<UUID>` -r true -o true

2) Retrieve shared content from other users using your CID and DEK.

> encloud retrieve-shared-content -c `<RECEIVED_CID_OF_YOUR_EMAIL>` -d `<RECEIVED_DEK_FILE_PATH>`


## Future features
- Distributed key management for KEKs
- Encryption and chunking for performant file uploads
- Integration with Singularity's Deal Preparation Framework to generate encrypted CAR files
- UI for clients and storage providers

## License
[AGPL3.0](https://github.com/encloud-tech/encloud/blob/main/LICENSE)
65 changes: 0 additions & 65 deletions cmd/cmd_test.go

This file was deleted.

6 changes: 3 additions & 3 deletions cmd/generate_key_pair.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package cmd

import (
thirdparty "encloud/third_party"
"encloud/types"
"encoding/json"
thirdparty "filecoin-encrypted-data-storage/third_party"
"filecoin-encrypted-data-storage/types"
"fmt"
"net/http"
"os"
Expand All @@ -26,7 +26,7 @@ func GenerateKeyPairCmd() *cobra.Command {
}
os.Remove(".keys/.idRsaPub")
os.Remove(".keys/.idRsa")
encoded, err := json.Marshal(response)
encoded, err := json.MarshalIndent(response, "", " ")
if err != nil {
fmt.Println(err)
return
Expand Down
17 changes: 13 additions & 4 deletions cmd/list.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package cmd

import (
"encloud/service"
thirdparty "encloud/third_party"
"encloud/types"
"encoding/json"
"filecoin-encrypted-data-storage/service"
"filecoin-encrypted-data-storage/types"
"fmt"
"net/http"
"os"
Expand All @@ -17,7 +18,14 @@ func ListContentsCmd() *cobra.Command {
Short: "List your uploaded contents",
Long: `List your uploaded contents data which contains file meta informations`,
Run: func(cmd *cobra.Command, args []string) {
kek, _ := cmd.Flags().GetString("publicKey")
kek := ""
publicKey, _ := cmd.Flags().GetString("publicKey")
readPublicKeyFromPath, _ := cmd.Flags().GetBool("readPublicKeyFromPath")
if readPublicKeyFromPath {
kek = thirdparty.ReadKeyFile(publicKey)
} else {
kek = publicKey
}
fileMetaData := service.Fetch(kek)
os.Remove("assets/downloaded.bin")
response := types.ListContentResponse{
Expand All @@ -26,7 +34,7 @@ func ListContentsCmd() *cobra.Command {
Message: "Content fetched successfully.",
Data: fileMetaData,
}
encoded, err := json.Marshal(response)
encoded, err := json.MarshalIndent(response, "", " ")
if err != nil {
fmt.Println(err)
return
Expand All @@ -36,6 +44,7 @@ func ListContentsCmd() *cobra.Command {
}

cmd.Flags().StringP("publicKey", "p", "", "Enter your public key")
cmd.Flags().BoolP("readPublicKeyFromPath", "r", false, "Do you want public key read from path you have entered?")
cmd.MarkFlagRequired("publicKey")
return cmd
}
Expand Down
43 changes: 31 additions & 12 deletions cmd/retrieve_by_cid.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package cmd

import (
"encloud/config"
"encloud/service"
thirdparty "encloud/third_party"
"encloud/types"
"encoding/json"
"filecoin-encrypted-data-storage/config"
"filecoin-encrypted-data-storage/service"
thirdparty "filecoin-encrypted-data-storage/third_party"
"filecoin-encrypted-data-storage/types"
"fmt"
"net/http"
"os"
Expand All @@ -22,15 +22,32 @@ func RetrieveByCidCmd() *cobra.Command {
cfg, _ := config.LoadConf("./config.yml")
estuaryService := service.New(cfg)

kek, _ := cmd.Flags().GetString("publicKey")
privateKey, _ := cmd.Flags().GetString("privateKey")
cid, _ := cmd.Flags().GetString("cid")
fileMetaData := service.FetchByCid(kek + "-" + cid)
kek := ""
privateKey := ""
publicKey, _ := cmd.Flags().GetString("publicKey")
pk, _ := cmd.Flags().GetString("privateKey")
uuid, _ := cmd.Flags().GetString("uuid")
readPublicKeyFromPath, _ := cmd.Flags().GetBool("readPublicKeyFromPath")
readPrivateKeyFromPath, _ := cmd.Flags().GetBool("readPrivateKeyFromPath")
if readPublicKeyFromPath {
kek = thirdparty.ReadKeyFile(publicKey)
} else {
kek = publicKey
}

if readPrivateKeyFromPath {
privateKey = thirdparty.ReadKeyFile(pk)
} else {
privateKey = pk
}

fileMetaData := service.FetchByCid(kek + ":" + uuid)
decryptedDek, err := thirdparty.DecryptWithRSA(fileMetaData.Dek, thirdparty.GetIdRsaFromStr(privateKey))
if err != nil {
fmt.Println(err)
}
filepath := estuaryService.DownloadContent(fileMetaData.Cid)

filepath := estuaryService.DownloadContent(fileMetaData.Cid[0])
err = thirdparty.DecryptFile(decryptedDek, filepath)
if err != nil {
fmt.Println(err)
Expand All @@ -42,7 +59,7 @@ func RetrieveByCidCmd() *cobra.Command {
Message: "Content fetched successfully.",
Data: fileMetaData,
}
encoded, err := json.Marshal(response)
encoded, err := json.MarshalIndent(response, "", " ")
if err != nil {
fmt.Println(err)
return
Expand All @@ -53,10 +70,12 @@ func RetrieveByCidCmd() *cobra.Command {

cmd.Flags().StringP("publicKey", "p", "", "Enter your public key")
cmd.Flags().StringP("privateKey", "k", "", "Enter your private key")
cmd.Flags().StringP("cid", "c", "", "Enter your cid")
cmd.Flags().StringP("uuid", "u", "", "Enter your uuid")
cmd.Flags().BoolP("readPublicKeyFromPath", "r", false, "Do you want public key read from path you have entered?")
cmd.Flags().BoolP("readPrivateKeyFromPath", "o", false, "Do you want private key read from path you have entered?")
cmd.MarkFlagRequired("publicKey")
cmd.MarkFlagRequired("privateKey")
cmd.MarkFlagRequired("cid")
cmd.MarkFlagRequired("uuid")
return cmd
}

Expand Down
46 changes: 46 additions & 0 deletions cmd/retrieve_shared_content.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package cmd

import (
"encloud/config"
"encloud/service"
thirdparty "encloud/third_party"
"fmt"
"os"

"github.com/spf13/cobra"
)

func RetrieveSharedContentCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "retrieve-shared-content",
Short: "Retrieve specific uploaded content using your cid",
Long: `Retrieve specific uploaded content using your cid and decrypt it using your private key`,
Run: func(cmd *cobra.Command, args []string) {
cfg, _ := config.LoadConf("./config.yml")
estuaryService := service.New(cfg)

decryptedDekPath, _ := cmd.Flags().GetString("dek")
cid, _ := cmd.Flags().GetString("cid")

dek := thirdparty.ReadFile(decryptedDekPath)

filepath := estuaryService.DownloadContent(cid)
err := thirdparty.DecryptFile(dek, filepath)
if err != nil {
fmt.Println(err)
}
os.Remove("assets/downloaded.bin")
fmt.Fprintf(cmd.OutOrStdout(), string("content downloaded successfully."))
},
}

cmd.Flags().StringP("dek", "d", "", "Enter your dek path")
cmd.Flags().StringP("cid", "c", "", "Enter your cid")
cmd.MarkFlagRequired("dek")
cmd.MarkFlagRequired("cid")
return cmd
}

func init() {
RootCmd.AddCommand(RetrieveSharedContentCmd())
}
14 changes: 7 additions & 7 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ var cfgFile string

// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
Use: "gupt",
Short: "gupt is encrypted data storage tool.",
Long: `gupt is upload and download data on filecoin
network using estuary api.
It also encrypt and decrypt data
using rsa algorithm`,
Use: "encloud",
Short: "encloud is a CLI tool for on-boarding sensitive data to Filecoin.",
Long: `encloud is a CLI tool that enables upload and retrieval of sensitive data from the Filecoin
network. It helps in key generation and management, file encryption and key mapping and upload and retrieval of data from the Filecoin network`,
// Uncomment the following line if your bare application
// has an action associated with it:
Run: func(cmd *cobra.Command, args []string) { fmt.Println("Welcome to our CLI!") },
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(`Encloud is a CLI tool for on-boarding sensitive data to Filecoin.`)
},
}

// Execute adds all child commands to the root command and sets flags appropriately.
Expand Down
Loading