package crypto
import (
"bytes"
"crypto/ed25519"
"crypto/subtle"
"errors"
"fmt"
"io"
pb "github.com/libp2p/go-libp2p/core/crypto/pb"
"github.com/libp2p/go-libp2p/core/internal/catch"
)
type Ed25519PrivateKey struct {
k ed25519 .PrivateKey
}
type Ed25519PublicKey struct {
k ed25519 .PublicKey
}
func GenerateEd25519Key (src io .Reader ) (PrivKey , PubKey , error ) {
pub , priv , err := ed25519 .GenerateKey (src )
if err != nil {
return nil , nil , err
}
return &Ed25519PrivateKey {
k : priv ,
},
&Ed25519PublicKey {
k : pub ,
},
nil
}
func (k *Ed25519PrivateKey ) Type () pb .KeyType {
return pb .KeyType_Ed25519
}
func (k *Ed25519PrivateKey ) Raw () ([]byte , error ) {
buf := make ([]byte , len (k .k ))
copy (buf , k .k )
return buf , nil
}
func (k *Ed25519PrivateKey ) pubKeyBytes () []byte {
return k .k [ed25519 .PrivateKeySize -ed25519 .PublicKeySize :]
}
func (k *Ed25519PrivateKey ) Equals (o Key ) bool {
edk , ok := o .(*Ed25519PrivateKey )
if !ok {
return basicEquals (k , o )
}
return subtle .ConstantTimeCompare (k .k , edk .k ) == 1
}
func (k *Ed25519PrivateKey ) GetPublic () PubKey {
return &Ed25519PublicKey {k : k .pubKeyBytes ()}
}
func (k *Ed25519PrivateKey ) Sign (msg []byte ) (res []byte , err error ) {
defer func () { catch .HandlePanic (recover (), &err , "ed15519 signing" ) }()
return ed25519 .Sign (k .k , msg ), nil
}
func (k *Ed25519PublicKey ) Type () pb .KeyType {
return pb .KeyType_Ed25519
}
func (k *Ed25519PublicKey ) Raw () ([]byte , error ) {
return k .k , nil
}
func (k *Ed25519PublicKey ) Equals (o Key ) bool {
edk , ok := o .(*Ed25519PublicKey )
if !ok {
return basicEquals (k , o )
}
return bytes .Equal (k .k , edk .k )
}
func (k *Ed25519PublicKey ) Verify (data []byte , sig []byte ) (success bool , err error ) {
defer func () {
catch .HandlePanic (recover (), &err , "ed15519 signature verification" )
if err != nil {
success = false
}
}()
return ed25519 .Verify (k .k , data , sig ), nil
}
func UnmarshalEd25519PublicKey (data []byte ) (PubKey , error ) {
if len (data ) != 32 {
return nil , errors .New ("expect ed25519 public key data size to be 32" )
}
return &Ed25519PublicKey {
k : ed25519 .PublicKey (data ),
}, nil
}
func UnmarshalEd25519PrivateKey (data []byte ) (PrivKey , error ) {
switch len (data ) {
case ed25519 .PrivateKeySize + ed25519 .PublicKeySize :
redundantPk := data [ed25519 .PrivateKeySize :]
pk := data [ed25519 .PrivateKeySize -ed25519 .PublicKeySize : ed25519 .PrivateKeySize ]
if subtle .ConstantTimeCompare (pk , redundantPk ) == 0 {
return nil , errors .New ("expected redundant ed25519 public key to be redundant" )
}
newKey := make ([]byte , ed25519 .PrivateKeySize )
copy (newKey , data [:ed25519 .PrivateKeySize ])
data = newKey
case ed25519 .PrivateKeySize :
default :
return nil , fmt .Errorf (
"expected ed25519 data size to be %d or %d, got %d" ,
ed25519 .PrivateKeySize ,
ed25519 .PrivateKeySize +ed25519 .PublicKeySize ,
len (data ),
)
}
return &Ed25519PrivateKey {
k : ed25519 .PrivateKey (data ),
}, nil
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .