forked from cosmos/cosmos-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e04a80c
commit 3a3abcd
Showing
8 changed files
with
299 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package attestation | ||
|
||
import ( | ||
"bytes" | ||
"encoding/hex" | ||
"github.com/tendermint/tendermint/crypto" | ||
) | ||
|
||
type Attestation struct { | ||
PublicKey crypto.PubKey | ||
Signature []byte | ||
} | ||
|
||
func NewAttestation(key crypto.PrivKey) (*Attestation, error) { | ||
|
||
// create the basic attestation | ||
att := &Attestation{ | ||
PublicKey: key.PubKey(), | ||
Signature: []byte{}, | ||
} | ||
|
||
// sign the attestation | ||
err := att.sign(key) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return att, nil | ||
} | ||
|
||
func NewAttestationFromString(encoded string) (*Attestation, error) { | ||
|
||
// decode the string | ||
bz, err := hex.DecodeString(encoded) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// unmarshall the attestation | ||
att := &Attestation{} | ||
err = UnmarshalBinaryBare(bz, att) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return att, nil | ||
} | ||
|
||
func (at *Attestation) sign(key crypto.PrivKey) error { | ||
|
||
// sign the payload | ||
signature, err := key.Sign(at.PublicKey.Address().Bytes()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// update the signature | ||
at.Signature = signature | ||
|
||
return nil | ||
} | ||
|
||
func (at *Attestation) Verify(address crypto.Address) bool { | ||
|
||
// ensure that the address derived from the public key matches the required address | ||
if !bytes.Equal(at.PublicKey.Address().Bytes(), address.Bytes()) { | ||
return false | ||
} | ||
|
||
// validate the signature present matches the public key | ||
return at.PublicKey.VerifyBytes(at.PublicKey.Address().Bytes(), at.Signature) | ||
} | ||
|
||
func (at *Attestation) Bytes() []byte { | ||
return AttestationCdc.MustMarshalBinaryBare(at) | ||
} | ||
|
||
func (at *Attestation) String() string { | ||
return hex.EncodeToString(at.Bytes()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package attestation | ||
|
||
import ( | ||
"bytes" | ||
"crypto/rand" | ||
"github.com/cosmos/cosmos-sdk/crypto/keys" | ||
"github.com/stretchr/testify/require" | ||
"github.com/tendermint/tendermint/crypto" | ||
"testing" | ||
) | ||
|
||
func generatePrivateKey(t *testing.T) crypto.PrivKey { | ||
|
||
// generate seed for the private key | ||
bz := make([]byte, 32) | ||
_, err := rand.Read(bz) | ||
require.NoError(t, err) | ||
|
||
// create the key | ||
return keys.SecpPrivKeyGen(bz) | ||
} | ||
|
||
func TestBasicAttestation(t *testing.T) { | ||
privKey := generatePrivateKey(t) | ||
|
||
// create the attestation | ||
att, err := NewAttestation(privKey) | ||
require.NoError(t, err) | ||
|
||
// verify that it is correct | ||
require.True(t, att.Verify(privKey.PubKey().Address())) | ||
} | ||
|
||
func TestBasicAttestationMarshalling(t *testing.T) { | ||
privKey := generatePrivateKey(t) | ||
|
||
// create the attestation | ||
att, err := NewAttestation(privKey) | ||
require.NoError(t, err) | ||
|
||
// marshall it to binary | ||
bz, err := MarshalBinaryBare(att) | ||
require.NoError(t, err) | ||
|
||
// recover the attestation | ||
recoveredAtt := &Attestation{} | ||
err = UnmarshalBinaryBare(bz, recoveredAtt) | ||
require.NoError(t, err) | ||
|
||
require.True(t, att.PublicKey.Equals(recoveredAtt.PublicKey)) | ||
require.True(t, bytes.Equal(att.Signature, recoveredAtt.Signature)) | ||
|
||
// check that it sis correct | ||
require.True(t, recoveredAtt.Verify(att.PublicKey.Address())) | ||
} | ||
|
||
func TestAttestationAsString(t *testing.T) { | ||
privKey := generatePrivateKey(t) | ||
|
||
// create the attestation | ||
att, err := NewAttestation(privKey) | ||
require.NoError(t, err) | ||
|
||
// recover the attestation | ||
recovered, err := NewAttestationFromString(att.String()) | ||
require.NoError(t, err) | ||
|
||
require.True(t, att.PublicKey.Equals(recovered.PublicKey)) | ||
require.True(t, bytes.Equal(att.Signature, recovered.Signature)) | ||
require.True(t, recovered.Verify(privKey.PubKey().Address())) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package attestation | ||
|
||
import ( | ||
"github.com/cosmos/cosmos-sdk/codec" | ||
) | ||
|
||
var AttestationCdc *codec.Codec | ||
|
||
func init() { | ||
AttestationCdc = codec.New() | ||
codec.RegisterCrypto(AttestationCdc) | ||
AttestationCdc.RegisterConcrete(Attestation{}, "cosmos-sdk/Attestation", nil) | ||
AttestationCdc.Seal() | ||
} | ||
|
||
// marshal | ||
func MarshalBinaryBare(o interface{}) ([]byte, error) { | ||
return AttestationCdc.MarshalBinaryBare(o) | ||
} | ||
|
||
// unmarshal | ||
func UnmarshalBinaryBare(bz []byte, ptr interface{}) error { | ||
return AttestationCdc.UnmarshalBinaryBare(bz, ptr) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package keys | ||
|
||
import ( | ||
"bufio" | ||
"errors" | ||
"fmt" | ||
"github.com/cosmos/cosmos-sdk/client/attestation" | ||
"github.com/cosmos/cosmos-sdk/client/flags" | ||
"github.com/cosmos/cosmos-sdk/client/input" | ||
"github.com/cosmos/cosmos-sdk/crypto/keys" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
"github.com/spf13/cobra" | ||
"github.com/spf13/viper" | ||
"github.com/tendermint/tendermint/crypto" | ||
"github.com/tendermint/tendermint/libs/bech32" | ||
) | ||
|
||
func AttestationCmd() *cobra.Command { | ||
cmd := &cobra.Command{ | ||
Use: "attestation", | ||
Short: "Create or verify attestations", | ||
Long: `Create or verify offline proofs to demonstrate ownership of keys`, | ||
} | ||
|
||
cmd.AddCommand( | ||
&cobra.Command{ | ||
Use: "create [name]", | ||
Short: "Create an attestation", | ||
Long: "Create and attestation for one of the keys present in the store", | ||
Args: cobra.ExactArgs(1), | ||
RunE: runAttestationCreate, | ||
}, | ||
&cobra.Command{ | ||
Use: "verify [address] [attestation]", | ||
Short: "Verify an attestation", | ||
Long: "Given an attestation and address, verify that one proves ownership of the other", | ||
Args: cobra.ExactArgs(2), | ||
RunE: runAttestationVerify, | ||
}, | ||
) | ||
|
||
return cmd | ||
} | ||
|
||
func runAttestationCreate(cmd *cobra.Command, args []string) error { | ||
buf := bufio.NewReader(cmd.InOrStdin()) | ||
kb, err := keys.NewKeyring(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), buf) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
decryptPassword, err := input.GetPassword("Enter passphrase to decrypt your key:", buf) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
privKey, err := kb.ExportPrivateKeyObject(args[0], decryptPassword) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
att, err := attestation.NewAttestation(privKey) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
cmd.Println(att.String()) | ||
|
||
return nil | ||
} | ||
|
||
func runAttestationVerify(cmd *cobra.Command, args []string) error { | ||
_, bz, err := bech32.DecodeAndConvert(args[0]) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
var address crypto.Address = bz | ||
|
||
// create the attestation | ||
att, err := attestation.NewAttestationFromString(args[1]) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// verification check | ||
verified := att.Verify(address) | ||
if !verified { | ||
return errors.New("verification failed") | ||
} | ||
|
||
fmt.Println("verification successful") | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters