// newManagedAddress returns a new managed address based on the passed account, // private key, and whether or not the public key is compressed. The managed // address will have access to the private and public keys. func newManagedAddress(m *Manager, account uint32, privKey *btcec.PrivateKey, compressed bool) (*managedAddress, error) { // Encrypt the private key. // // NOTE: The privKeyBytes here are set into the managed address which // are cleared when locked, so they aren't cleared here. privKeyBytes := privKey.Serialize() privKeyEncrypted, err := m.cryptoKeyPriv.Encrypt(privKeyBytes) if err != nil { str := "failed to encrypt private key" return nil, managerError(ErrCrypto, str, err) } // Leverage the code to create a managed address without a private key // and then add the private key to it. ecPubKey := (*btcec.PublicKey)(&privKey.PublicKey) managedAddr, err := newManagedAddressWithoutPrivKey(m, account, ecPubKey, compressed) if err != nil { return nil, err } managedAddr.privKeyEncrypted = privKeyEncrypted managedAddr.privKeyCT = privKeyBytes return managedAddr, nil }
func generateSinFromKey(key *btcec.PrivateKey) string { pub := key.PubKey() comp := pub.SerializeCompressed() hexb := hex.EncodeToString(comp) stx := generateSinFromPublicKey(hexb) return stx }
// keyToAddr maps the passed private to corresponding p2pkh address. func keyToAddr(key *btcec.PrivateKey, net *chaincfg.Params) (btcutil.Address, error) { serializedKey := key.PubKey().SerializeCompressed() pubKeyAddr, err := btcutil.NewAddressPubKey(serializedKey, net) if err != nil { return nil, err } return pubKeyAddr.AddressPubKeyHash(), nil }
// authPKH... func (c *LNDConn) authPKH( myId *btcec.PrivateKey, theirPKH, localEphPubBytes []byte) error { if c.Authed { return fmt.Errorf("%s already authed", c.RemotePub) } if len(theirPKH) != 20 { return fmt.Errorf("remote PKH must be 20 bytes, got %d", len(theirPKH)) } // Send 53 bytes: our pubkey, and the remote's pubkey hash. var greetingMsg [53]byte copy(greetingMsg[:33], myId.PubKey().SerializeCompressed()) copy(greetingMsg[:33], theirPKH) if _, err := c.Conn.Write(greetingMsg[:]); err != nil { return err } // Wait for their response. // TODO(tadge): add timeout here // * NOTE(roasbeef): read timeout should be set on the underlying // net.Conn. resp := make([]byte, 53) if _, err := c.Conn.Read(resp); err != nil { return err } // Parse their long-term public key, and generate the DH proof. theirPub, err := btcec.ParsePubKey(resp[:33], btcec.S256()) if err != nil { return err } idDH := fastsha256.Sum256(btcec.GenerateSharedSecret(myId, theirPub)) fmt.Printf("made idDH %x\n", idDH) theirDHproof := btcutil.Hash160(append(localEphPubBytes, idDH[:]...)) // Verify that their DH proof matches the one we just generated. if bytes.Equal(resp[33:], theirDHproof) == false { return fmt.Errorf("Invalid DH proof %x", theirDHproof) } // If their DH proof checks out, then send our own. myDHproof := btcutil.Hash160(append(c.RemotePub.SerializeCompressed(), idDH[:]...)) if _, err = c.Conn.Write(myDHproof); err != nil { return err } // Proof sent, auth complete. c.RemotePub = theirPub theirAdr := btcutil.Hash160(theirPub.SerializeCompressed()) copy(c.RemoteLNId[:], theirAdr[:16]) c.Authed = true return nil }
// RawTxInSignature returns the serialized ECDSA signature for the input idx of // the given transaction, with hashType appended to it. func RawTxInSignature(tx *wire.MsgTx, idx int, subScript []byte, hashType SigHashType, key *btcec.PrivateKey) ([]byte, error) { parsedScript, err := parseScript(subScript) if err != nil { return nil, fmt.Errorf("cannot parse output script: %v", err) } hash := calcSignatureHash(parsedScript, hashType, tx, idx) signature, err := key.Sign(hash) if err != nil { return nil, fmt.Errorf("cannot sign tx input: %s", err) } return append(signature.Serialize(), byte(hashType)), nil }
func GeneratePemFromKey(priv *btcec.PrivateKey) string { pub := priv.PubKey() ecd := pub.ToECDSA() oid := asn1.ObjectIdentifier{1, 3, 132, 0, 10} curve := btcec.S256() der, _ := asn1.Marshal(ecPrivateKey{ Version: 1, PrivateKey: priv.D.Bytes(), NamedCurveOID: oid, PublicKey: asn1.BitString{Bytes: elliptic.Marshal(curve, ecd.X, ecd.Y)}, }) blck := pem.Block{Type: "EC PRIVATE KEY", Bytes: der} pm := pem.EncodeToMemory(&blck) return string(pm) }
// NewSphinxNode... func NewSphinxNode(nodeKey *btcec.PrivateKey, net *chaincfg.Params) *SphinxNode { var nodeID [securityParameter]byte copy(nodeID[:], btcutil.Hash160(nodeKey.PubKey().SerializeCompressed())) // Safe to ignore the error here, nodeID is 20 bytes. nodeAddr, _ := btcutil.NewAddressPubKeyHash(nodeID[:], net) return &SphinxNode{ nodeID: nodeID, nodeAddr: nodeAddr, lnKey: nodeKey, // TODO(roasbeef): replace instead with bloom filter? // * https://moderncrypto.org/mail-archive/messaging/2015/001911.html seenSecrets: make(map[[sharedSecretSize]byte]struct{}), } }
// authPubKey... func (c *LNDConn) authPubKey( myId *btcec.PrivateKey, remotePubBytes, localEphPubBytes []byte) error { if c.Authed { return fmt.Errorf("%s already authed", c.RemotePub) } // Since we already know their public key, we can immediately generate // the DH proof without an additional round-trip. theirPub, err := btcec.ParsePubKey(remotePubBytes, btcec.S256()) if err != nil { return err } theirPKH := btcutil.Hash160(remotePubBytes) idDH := fastsha256.Sum256(btcec.GenerateSharedSecret(myId, theirPub)) myDHproof := btcutil.Hash160(append(c.RemotePub.SerializeCompressed(), idDH[:]...)) // Send over the 73 byte authentication message: my pubkey, their // pubkey hash, DH proof. var authMsg [73]byte copy(authMsg[:33], myId.PubKey().SerializeCompressed()) copy(authMsg[33:], theirPKH) copy(authMsg[53:], myDHproof) if _, err = c.Conn.Write(authMsg[:]); err != nil { return nil } // Await, their response. They should send only the 20-byte DH proof. resp := make([]byte, 20) _, err = c.Conn.Read(resp) if err != nil { return err } // Verify that their proof matches our locally computed version. theirDHproof := btcutil.Hash160(append(localEphPubBytes, idDH[:]...)) if bytes.Equal(resp, theirDHproof) == false { return fmt.Errorf("invalid DH proof %x", theirDHproof) } // Proof checks out, auth complete. c.RemotePub = theirPub theirAdr := btcutil.Hash160(theirPub.SerializeCompressed()) copy(c.RemoteLNId[:], theirAdr[:16]) c.Authed = true return nil }