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

feat: ADR-036: Arbitrary Message Signature Specification #7896

Closed
wants to merge 74 commits into from
Closed
Show file tree
Hide file tree
Changes from 61 commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
6c8406e
add: arbitrary signature adr draft
fdymylja Oct 28, 2020
f54988f
fix: adr number
fdymylja Oct 29, 2020
deb1d03
Merge branch 'master' into frojdi/signature-adr
Oct 29, 2020
971d0b6
Merge branch 'master' into frojdi/signature-adr
Oct 29, 2020
054f689
Merge branch 'master' into frojdi/signature-adr
fdymylja Oct 29, 2020
e012555
change: adjust scope, address feedback
fdymylja Oct 29, 2020
8481af3
fix: missing sentence
fdymylja Oct 29, 2020
6fb3681
Merge branch 'master' into frojdi/signature-adr
Oct 30, 2020
4cb2ee8
Merge branch 'master' into frojdi/signature-adr
Oct 30, 2020
8325dbf
Merge branch 'master' into frojdi/signature-adr
Nov 1, 2020
d92cf39
Merge branch 'master' into frojdi/signature-adr
Nov 2, 2020
252ca11
Merge branch 'master' into frojdi/signature-adr
Nov 5, 2020
3c6ee29
Merge branch 'master' into frojdi/signature-adr
Nov 5, 2020
2ff847d
Merge branch 'master' into frojdi/signature-adr
Nov 6, 2020
5f53530
Merge branch 'master' into frojdi/signature-adr
Nov 9, 2020
3faf219
Merge branch 'master' into frojdi/signature-adr
Nov 9, 2020
b8620d9
Merge branch 'master' into frojdi/signature-adr
fdymylja Nov 10, 2020
87ad64a
change: address wording
fdymylja Nov 10, 2020
f15c487
change: address wording and formatting
fdymylja Nov 10, 2020
1e33f9f
change: address formatting
fdymylja Nov 10, 2020
4ad1115
change: message name, address modal verbs changes
fdymylja Nov 10, 2020
8ddd4cb
change: document how MsgSignData should be used
fdymylja Nov 10, 2020
03d0804
Merge remote-tracking branch 'origin/frojdi/signature-adr' into frojd…
fdymylja Nov 10, 2020
af35dc4
change: address wording
fdymylja Nov 10, 2020
d147329
add: offchain init
fdymylja Nov 11, 2020
3e2516f
chore: cleanup gomod
fdymylja Nov 11, 2020
61b07fb
change: use testify.Suite
fdymylja Nov 11, 2020
9640e1e
change: change error types to sdkerrors
fdymylja Nov 11, 2020
4ad6bd5
add: missing tests
fdymylja Nov 11, 2020
7262fad
remove: logging
fdymylja Nov 11, 2020
fa98012
chore: gomod tidy
fdymylja Nov 11, 2020
bd0a07d
chore: make linter happy
fdymylja Nov 11, 2020
0b60125
fix: MsgSignData type URL
fdymylja Nov 12, 2020
df8248b
chore: proto lint
fdymylja Nov 12, 2020
fc88045
fix: verify test
fdymylja Nov 12, 2020
9cf6e4f
Merge remote-tracking branch 'origin/master' into fdymylja/implement-…
fdymylja Nov 12, 2020
d11c2a4
Merge branch 'master' into frojdi/signature-adr
Nov 12, 2020
71a58b9
chore: clean go mod and makefile
fdymylja Nov 12, 2020
cbd42ac
add: how verification works
fdymylja Nov 12, 2020
ec0cee2
Merge branch 'frojdi/signature-adr' of https://github.com/cosmos/cosm…
fdymylja Nov 12, 2020
8418241
Merge branch 'master' into frojdi/signature-adr
Nov 13, 2020
4b11e74
Merge branch 'master' into frojdi/signature-adr
Nov 13, 2020
0fc3e61
Merge branch 'master' into frojdi/signature-adr
Nov 13, 2020
6967986
Update docs/architecture/adr-036-arbitrary-signature.md
Nov 13, 2020
10f4cd5
Update docs/architecture/adr-036-arbitrary-signature.md
Nov 13, 2020
bd83648
Apply suggestions from code review
Nov 13, 2020
181ba07
Update docs/architecture/adr-036-arbitrary-signature.md
Nov 13, 2020
6f65692
add: expand further discussion items
fdymylja Nov 13, 2020
2e5cea6
Merge branch 'frojdi/signature-adr' of https://github.com/cosmos/cosm…
fdymylja Nov 13, 2020
9a03583
fix: wording
fdymylja Nov 13, 2020
4847358
add: context references
fdymylja Nov 13, 2020
ab670d0
change: split offchain tx specific from MsgSignData
fdymylja Nov 13, 2020
d8523c1
Merge branch 'master' into frojdi/signature-adr
Nov 13, 2020
e0f5751
change: move offchain implementation to x/auth
fdymylja Nov 13, 2020
8c86444
change: MsgSignData signer to string
fdymylja Nov 13, 2020
61dfc0b
Merge branch 'master' into frojdi/signature-adr
Nov 13, 2020
c35d50f
Merge branch 'master' into frojdi/signature-adr
Nov 13, 2020
3fe26de
Merge branch 'master' into frojdi/signature-adr
Nov 13, 2020
fb1541a
Merge remote-tracking branch 'origin/frojdi/signature-adr' into fdymy…
fdymylja Nov 13, 2020
a27f9f1
change: support keyring
fdymylja Nov 16, 2020
c101582
chore: linting fixes
fdymylja Nov 16, 2020
34ab811
Merge branch 'master' into fdymylja/implement-adr-034
Apr 20, 2021
00558b2
run go mod tidy
Apr 20, 2021
0091e63
run make format
Apr 20, 2021
630b661
fix usage of GetPubKeys(), linter warnings
Apr 20, 2021
3d79fab
Merge branch 'master' into fdymylja/implement-adr-034
fdymylja Apr 21, 2021
8f84dd3
Merge branch 'master' into fdymylja/implement-adr-034
May 10, 2021
d663fb7
Merge branch 'master' into fdymylja/implement-adr-034
May 21, 2021
92a3d87
Merge branch 'master' into fdymylja/implement-adr-034
Sep 22, 2021
d6bde94
Merge branch 'master' of github.com:cosmos/cosmos-sdk into fdymylja/i…
RiccardoM Apr 19, 2022
8b9773b
moved files into the proper folder and updated ADR
RiccardoM Apr 19, 2022
21019e0
updated MsgSignData Proto spec
RiccardoM Apr 19, 2022
aeefcac
Merge branch 'main' into fdymylja/implement-adr-034
tac0turtle Apr 25, 2022
cba434a
Merge branch 'main' into fdymylja/implement-adr-034
RiccardoM Apr 25, 2022
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
128 changes: 128 additions & 0 deletions docs/architecture/adr-036-arbitrary-signature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# ADR 036: Arbitrary Message Signature Specification

