Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release finding #585

Merged
merged 9 commits into from
Feb 2, 2023
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
33 changes: 23 additions & 10 deletions proto/shentu/bounty/v1/bounty.proto
Original file line number Diff line number Diff line change
Expand Up @@ -41,29 +41,42 @@ message Finding {

uint64 finding_id = 1 [(gogoproto.jsontag) = "id", (gogoproto.moretags) = "yaml:\"id\""];
string title = 2 [(gogoproto.moretags) = "yaml:\"title\""];
google.protobuf.Any encrypted_desc = 3 [(cosmos_proto.accepts_interface) = "EncryptedDesc",(gogoproto.moretags) = "yaml:\"encrypted_desc\""];
google.protobuf.Any finding_desc = 3 [(cosmos_proto.accepts_interface) = "FindingDesc",(gogoproto.moretags) = "yaml:\"finding_desc\""];
uint64 program_id = 4 [(gogoproto.moretags) = "yaml:\"program_id\""];
SeverityLevel severity_level = 5 [(gogoproto.moretags) = "yaml:\"severity_level\""];;
google.protobuf.Any encrypted_poc = 6 [(cosmos_proto.accepts_interface) = "EncryptedPoc",(gogoproto.moretags) = "yaml:\"encrypted_poc\""];
google.protobuf.Any finding_poc = 6 [(cosmos_proto.accepts_interface) = "FindingPoc",(gogoproto.moretags) = "yaml:\"finding_poc\""];
string submitter_address = 7 [(gogoproto.moretags) = "yaml:\"submitter_address\""];
FindingStatus finding_status = 8 [(gogoproto.moretags) = "yaml:\"finding_status\""];

google.protobuf.Any encrypted_comment = 9 [(cosmos_proto.accepts_interface) = "EncryptedComment",(gogoproto.moretags) = "yaml:\"encrypted_comment\""];
google.protobuf.Any finding_comment = 9 [(cosmos_proto.accepts_interface) = "FindingComment",(gogoproto.moretags) = "yaml:\"finding_comment\""];
}

message EciesEncryptedDesc {
option (cosmos_proto.implements_interface) = "EncryptedDesc";
bytes encrypted_desc = 1;
option (cosmos_proto.implements_interface) = "FindingDesc";
bytes finding_desc = 1;
}

message EciesEncryptedPoc {
option (cosmos_proto.implements_interface) = "EncryptionPoc";
bytes encrypted_poc = 1;
option (cosmos_proto.implements_interface) = "FindingPoc";
bytes finding_poc = 1;
}

message EciesEncryptedComment {
option (cosmos_proto.implements_interface) = "EncryptionComment";
bytes encrypted_comment = 1;
option (cosmos_proto.implements_interface) = "FindingComment";
bytes finding_comment = 1;
}
message PlainTextDesc {
option (cosmos_proto.implements_interface) = "FindingDesc";
bytes finding_desc = 1;
}

message PlainTextPoc {
option (cosmos_proto.implements_interface) = "FindingPoc";
bytes finding_poc = 1;
}

message PlainTextComment {
option (cosmos_proto.implements_interface) = "FindingComment";
bytes finding_comment = 1;
}

