func ToECDSAPub(pub []byte) *ecdsa.PublicKey { if len(pub) == 0 { return nil } x, y := elliptic.Unmarshal(secp256k1.S256(), pub) return &ecdsa.PublicKey{secp256k1.S256(), x, y} }
func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) { s, err := Ecrecover(hash, sig) if err != nil { return nil, err } x, y := elliptic.Unmarshal(secp256k1.S256(), s) return &ecdsa.PublicKey{secp256k1.S256(), x, y}, nil }
// New methods using proper ecdsa keys from the stdlib func ToECDSA(prv []byte) *ecdsa.PrivateKey { if len(prv) == 0 { return nil } priv := new(ecdsa.PrivateKey) priv.PublicKey.Curve = secp256k1.S256() priv.D = common.BigD(prv) priv.PublicKey.X, priv.PublicKey.Y = secp256k1.S256().ScalarBaseMult(prv) return priv }
func decodeAuthMsg(prv *ecdsa.PrivateKey, token []byte, auth []byte) (*encHandshake, error) { var err error h := new(encHandshake) // generate random keypair for session h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, secp256k1.S256(), nil) if err != nil { return nil, err } // generate random nonce h.respNonce = make([]byte, shaLen) if _, err = rand.Read(h.respNonce); err != nil { return nil, err } msg, err := crypto.Decrypt(prv, auth) if err != nil { return nil, fmt.Errorf("could not decrypt auth message (%v)", err) } // decode message parameters // signature || sha3(ecdhe-random-pubk) || pubk || nonce || token-flag h.initNonce = msg[authMsgLen-shaLen-1 : authMsgLen-1] copy(h.remoteID[:], msg[sigLen+shaLen:sigLen+shaLen+pubLen]) rpub, err := h.remoteID.Pubkey() if err != nil { return nil, fmt.Errorf("bad remoteID: %#v", err) } h.remotePub = ecies.ImportECDSAPublic(rpub) // recover remote random pubkey from signed message. if token == nil { // TODO: it is an error if the initiator has a token and we don't. check that. // no session token means we need to generate shared secret. // ecies shared secret is used as initial session token for new peers. // generate shared key from prv and remote pubkey. if token, err = h.ecdhShared(prv); err != nil { return nil, err } } signedMsg := xor(token, h.initNonce) remoteRandomPub, err := secp256k1.RecoverPubkey(signedMsg, msg[:sigLen]) if err != nil { return nil, err } // validate the sha3 of recovered pubkey remoteRandomPubMAC := msg[sigLen : sigLen+shaLen] shaRemoteRandomPub := crypto.Sha3(remoteRandomPub[1:]) if !bytes.Equal(remoteRandomPubMAC, shaRemoteRandomPub) { return nil, fmt.Errorf("sha3 of recovered ephemeral pubkey does not match checksum in auth message") } h.remoteRandomPub, _ = importPublicKey(remoteRandomPub) return h, nil }
// Pubkey returns the public key represented by the node ID. // It returns an error if the ID is not a point on the curve. func (id NodeID) Pubkey() (*ecdsa.PublicKey, error) { p := &ecdsa.PublicKey{Curve: secp256k1.S256(), X: new(big.Int), Y: new(big.Int)} half := len(id) / 2 p.X.SetBytes(id[:half]) p.Y.SetBytes(id[half:]) if !p.Curve.IsOnCurve(p.X, p.Y) { return nil, errors.New("id is invalid secp256k1 curve point") } return p, nil }
func namedCurveFromOID(curve secgNamedCurve) elliptic.Curve { switch { case curve.Equal(secgNamedCurveS256): return secp256k1.S256() case curve.Equal(secgNamedCurveP256): return elliptic.P256() case curve.Equal(secgNamedCurveP384): return elliptic.P384() case curve.Equal(secgNamedCurveP521): return elliptic.P521() } return nil }
func oidFromNamedCurve(curve elliptic.Curve) (secgNamedCurve, bool) { switch curve { case elliptic.P256(): return secgNamedCurveP256, true case elliptic.P384(): return secgNamedCurveP384, true case elliptic.P521(): return secgNamedCurveP521, true case secp256k1.S256(): return secgNamedCurveS256, true } return nil, false }
func NewKey(rand io.Reader) *Key { randBytes := make([]byte, 64) _, err := rand.Read(randBytes) if err != nil { panic("key generation: could not read from random source: " + err.Error()) } reader := bytes.NewReader(randBytes) privateKeyECDSA, err := ecdsa.GenerateKey(secp256k1.S256(), reader) if err != nil { panic("key generation: ecdsa.GenerateKey failed: " + err.Error()) } return NewKeyFromECDSA(privateKeyECDSA) }
// generate key whose address fits into < 155 bits so it can fit into // the Direct ICAP spec. for simplicity and easier compatibility with // other libs, we retry until the first byte is 0. func NewKeyForDirectICAP(rand io.Reader) *Key { randBytes := make([]byte, 64) _, err := rand.Read(randBytes) if err != nil { panic("key generation: could not read from random source: " + err.Error()) } reader := bytes.NewReader(randBytes) privateKeyECDSA, err := ecdsa.GenerateKey(secp256k1.S256(), reader) if err != nil { panic("key generation: ecdsa.GenerateKey failed: " + err.Error()) } key := NewKeyFromECDSA(privateKeyECDSA) if !strings.HasPrefix(key.Address.Hex(), "0x00") { return NewKeyForDirectICAP(rand) } return key }
func newInitiatorHandshake(remoteID discover.NodeID) (*encHandshake, error) { rpub, err := remoteID.Pubkey() if err != nil { return nil, fmt.Errorf("bad remoteID: %v", err) } // generate random initiator nonce n := make([]byte, shaLen) if _, err := rand.Read(n); err != nil { return nil, err } // generate random keypair to use for signing randpriv, err := ecies.GenerateKey(rand.Reader, secp256k1.S256(), nil) if err != nil { return nil, err } h := &encHandshake{ initiator: true, remoteID: remoteID, remotePub: ecies.ImportECDSAPublic(rpub), initNonce: n, randomPrivKey: randpriv, } return h, nil }
import ( "crypto" "crypto/aes" "crypto/cipher" "crypto/elliptic" "crypto/sha256" "crypto/sha512" "fmt" "hash" "github.com/gophergala2016/etherapis/etherapis/Godeps/_workspace/src/github.com/ethereum/go-ethereum/crypto/secp256k1" ) var ( DefaultCurve = secp256k1.S256() ErrUnsupportedECDHAlgorithm = fmt.Errorf("ecies: unsupported ECDH algorithm") ErrUnsupportedECIESParameters = fmt.Errorf("ecies: unsupported ECIES parameters") ) type ECIESParams struct { Hash func() hash.Hash // hash function hashAlgo crypto.Hash Cipher func([]byte) (cipher.Block, error) // symmetric cipher BlockSize int // block size of symmetric cipher KeyLen int // length of symmetric key } // Standard ECIES parameters: // * ECIES using AES128 and HMAC-SHA-256-16 // * ECIES using AES256 and HMAC-SHA-256-32
func GenerateKey() (*ecdsa.PrivateKey, error) { return ecdsa.GenerateKey(secp256k1.S256(), rand.Reader) }
func FromECDSAPub(pub *ecdsa.PublicKey) []byte { if pub == nil || pub.X == nil || pub.Y == nil { return nil } return elliptic.Marshal(secp256k1.S256(), pub.X, pub.Y) }