## Changelog

- 28/10/2020 - Initial draft

## Authors
- Antoine Herzog (@antoineherzog)
- Zaki Manian (@zmanian)
- Aleksandr Bezobchuk (alexanderbez) [1]
- Frojdi Dymylja (@fdymylja)

## Status

Draft

## Abstract

Currently, in the SDK, there is no convention to sign arbitrary message like on Ethereum. We propose with this specification, for Cosmos SDK ecosystem, a way to sign and validate off-chain arbitrary messages.

This specification serves the purpose of covering every use case, this means that cosmos-sdk applications developers decide how to serialize and represent `Data` to users.
## Context

Having the ability to sign messages off-chain has proven to be a fundamental aspect of nearly any blockchain. The notion of signing messages off-chain has many added benefits such as saving on computational costs and reducing transaction throughput and overhead. Within the context of the Cosmos, some of the major applications of signing such data includes, but is not limited to, providing a cryptographic secure and verifiable means of proving validator identity and possibly associating it with some other framework or organization. In addition, having the ability to sign Cosmos messages with a Ledger or similar HSM device.

Further context and use cases can be found in the references links.

## Decision

The aim is being able to sign arbitrary messages, even using Ledger or similar HSM devices.

As a result signed messages should look roughly like Cosmos SDK messages but **must not** be a valid on-chain transaction. `chain-id`, `account_number` and `sequence` can all be assigned invalid values.

Cosmos SDK 0.40 also introduces a concept of “auth_info” this can specify SIGN_MODES.

A spec should include an `auth_info` that supports SIGN_MODE_DIRECT and SIGN_MODE_LEGACY_AMINO.

Create the `offchain` proto definitions, we extend the auth module with `offchain` package to offer functionalities to verify and sign offline messages.

An offchain transaction follows these rules:

- the memo must be empty
- nonce, sequence number must be equal to 0
- chain-id must be equal to “”
- fee gas must be equal to 0
- fee amount must be an empty array

Verification of an offchain transaction follows the same rules as an onchain one, except for the spec differences highlighted above.

The first message added to the `offchain` package is `MsgSignData`.

`MsgSignData` allows developers to sign arbitrary bytes valid offchain only. Where `Signer` is the account address of the signer. `Data` is arbitrary bytes which can represent `text`, `files`, `object`s. It's applications developers decision how `Data` should be deserialized, serialized and the object it can represent in their context.

It's applications developers decision how `Data` should be treated, by treated we mean the serialization and deserialization process and the Object `Data` should represent.


Proto definition:
```proto
// MsgSignData defines an arbitrary, general-purpose, off-chain message
message MsgSignData {
// Signer is the sdk.AccAddress of the message signer
bytes Signer = 1 [(gogoproto.jsontag) = "signer", (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"];
// Data represents the raw bytes of the content that is signed (text, json, etc)
bytes Data = 2 [(gogoproto.jsontag) = "data"];
}
```
Signed MsgSignData json example:
```json
{
"type": "cosmos-sdk/StdTx",
"value": {
"msg": [
{
"type": "sign/MsgSignData",
"value": {
"signer": "cosmos1hftz5ugqmpg9243xeegsqqav62f8hnywsjr4xr",
"data": "cmFuZG9t"
}
}
],
"fee": {
"amount": [],
"gas": "0"
},
"signatures": [
{
"pub_key": {
"type": "tendermint/PubKeySecp256k1",
"value": "AqnDSiRoFmTPfq97xxEb2VkQ/Hm28cPsqsZm9jEVsYK9"
},
"signature": "8y8i34qJakkjse9pOD2De+dnlc4KvFgh0wQpes4eydN66D9kv7cmCEouRrkka9tlW9cAkIL52ErB+6ye7X5aEg=="
}
],
"memo": ""
}
}
```

## Consequences

There is a specification on how messages, that are not meant to be broadcast to a live chain, should be formed.

### Backwards Compatibility

Backwards compatibility is maintained as this is a new message spec definition.

### Positive

- A common format that can be used by multiple applications to sign and verify off-chain messages.
- The specification is primitive which means it can cover every use case without limiting what is possible to fit inside it.
- It gives room for other off-chain messages specifications that aim to target more specific and common use cases such as off-chain-based authN/authZ layers [2].

### Negative

- Current proposal requires a fixed relationship between an account address and a public key.
- Doesn't work with multisig accounts.

## Further discussion

- Regarding security in `MsgSignData`, the developer using `MsgSignData` is in charge of making the content laying in `Data` non-replayable when, and if, needed.
- the offchain package will be further extended with extra messages that target specific use cases such as, but not limited to, authentication in applications, payment channels, L2 solutions in general.

## References

1. https://github.com/cosmos/ics/pull/33
2. https://github.com/cosmos/cosmos-sdk/pull/7727#discussion_r515668204
3. https://github.com/cosmos/cosmos-sdk/pull/7727#issuecomment-722478477
4. https://github.com/cosmos/cosmos-sdk/pull/7727#issuecomment-721062923
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,4 @@ require (
gopkg.in/yaml.v2 v2.3.0
)

replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.2-alpha.regen.4
replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.2-alpha.regen.4
2 changes: 1 addition & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -877,4 +877,4 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
15 changes: 15 additions & 0 deletions proto/cosmos/offchain/v1alpha1/offchain.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
syntax="proto3";

package cosmos.offchain.v1alpha1;
Copy link
Collaborator

Choose a reason for hiding this comment

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

how about storing this file in proto/cosmos/auth/v1beta1/offchain-sig/?

Copy link
Collaborator

Choose a reason for hiding this comment

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

