Browse Source

Cleanup; Implement .Wrap()

pull/1782/head
Jae Kwon 8 years ago
committed by Ethan Frey
parent
commit
a3324cc97b
7 changed files with 181 additions and 233 deletions
  1. +9
    -0
      crypto.go
  2. +32
    -70
      embed_test.go
  3. +2
    -2
      encode_test.go
  4. +39
    -52
      priv_key.go
  5. +40
    -45
      pub_key.go
  6. +47
    -52
      signature.go
  7. +12
    -12
      signature_test.go

+ 9
- 0
crypto.go View File

@ -0,0 +1,9 @@
package crypto
// Types of implementations
const (
TypeEd25519 = byte(0x01)
TypeSecp256k1 = byte(0x02)
NameEd25519 = "ed25519"
NameSecp256k1 = "secp256k1"
)

+ 32
- 70
embed_test.go View File

@ -9,50 +9,13 @@ import (
data "github.com/tendermint/go-data"
)
type Foo struct {
Name string
}
func (f Foo) Greet() string {
return "Foo: " + f.Name
}
type Bar struct {
Age int
}
func (b Bar) Greet() string {
return fmt.Sprintf("Bar #%d", b.Age)
type PubName struct {
PubNameInner
}
type PubNameInner interface {
Greet() string
}
type privNameInner interface {
Greet() string
}
type Greeter interface {
Greet() string
}
var (
pubNameMapper, privNameMapper data.Mapper
)
// register both public key types with go-data (and thus go-wire)
func init() {
pubNameMapper = data.NewMapper(PubName{}).
RegisterImplementation(Foo{}, "foo", 1).
RegisterImplementation(Bar{}, "bar", 2)
privNameMapper = data.NewMapper(PrivName{}).
RegisterImplementation(Foo{}, "foo", 1).
RegisterImplementation(Bar{}, "bar", 2)
}
type PubName struct {
PubNameInner
AssertIsPubNameInner()
String() string
}
func (p PubName) MarshalJSON() ([]byte, error) {
@ -67,62 +30,61 @@ func (p *PubName) UnmarshalJSON(data []byte) error {
return err
}
type PrivName struct {
privNameInner
}
var pubNameMapper = data.NewMapper(PubName{}).
RegisterImplementation(PubNameFoo{}, "foo", 1).
RegisterImplementation(PubNameBar{}, "bar", 2)
func (p PrivName) MarshalJSON() ([]byte, error) {
return privNameMapper.ToJSON(p.privNameInner)
func (f PubNameFoo) AssertIsPubNameInner() {}
func (f PubNameBar) AssertIsPubNameInner() {}
//----------------------------------------
type PubNameFoo struct {
Name string
}
func (p *PrivName) UnmarshalJSON(data []byte) error {
parsed, err := privNameMapper.FromJSON(data)
if err == nil && parsed != nil {
p.privNameInner = parsed.(privNameInner)
}
return err
func (f PubNameFoo) String() string { return "Foo: " + f.Name }
type PubNameBar struct {
Age int
}
func (b PubNameBar) String() string { return fmt.Sprintf("Bar #%d", b.Age) }
//----------------------------------------
// TestEncodeDemo tries the various strategies to encode the objects
func TestEncodeDemo(t *testing.T) {
assert, require := assert.New(t), require.New(t)
// assert := assert.New(t)
// require := require.New(t)
cases := []struct {
in, out Greeter
in, out PubNameInner
expected string
}{
{PubName{Foo{"pub-foo"}}, &PubName{}, "Foo: pub-foo"},
{PubName{Bar{7}}, &PubName{}, "Bar #7"},
// Note these fail - if you can figure a solution here, I'll buy you a beer :)
// (ebuchman is right, you must either break the reflection system, or modify go-wire)
// but such a mod would let us make REALLY sure that no one could construct like this
// {PrivName{Foo{"priv-foo"}}, &PrivName{}, "Foo: priv-foo"},
// {PrivName{Bar{9}}, &PrivName{}, "Bar #9"},
{PubName{PubNameFoo{"pub-foo"}}, &PubName{}, "Foo: pub-foo"},
{PubName{PubNameBar{7}}, &PubName{}, "Bar #7"},
}
for i, tc := range cases {
// make sure it is proper to start
require.Equal(tc.expected, tc.in.Greet())
// now, try to encode as binary
// Make sure it is proper to start
require.Equal(tc.expected, tc.in.String())
// Try to encode as binary
b, err := data.ToWire(tc.in)
if assert.Nil(err, "%d: %#v", i, tc.in) {
err := data.FromWire(b, tc.out)
if assert.Nil(err) {
assert.Equal(tc.expected, tc.out.Greet())
assert.Equal(tc.expected, tc.out.String())
}
}
// try to encode it as json
// Try to encode it as json
j, err := data.ToJSON(tc.in)
if assert.Nil(err, "%d: %#v", i, tc.in) {
err := data.FromJSON(j, tc.out)
if assert.Nil(err) {
assert.Equal(tc.expected, tc.out.Greet())
assert.Equal(tc.expected, tc.out.String())
}
}
}


+ 2
- 2
encode_test.go View File

@ -69,12 +69,12 @@ func TestKeyEncodings(t *testing.T) {
keyName string
}{
{
privKey: WrapPrivKey(GenPrivKeyEd25519()),
privKey: GenPrivKeyEd25519().Wrap(),
keyType: TypeEd25519,
keyName: NameEd25519,
},
{
privKey: WrapPrivKey(GenPrivKeySecp256k1()),
privKey: GenPrivKeySecp256k1().Wrap(),
keyType: TypeSecp256k1,
keyName: NameSecp256k1,
},


+ 39
- 52
priv_key.go View File

@ -11,50 +11,38 @@ import (
"github.com/tendermint/go-wire"
)
/*
DO NOT USE this interface.
func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) {
err = wire.ReadBinaryBytes(privKeyBytes, &privKey)
return
}
It is public by necessity but should never be used directly
outside of this package.
//----------------------------------------
Only use the PrivKey, never the PrivKeyInner
*/
type PrivKey struct {
PrivKeyInner `json:"unwrap"`
}
// DO NOT USE THIS INTERFACE.
// You probably want to use PubKey
type PrivKeyInner interface {
AssertIsPrivKeyInner()
Bytes() []byte
Sign(msg []byte) Signature
PubKey() PubKey
Equals(PrivKey) bool
Wrap() PrivKey
}
// Types of implementations
const (
TypeEd25519 = byte(0x01)
TypeSecp256k1 = byte(0x02)
NameEd25519 = "ed25519"
NameSecp256k1 = "secp256k1"
)
var privKeyMapper data.Mapper
// register both private key types with go-data (and thus go-wire)
func init() {
privKeyMapper = data.NewMapper(PrivKey{}).
RegisterImplementation(PrivKeyEd25519{}, NameEd25519, TypeEd25519).
RegisterImplementation(PrivKeySecp256k1{}, NameSecp256k1, TypeSecp256k1)
}
// PrivKey should be used instead of an interface in all external packages
// unless you demand a concrete implementation, then use that directly.
type PrivKey struct {
PrivKeyInner `json:"unwrap"`
func (p PrivKey) MarshalJSON() ([]byte, error) {
return privKeyMapper.ToJSON(p.PrivKeyInner)
}
// WrapPrivKey goes from concrete implementation to "interface" struct
func WrapPrivKey(pk PrivKeyInner) PrivKey {
if wrap, ok := pk.(PrivKey); ok {
pk = wrap.Unwrap()
func (p *PrivKey) UnmarshalJSON(data []byte) (err error) {
parsed, err := privKeyMapper.FromJSON(data)
if err == nil && parsed != nil {
p.PrivKeyInner = parsed.(PrivKeyInner)
}
return PrivKey{pk}
return
}
// Unwrap recovers the concrete interface safely (regardless of levels of embeds)
@ -66,32 +54,21 @@ func (p PrivKey) Unwrap() PrivKeyInner {
return pk
}
func (p PrivKey) MarshalJSON() ([]byte, error) {
return privKeyMapper.ToJSON(p.PrivKeyInner)
}
func (p *PrivKey) UnmarshalJSON(data []byte) (err error) {
parsed, err := privKeyMapper.FromJSON(data)
if err == nil && parsed != nil {
p.PrivKeyInner = parsed.(PrivKeyInner)
}
return
}
func (p PrivKey) Empty() bool {
return p.PrivKeyInner == nil
}
func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) {
err = wire.ReadBinaryBytes(privKeyBytes, &privKey)
return
}
var privKeyMapper = data.NewMapper(PrivKey{}).
RegisterImplementation(PrivKeyEd25519{}, NameEd25519, TypeEd25519).
RegisterImplementation(PrivKeySecp256k1{}, NameSecp256k1, TypeSecp256k1)
//-------------------------------------
// Implements PrivKey
type PrivKeyEd25519 [64]byte
func (privKey PrivKeyEd25519) AssertIsPrivKeyInner() {}
func (privKey PrivKeyEd25519) Bytes() []byte {
return wire.BinaryBytes(PrivKey{privKey})
}
@ -99,13 +76,13 @@ func (privKey PrivKeyEd25519) Bytes() []byte {
func (privKey PrivKeyEd25519) Sign(msg []byte) Signature {
privKeyBytes := [64]byte(privKey)
signatureBytes := ed25519.Sign(&privKeyBytes, msg)
return WrapSignature(SignatureEd25519(*signatureBytes))
return SignatureEd25519(*signatureBytes).Wrap()
}
func (privKey PrivKeyEd25519) PubKey() PubKey {
privKeyBytes := [64]byte(privKey)
pubBytes := *ed25519.MakePublicKey(&privKeyBytes)
return WrapPubKey(PubKeyEd25519(pubBytes))
return PubKeyEd25519(pubBytes).Wrap()
}
func (privKey PrivKeyEd25519) Equals(other PrivKey) bool {
@ -149,6 +126,10 @@ func (privKey PrivKeyEd25519) Generate(index int) PrivKeyEd25519 {
return PrivKeyEd25519(newKey)
}
func (privKey PrivKeyEd25519) Wrap() PrivKey {
return PrivKey{privKey}
}
func GenPrivKeyEd25519() PrivKeyEd25519 {
privKeyBytes := new([64]byte)
copy(privKeyBytes[:32], CRandBytes(32))
@ -171,6 +152,8 @@ func GenPrivKeyEd25519FromSecret(secret []byte) PrivKeyEd25519 {
// Implements PrivKey
type PrivKeySecp256k1 [32]byte
func (privKey PrivKeySecp256k1) AssertIsPrivKeyInner() {}
func (privKey PrivKeySecp256k1) Bytes() []byte {
return wire.BinaryBytes(PrivKey{privKey})
}
@ -181,14 +164,14 @@ func (privKey PrivKeySecp256k1) Sign(msg []byte) Signature {
if err != nil {
PanicSanity(err)
}
return WrapSignature(SignatureSecp256k1(sig__.Serialize()))
return SignatureSecp256k1(sig__.Serialize()).Wrap()
}
func (privKey PrivKeySecp256k1) PubKey() PubKey {
_, pub__ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:])
var pub PubKeySecp256k1
copy(pub[:], pub__.SerializeCompressed())
return WrapPubKey(pub)
return pub.Wrap()
}
func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool {
@ -214,6 +197,10 @@ func (privKey PrivKeySecp256k1) String() string {
return Fmt("PrivKeySecp256k1{*****}")
}
func (privKey PrivKeySecp256k1) Wrap() PrivKey {
return PrivKey{privKey}
}
/*
// Deterministically generates new priv-key bytes from key.
func (key PrivKeySecp256k1) Generate(index int) PrivKeySecp256k1 {


+ 40
- 45
pub_key.go View File

@ -13,80 +13,65 @@ import (
"golang.org/x/crypto/ripemd160"
)
/*
DO NOT USE this interface.
func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) {
err = wire.ReadBinaryBytes(pubKeyBytes, &pubKey)
return
}
It is public by necessity but should never be used directly
outside of this package.
//----------------------------------------
Only use the PubKey, never the PubKeyInner
*/
type PubKey struct {
PubKeyInner `json:"unwrap"`
}
// DO NOT USE THIS INTERFACE.
// You probably want to use PubKey
type PubKeyInner interface {
AssertIsPubKeyInner()
Address() []byte
Bytes() []byte
KeyString() string
VerifyBytes(msg []byte, sig Signature) bool
Equals(PubKey) bool
Wrap() PubKey
}
var pubKeyMapper data.Mapper
// register both public key types with go-data (and thus go-wire)
func init() {
pubKeyMapper = data.NewMapper(PubKey{}).
RegisterImplementation(PubKeyEd25519{}, NameEd25519, TypeEd25519).
RegisterImplementation(PubKeySecp256k1{}, NameSecp256k1, TypeSecp256k1)
func (pk PubKey) MarshalJSON() ([]byte, error) {
return pubKeyMapper.ToJSON(pk.PubKeyInner)
}
// PubKey should be used instead of an interface in all external packages
// unless you demand a concrete implementation, then use that directly.
type PubKey struct {
PubKeyInner `json:"unwrap"`
}
// WrapPubKey goes from concrete implementation to "interface" struct
func WrapPubKey(pk PubKeyInner) PubKey {
if wrap, ok := pk.(PubKey); ok {
pk = wrap.Unwrap()
func (pk *PubKey) UnmarshalJSON(data []byte) (err error) {
parsed, err := pubKeyMapper.FromJSON(data)
if err == nil && parsed != nil {
pk.PubKeyInner = parsed.(PubKeyInner)
}
return PubKey{pk}
return
}
// Unwrap recovers the concrete interface safely (regardless of levels of embeds)
func (p PubKey) Unwrap() PubKeyInner {
pk := p.PubKeyInner
for wrap, ok := pk.(PubKey); ok; wrap, ok = pk.(PubKey) {
pk = wrap.PubKeyInner
}
return pk
}
func (p PubKey) MarshalJSON() ([]byte, error) {
return pubKeyMapper.ToJSON(p.PubKeyInner)
}
func (p *PubKey) UnmarshalJSON(data []byte) (err error) {
parsed, err := pubKeyMapper.FromJSON(data)
if err == nil && parsed != nil {
p.PubKeyInner = parsed.(PubKeyInner)
func (pk PubKey) Unwrap() PubKeyInner {
pkI := pk.PubKeyInner
for wrap, ok := pkI.(PubKey); ok; wrap, ok = pkI.(PubKey) {
pkI = wrap.PubKeyInner
}
return
return pkI
}
func (p PubKey) Empty() bool {
return p.PubKeyInner == nil
}
func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) {
err = wire.ReadBinaryBytes(pubKeyBytes, &pubKey)
return
}
var pubKeyMapper = data.NewMapper(PubKey{}).
RegisterImplementation(PubKeyEd25519{}, NameEd25519, TypeEd25519).
RegisterImplementation(PubKeySecp256k1{}, NameSecp256k1, TypeSecp256k1)
//-------------------------------------
// Implements PubKeyInner
type PubKeyEd25519 [32]byte
func (pubKey PubKeyEd25519) AssertIsPubKeyInner() {}
func (pubKey PubKeyEd25519) Address() []byte {
w, n, err := new(bytes.Buffer), new(int), new(error)
wire.WriteBinary(pubKey[:], w, n, err)
@ -155,6 +140,10 @@ func (pubKey PubKeyEd25519) Equals(other PubKey) bool {
}
}
func (pubKey PubKeyEd25519) Wrap() PubKey {
return PubKey{pubKey}
}
//-------------------------------------
// Implements PubKey.
@ -162,6 +151,8 @@ func (pubKey PubKeyEd25519) Equals(other PubKey) bool {
// prefixed with 0x02 or 0x03, depending on the y-cord.
type PubKeySecp256k1 [33]byte
func (pubKey PubKeySecp256k1) AssertIsPubKeyInner() {}
// Implements Bitcoin style addresses: RIPEMD160(SHA256(pubkey))
func (pubKey PubKeySecp256k1) Address() []byte {
hasherSHA256 := sha256.New()
@ -223,3 +214,7 @@ func (pubKey PubKeySecp256k1) Equals(other PubKey) bool {
return false
}
}
func (pubKey PubKeySecp256k1) Wrap() PubKey {
return PubKey{pubKey}
}

+ 47
- 52
signature.go View File

@ -9,79 +9,64 @@ import (
"github.com/tendermint/go-wire"
)
/*
DO NOT USE this interface.
func SignatureFromBytes(sigBytes []byte) (sig Signature, err error) {
err = wire.ReadBinaryBytes(sigBytes, &sig)
return
}
It is public by necessity but should never be used directly
outside of this package.
//----------------------------------------
Only use the Signature, never the SignatureInner
*/
type Signature struct {
SignatureInner `json:"unwrap"`
}
// DO NOT USE THIS INTERFACE.
// You probably want to use Signature.
type SignatureInner interface {
AssertIsSignatureInner()
Bytes() []byte
IsZero() bool
String() string
Equals(Signature) bool
Wrap() Signature
}
var sigMapper data.Mapper
// register both public key types with go-data (and thus go-wire)
func init() {
sigMapper = data.NewMapper(Signature{}).
RegisterImplementation(SignatureEd25519{}, NameEd25519, TypeEd25519).
RegisterImplementation(SignatureSecp256k1{}, NameSecp256k1, TypeSecp256k1)
func (sig Signature) MarshalJSON() ([]byte, error) {
return sigMapper.ToJSON(sig.SignatureInner)
}
// Signature should be used instead of an interface in all external packages
// unless you demand a concrete implementation, then use that directly.
type Signature struct {
SignatureInner `json:"unwrap"`
}
// WrapSignature goes from concrete implementation to "interface" struct
func WrapSignature(pk SignatureInner) Signature {
if wrap, ok := pk.(Signature); ok {
pk = wrap.Unwrap()
func (sig *Signature) UnmarshalJSON(data []byte) (err error) {
parsed, err := sigMapper.FromJSON(data)
if err == nil && parsed != nil {
sig.SignatureInner = parsed.(SignatureInner)
}
return Signature{pk}
return
}
// Unwrap recovers the concrete interface safely (regardless of levels of embeds)
func (p Signature) Unwrap() SignatureInner {
pk := p.SignatureInner
func (sig Signature) Unwrap() SignatureInner {
pk := sig.SignatureInner
for wrap, ok := pk.(Signature); ok; wrap, ok = pk.(Signature) {
pk = wrap.SignatureInner
}
return pk
}
func (p Signature) MarshalJSON() ([]byte, error) {
return sigMapper.ToJSON(p.SignatureInner)
}
func (p *Signature) UnmarshalJSON(data []byte) (err error) {
parsed, err := sigMapper.FromJSON(data)
if err == nil && parsed != nil {
p.SignatureInner = parsed.(SignatureInner)
}
return
func (sig Signature) Empty() bool {
return sig.SignatureInner == nil
}
func (p Signature) Empty() bool {
return p.SignatureInner == nil
}
func SignatureFromBytes(sigBytes []byte) (sig Signature, err error) {
err = wire.ReadBinaryBytes(sigBytes, &sig)
return
}
var sigMapper = data.NewMapper(Signature{}).
RegisterImplementation(SignatureEd25519{}, NameEd25519, TypeEd25519).
RegisterImplementation(SignatureSecp256k1{}, NameSecp256k1, TypeSecp256k1)
//-------------------------------------
// Implements Signature
type SignatureEd25519 [64]byte
func (sig SignatureEd25519) AssertIsSignatureInner() {}
func (sig SignatureEd25519) Bytes() []byte {
return wire.BinaryBytes(Signature{sig})
}
@ -98,22 +83,28 @@ func (sig SignatureEd25519) Equals(other Signature) bool {
}
}
func (p SignatureEd25519) MarshalJSON() ([]byte, error) {
return data.Encoder.Marshal(p[:])
func (sig SignatureEd25519) MarshalJSON() ([]byte, error) {
return data.Encoder.Marshal(sig[:])
}
func (p *SignatureEd25519) UnmarshalJSON(enc []byte) error {
func (sig *SignatureEd25519) UnmarshalJSON(enc []byte) error {
var ref []byte
err := data.Encoder.Unmarshal(&ref, enc)
copy(p[:], ref)
copy(sig[:], ref)
return err
}
func (sig SignatureEd25519) Wrap() Signature {
return Signature{sig}
}
//-------------------------------------
// Implements Signature
type SignatureSecp256k1 []byte
func (sig SignatureSecp256k1) AssertIsSignatureInner() {}
func (sig SignatureSecp256k1) Bytes() []byte {
return wire.BinaryBytes(Signature{sig})
}
@ -129,10 +120,14 @@ func (sig SignatureSecp256k1) Equals(other Signature) bool {
return false
}
}
func (p SignatureSecp256k1) MarshalJSON() ([]byte, error) {
return data.Encoder.Marshal(p)
func (sig SignatureSecp256k1) MarshalJSON() ([]byte, error) {
return data.Encoder.Marshal(sig)
}
func (sig *SignatureSecp256k1) UnmarshalJSON(enc []byte) error {
return data.Encoder.Unmarshal((*[]byte)(sig), enc)
}
func (p *SignatureSecp256k1) UnmarshalJSON(enc []byte) error {
return data.Encoder.Unmarshal((*[]byte)(p), enc)
func (sig SignatureSecp256k1) Wrap() Signature {
return Signature{sig}
}

+ 12
- 12
signature_test.go View File

@ -24,7 +24,7 @@ func TestSignAndValidateEd25519(t *testing.T) {
// Mutate the signature, just one bit.
sigEd := sig.Unwrap().(SignatureEd25519)
sigEd[7] ^= byte(0x01)
sig = WrapSignature(sigEd)
sig = sigEd.Wrap()
assert.False(t, pubKey.VerifyBytes(msg, sig))
}
@ -41,7 +41,7 @@ func TestSignAndValidateSecp256k1(t *testing.T) {
// Mutate the signature, just one bit.
sigEd := sig.Unwrap().(SignatureSecp256k1)
sigEd[3] ^= byte(0x01)
sig = WrapSignature(sigEd)
sig = sigEd.Wrap()
assert.False(t, pubKey.VerifyBytes(msg, sig))
}
@ -54,13 +54,13 @@ func TestSignatureEncodings(t *testing.T) {
sigName string
}{
{
privKey: WrapPrivKey(GenPrivKeyEd25519()),
privKey: GenPrivKeyEd25519().Wrap(),
sigSize: ed25519.SignatureSize,
sigType: TypeEd25519,
sigName: NameEd25519,
},
{
privKey: WrapPrivKey(GenPrivKeySecp256k1()),
privKey: GenPrivKeySecp256k1().Wrap(),
sigSize: 0, // unknown
sigType: TypeSecp256k1,
sigName: NameSecp256k1,
@ -119,10 +119,10 @@ func TestWrapping(t *testing.T) {
// do some wrapping
pubs := []PubKey{
WrapPubKey(nil),
WrapPubKey(pub),
WrapPubKey(WrapPubKey(WrapPubKey(WrapPubKey(pub)))),
WrapPubKey(PubKey{PubKey{PubKey{pub}}}),
PubKey{nil},
pub.Wrap(),
pub.Wrap().Wrap().Wrap(),
PubKey{PubKey{PubKey{pub}}}.Wrap(),
}
for _, p := range pubs {
_, ok := p.PubKeyInner.(PubKey)
@ -130,10 +130,10 @@ func TestWrapping(t *testing.T) {
}
sigs := []Signature{
WrapSignature(nil),
WrapSignature(sig),
WrapSignature(WrapSignature(WrapSignature(WrapSignature(sig)))),
WrapSignature(Signature{Signature{Signature{sig}}}),
Signature{nil},
sig.Wrap(),
sig.Wrap().Wrap().Wrap(),
Signature{Signature{Signature{sig}}}.Wrap(),
}
for _, s := range sigs {
_, ok := s.SignatureInner.(Signature)


Loading…
Cancel
Save