Skip to content

Commit

Permalink
feat: implementation of btip52 (#398)
Browse files Browse the repository at this point in the history
* feat: init btip52

* feat: impletation by go-btfs-api

* feat: p2p remote call

* fix: decryption to cat

* test: fix command test

* test: command test shows that tagline is required
  • Loading branch information
Shawn-Huang-Tron authored Dec 7, 2023
1 parent db951d7 commit 68295b1
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 6 deletions.
2 changes: 2 additions & 0 deletions core/commands/commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,8 @@ func TestCommands(t *testing.T) {
"/accesskey/get",
"/accesskey/list",
"/cheque/fix_cheque_cashout",
"/encrypt",
"/decrypt",
}

cmdSet := make(map[string]struct{})
Expand Down
162 changes: 162 additions & 0 deletions core/commands/encrypt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package commands

import (
"bytes"
"crypto/rand"
"errors"
"io"
"os"

shell "github.com/bittorrent/go-btfs-api"
cmds "github.com/bittorrent/go-btfs-cmds"
cp "github.com/bittorrent/go-btfs-common/crypto"
"github.com/bittorrent/go-btfs/core/commands/cmdenv"
"github.com/bittorrent/go-btfs/core/corehttp/remote"
ethCrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/ecies"
peer "github.com/libp2p/go-libp2p/core/peer"
)

const toOption = "to"
const fromOption = "from"

var encryptCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "encrypt file with the public key of the peer",
},
Arguments: []cmds.Argument{
cmds.FileArg("path", true, true, "The path to a file to be added to btfs.").EnableRecursive().EnableStdin(),
},
Options: []cmds.Option{
cmds.StringOption(toOption, "the peerID of the node which you want to share with"),
},
Run: func(r *cmds.Request, re cmds.ResponseEmitter, e cmds.Environment) error {
n, err := cmdenv.GetNode(e)
if err != nil {
return err
}
to, ok := r.Options[toOption].(string)
if !ok {
to = n.Identity.String()
}
id, err := peer.Decode(to)
if err != nil {
return errors.New("the to option must be a valid peerID")
}
p2pPk, err := id.ExtractPublicKey()
if err != nil {
return errors.New("can't extract public key from peerID")
}
pkBytes, err := cp.Secp256k1PublicKeyRaw(p2pPk)
if err != nil {
return errors.New("can't change from p2p public key to secp256k1 public key from peerID")
}

ethPk, err := ethCrypto.UnmarshalPubkey(pkBytes)
if err != nil {
return errors.New("can't unmarshall public key from peerID")
}

eciesPk := ecies.ImportECDSAPublic(ethPk)
it := r.Files.Entries()
file, err := cmdenv.GetFileArg(it)
if err != nil {
return err
}
originalBytes, err := io.ReadAll(file)
if err != nil {
return err
}
encryptedBytes, err := ECCEncrypt(originalBytes, *eciesPk)
if err != nil {
return err
}
btfsClient := shell.NewLocalShell()
cid, err := btfsClient.Add(bytes.NewReader(encryptedBytes), shell.Pin(true))
if err != nil {
return err
}
return re.Emit(cid)
},
}

var decryptCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "decrypt the content of a CID with the private key of this peer",
},
Arguments: []cmds.Argument{
cmds.StringArg("cid", true, false, "the CID of the encrypted file"),
},
Options: []cmds.Option{
cmds.StringOption(fromOption, "specify the source peerID of CID"),
},
Run: func(r *cmds.Request, re cmds.ResponseEmitter, e cmds.Environment) error {
conf, err := cmdenv.GetConfig(e)
if err != nil {
return err
}
n, err := cmdenv.GetNode(e)
if err != nil {
return err
}
api, err := cmdenv.GetApi(e, r)
if err != nil {
return err
}

var readClose io.ReadCloser
cid := r.Arguments[0]
from, ok := r.Options[fromOption].(string)
if ok {
peerID, err := peer.Decode(from)
if err != nil {
return err
}
b, err := remote.P2PCallStrings(r.Context, n, api, peerID, "/decryption", cid)
if err != nil {
return err
}
readClose = io.NopCloser(bytes.NewReader(b))
} else {
readClose, err = shell.NewLocalShell().Cat(cid)
if err != nil {
return err
}
}
ecdsaPrivateKey, err := ethCrypto.HexToECDSA(conf.Identity.HexPrivKey)
if err != nil {
return err
}
eciesPrivateKey := ecies.ImportECDSA(ecdsaPrivateKey)
endata, err := io.ReadAll(readClose)
if err != nil {
return err
}
defer readClose.Close()
dedata, err := ECCDecrypt(endata, *eciesPrivateKey)
if err != nil {
panic(err)
}
fileName := "./decrypt-file-of-" + cid
f, err := os.Create(fileName)
if err != nil {
return err
}
defer f.Close()
_, err = f.Write(dedata)
if err != nil {
return err
}
return re.Emit("decrypted file name is: " + fileName)
},
}

func ECCEncrypt(pt []byte, puk ecies.PublicKey) ([]byte, error) {
ct, err := ecies.Encrypt(rand.Reader, &puk, pt, nil, nil)
return ct, err
}

func ECCDecrypt(ct []byte, prk ecies.PrivateKey) ([]byte, error) {
pt, err := prk.Decrypt(ct, nil, nil)
return pt, err
}
15 changes: 9 additions & 6 deletions core/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ var rootSubcommands = map[string]*cmds.Command{
"backup": BackupCmd,
"recovery": RecoveryCmd,
"accesskey": AccessKeyCmd,
"encrypt": encryptCmd,
"decrypt": decryptCmd,
}

// RootRO is the readonly version of Root
Expand All @@ -199,7 +201,7 @@ var VersionROCmd = &cmds.Command{}
var rootROSubcommands = map[string]*cmds.Command{
"commands": CommandsDaemonROCmd,
"cat": CatCmd,
"block": &cmds.Command{
"block": {
Subcommands: map[string]*cmds.Command{
"stat": blockStatCmd,
"get": blockGetCmd,
Expand Down Expand Up @@ -235,33 +237,34 @@ var rootROSubcommands = map[string]*cmds.Command{
var RootRemote = &cmds.Command{}

var rootRemoteSubcommands = map[string]*cmds.Command{
"storage": &cmds.Command{
"storage": {
Subcommands: map[string]*cmds.Command{
"challenge": &cmds.Command{
"challenge": {
Subcommands: map[string]*cmds.Command{
"response": challenge.StorageChallengeResponseCmd,
},
},
"upload": &cmds.Command{
"upload": {
Subcommands: map[string]*cmds.Command{
"init": upload.StorageUploadInitCmd,
"supporttokens": upload.StorageUploadSupportTokensCmd,
"recvcontract": upload.StorageUploadRecvContractCmd,
"cheque": upload.StorageUploadChequeCmd,
},
},
"dcrepair": &cmds.Command{
"dcrepair": {
Subcommands: map[string]*cmds.Command{
"response": upload.HostRepairResponseCmd,
},
},
},
},
"p2p": &cmds.Command{
"p2p": {
Subcommands: map[string]*cmds.Command{
"handshake": P2phandshakeCmd,
},
},
"decryption": CatCmd,
}

func init() {
Expand Down

0 comments on commit 68295b1

Please sign in to comment.