After the meeting today, I suggest to move this to proto/cosmos/offchain/adr038 :

  • offchain - a place where we group offchain use-cases
  • adr038 - name of this use-case - unless you have better idea?


option go_package="github.com/cosmos/cosmos-sdk/x/auth/offchain";

import "gogoproto/gogo.proto";

// MsgSignData defines an arbitrary, general-purpose, off-chain message
message MsgSignData {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
message MsgSignData {
message SigData {

Copy link
Collaborator

Choose a reason for hiding this comment

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

  1. we shouldn't prefix it with Msg because that would confuse with state machine messages / transaction messages.
  2. Sig (signature) is better than Sign (signing)

Copy link
Member

Choose a reason for hiding this comment

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

If you change the name as part of this PR, could you also adapt ADR 036 accordingly? We have Amino sirning with type sign/MsgSignData there.

Since this sits in the msg field of a transaction, the current naming makes perfect sense to me. The SDK should just not process MsgSignDatas.

Copy link
Contributor

@RiccardoM RiccardoM Apr 19, 2022

Choose a reason for hiding this comment

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

What's the end decision on this? Should we remove Msg or not?

// signer is the bech32 representation of the signer's account address
string signer = 1;
// data represents the raw bytes of the content that is signed (text, json, etc)
bytes data = 2;
}
27 changes: 27 additions & 0 deletions x/auth/offchain/codec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package offchain
Copy link
Collaborator

Choose a reason for hiding this comment

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

similarly to the proto path - let's move this package to /offchain/adr036


import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
)

// ModuleCdc is the codec used by the module to serialize and deserialize data
var ModuleCdc = codec.NewAminoCodec(amino)
var amino = codec.NewLegacyAmino()

// RegisterInterfaces adds offchain sdk.Msg types to the interface registry
func RegisterInterfaces(ir types.InterfaceRegistry) {
ir.RegisterImplementations((*sdk.Msg)(nil), &MsgSignData{})
}

// RegisterLegacyAminoCodec registers amino's legacy codec
func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
cdc.RegisterConcrete(&MsgSignData{}, "offchain/MsgSignData", nil)
Copy link
Member

Choose a reason for hiding this comment

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

Could you please update ADR 036 too? There we have sign/MsgSignData

}

func init() {
RegisterLegacyAminoCodec(amino)
cryptocodec.RegisterCrypto(amino)
}
74 changes: 74 additions & 0 deletions x/auth/offchain/offchain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package offchain

import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)

// interface implementation assertions
var _ msg = &MsgSignData{}

const (
// ExpectedChainID defines the chain id an off-chain message must have
ExpectedChainID = ""
// ExpectedAccountNumber defines the account number an off-chain message must have
ExpectedAccountNumber = 0
// ExpectedSequence defines the sequence number an off-chain message must have
ExpectedSequence = 0
// ExpectedRoute defines the route to use for sdk.Msg.ExpectedRoute() implementation for offchain messages
ExpectedRoute = "offchain"
)

// msg defines an off-chain msg this exists so that offchain verification
// procedures are only applied to transactions lying in this package.
// TODO: making this exported would allow external types to use the SignatureVerifier and Signer
type msg interface {
sdk.Msg
offchain()
}

// NewMsgSignData is MsgSignData's constructor
func NewMsgSignData(signer sdk.AccAddress, data []byte) *MsgSignData { // nolint
return &MsgSignData{
Signer: signer.String(),
Data: data,
}
}

// sdk.Msg implementation

func (m *MsgSignData) Route() string {
return ExpectedRoute
}

func (m *MsgSignData) Type() string {
return "MsgSignData"
}

func (m *MsgSignData) ValidateBasic() error {
signer, err := sdk.AccAddressFromBech32(m.Signer)
if err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid signer: %s", err.Error())
}
if signer.Empty() {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "empty signer")
}
if len(m.Data) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "empty data")
}
return nil
}

func (m *MsgSignData) GetSignBytes() []byte {
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(m))
}

func (m *MsgSignData) GetSigners() []sdk.AccAddress {
signer, err := sdk.AccAddressFromBech32(m.Signer)
if err != nil {
panic(err)
}
return []sdk.AccAddress{signer}
}

func (m *MsgSignData) offchain() {}
Loading