enum SeverityLevel {
Expand Down
22 changes: 21 additions & 1 deletion proto/shentu/bounty/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ service Msg {

// HostRejectFinding defines a method for host reject a finding.
rpc HostRejectFinding(MsgHostRejectFinding) returns (MsgHostRejectFindingResponse);

// MsgReleaseFinding defines a method for release a finding.
rpc ReleaseFinding(MsgReleaseFinding) returns (MsgReleaseFindingResponse);
}

// MsgCreateProgram defines a SDK message for creating a new program.
Expand All @@ -48,6 +51,8 @@ message MsgCreateProgram {
message MsgCreateProgramResponse {
uint64 program_id = 1 [(gogoproto.jsontag) = "id", (gogoproto.moretags) = "yaml:\"id\""];
}

// MsgSubmitFinding defines a message to submit a finding.
message MsgSubmitFinding {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
Expand All @@ -60,6 +65,7 @@ message MsgSubmitFinding {
string submitter_address = 6 [(gogoproto.moretags) = "yaml:\"submitter_address\""];
}

// MsgSubmitFindingResponse defines the MsgSubmitFinding response type.
message MsgSubmitFindingResponse {
option (gogoproto.goproto_getters) = false;
uint64 finding_id = 1 [(gogoproto.jsontag) = "finding_id", (gogoproto.moretags) = "yaml:\"finding_id\""];
Expand Down Expand Up @@ -89,4 +95,18 @@ message MsgHostRejectFinding {
}

// MsgHostRejectFindingResponse defines the Msg/ostRejectFinding response type.
message MsgHostRejectFindingResponse {}
message MsgHostRejectFindingResponse {}

// MsgReleaseFinding defines a message to release a finding.
message MsgReleaseFinding {
option (gogoproto.equal) = false;

uint64 finding_id = 1 [(gogoproto.moretags) = "yaml:\"finding_id\""];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might also need release all or some findings of a given program.

string desc = 2 [(gogoproto.moretags) = "yaml:\"desc\""];
string poc = 3 [(gogoproto.moretags) = "yaml:\"poc\""];
string comment = 4 [(gogoproto.moretags) = "yaml:\"comment\""];
string host_address = 5 [(gogoproto.moretags) = "yaml:\"host_address\""];
}

// MsgReleaseFindingResponse defines the MsgReleaseFinding response type.
message MsgReleaseFindingResponse {}
1 change: 1 addition & 0 deletions x/bounty/client/cli/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ const (

FlagFindingAddress = "finding-address"
FlagSubmitterAddress = "submitter-address"
FlagFindingID = "finding-id"
)
102 changes: 98 additions & 4 deletions x/bounty/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func NewTxCmd() *cobra.Command {
NewSubmitFindingCmd(),
NewHostAcceptFindingCmd(),
NewHostRejectFindingCmd(),
NewReleaseFindingCmd(),
)

return bountyTxCmds
Expand Down Expand Up @@ -166,7 +167,6 @@ func NewSubmitFindingCmd() *cobra.Command {

poc, _ := cmd.Flags().GetString(FlagFindingPoc)

//func EncryptMsg(cmd *cobra.Command, programID uint64, desc, poc string) (descAny, pocAny *codectypes.Any, err error) {
descAny, pocAny, err := EncryptMsg(cmd, pid, desc, poc)
if err != nil {
return err
Expand Down Expand Up @@ -208,7 +208,7 @@ func EncryptMsg(cmd *cobra.Command, programID uint64, desc, poc string) (descAny
return nil, nil, err
}
encDesc := types.EciesEncryptedDesc{
EncryptedDesc: encryptedDescBytes,
FindingDesc: encryptedDescBytes,
}
descAny, err = codectypes.NewAnyWithValue(&encDesc)
if err != nil {
Expand All @@ -220,7 +220,7 @@ func EncryptMsg(cmd *cobra.Command, programID uint64, desc, poc string) (descAny
return nil, nil, err
}
encPoc := types.EciesEncryptedPoc{
EncryptedPoc: encryptedPocBytes,
FindingPoc: encryptedPocBytes,
}
pocAny, err = codectypes.NewAnyWithValue(&encPoc)
if err != nil {
Expand Down Expand Up @@ -350,7 +350,7 @@ func HostProcessFinding(cmd *cobra.Command, args []string) (fid uint64,
return fid, commentAny, hostAddr, err
}
encComment := types.EciesEncryptedComment{
EncryptedComment: encryptedComment,
FindingComment: encryptedComment,
}
commentAny, err = codectypes.NewAnyWithValue(&encComment)
if err != nil {
Expand All @@ -359,3 +359,97 @@ func HostProcessFinding(cmd *cobra.Command, args []string) (fid uint64,

return fid, commentAny, hostAddr, nil
}

func NewReleaseFindingCmd() *cobra.Command {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was deprecated in favor of providing the decrypted plaintext for each finding to be verified by encrypting it again and matching it with the on-chain encrypted ciphertext

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so you'd only be able to release findings one by one

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make sense

cmd := &cobra.Command{
Use: "release-finding",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use release-finding 1 instead of release-finding --finding-id 1 , it may be more user-friendly

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all commands should use the same command format

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, there are currently 2 formats, and should be unified.

Short: "release encrypted part of a finding ",
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
hostAddr := clientCtx.GetFromAddress()

fid, err := cmd.Flags().GetUint64(FlagFindingID)
if err != nil {
return err
}

encKeyFile, err := cmd.Flags().GetString(FlagEncKeyFile)
if err != nil {
return err
}

findingDesc, findingPoc, findingComment, err := GetFindingPlainText(cmd, fid, encKeyFile)
if err != nil {
return err
}

msg := types.NewReleaseFinding(
hostAddr.String(),
fid,
findingDesc,
findingPoc,
findingComment,
)

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

cmd.Flags().String(FlagEncKeyFile, "", "The program's encryption key file to decrypt findings")
cmd.Flags().Uint64(FlagFindingID, 0, "The program's ID")
flags.AddTxFlagsToCmd(cmd)

_ = cmd.MarkFlagRequired(flags.FlagFrom)
_ = cmd.MarkFlagRequired(FlagFindingID)
_ = cmd.MarkFlagRequired(FlagEncKeyFile)

return cmd
}

func GetFindingPlainText(cmd *cobra.Command, fid uint64, encKeyFile string) (
desc, poc, comment string, err error) {
// get finding info
finding, err := GetFinding(cmd, fid)
if err != nil {
return "", "", "", err
}

prvKey := LoadPrvKey(encKeyFile)

if finding.FindingDesc == nil {
desc = ""
} else {
encryptedDescBytes := finding.FindingDesc.GetValue()
descBytes, err := prvKey.Decrypt(encryptedDescBytes[2:], nil, nil)
if err != nil {
return "", "", "", err
}
desc = string(descBytes)
}

if finding.FindingPoc == nil {
poc = ""
} else {
encryptedPocBytes := finding.FindingPoc.GetValue()
pocBytes, err := prvKey.Decrypt(encryptedPocBytes[2:], nil, nil)
if err != nil {
return "", "", "", err
}
poc = string(pocBytes)
}

if finding.FindingComment == nil {
comment = ""
} else {
encryptedCommentBytes := finding.FindingComment.GetValue()
commentBytes, err := prvKey.Decrypt(encryptedCommentBytes[2:], nil, nil)
if err != nil {
return "", "", "", err
}
comment = string(commentBytes)
}
return desc, poc, comment, nil
}
31 changes: 31 additions & 0 deletions x/bounty/client/cli/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,43 @@ import (

"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/ecies"

codectypes "github.com/cosmos/cosmos-sdk/codec/types"

"github.com/shentufoundation/shentu/v2/x/bounty/types"
)

const (
keyFile = "./dec-key.json"
)

func TestAnyToBytes(t *testing.T) {
decKey, err := ecies.GenerateKey(rand.Reader, ecies.DefaultCurve, nil)
if err != nil {
t.Fatal(err.Error())
}
desc := "test"
encryptedDesc, err := ecies.Encrypt(rand.Reader, &decKey.PublicKey, []byte(desc), nil, nil)
if err != nil {
t.Fatal(err)
}

var descAny *codectypes.Any
encDesc := types.EciesEncryptedDesc{
FindingDesc: encryptedDesc,
}
if descAny, err = codectypes.NewAnyWithValue(&encDesc); err != nil {
t.Fatal(err)
}

descBytes := descAny.GetValue()[2:]
descDecrypt, err := decKey.Decrypt(descBytes, nil, nil)

if string(descDecrypt) != desc {
t.Fatal("error")
}
}

func TestSaveLoadKey(t *testing.T) {
decKey, err := ecies.GenerateKey(rand.Reader, ecies.DefaultCurve, nil)
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions x/bounty/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
case *types.MsgHostRejectFinding:
res, err := msgServer.HostRejectFinding(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *types.MsgReleaseFinding:
res, err := msgServer.ReleaseFinding(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
default:
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", types.ModuleName, msg)
}
Expand Down
10 changes: 6 additions & 4 deletions x/bounty/keeper/finding.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,12 @@ func (k Keeper) GetPidFindingIDList(ctx sdk.Context, pid uint64) ([]uint64, erro

func (k Keeper) AppendFidToFidList(ctx sdk.Context, pid, fid uint64) error {
fids, err := k.GetPidFindingIDList(ctx, pid)
if err.Error() == types.ErrorEmptyProgramIDFindingList {
fids = []uint64{}
} else if err != nil {
return err
if err != nil {
if err.Error() == types.ErrorEmptyProgramIDFindingList {
fids = []uint64{}
} else {
return err
}
}

fids = append(fids, fid)
Expand Down
Loading