func createAEADWorker(cipherType uint16, key []byte) (cipher.AEAD, error) { switch cipherType { case aeadCipherAES: block, err := aes.NewCipher(key) if err != nil { return nil, err } return cipher.NewGCM(block) case aeadCipherChaCha: return chacha.New(key) } return nil, fmt.Errorf("No such cipher type.") }
// createCipherConn.... func (l *Listener) createCipherConn(lnConn *LNDConn) (*btcec.PrivateKey, error) { var err error var theirEphPubBytes []byte // First, read and deserialize their ephemeral public key. theirEphPubBytes, err = readClear(lnConn.Conn) if err != nil { return nil, err } if len(theirEphPubBytes) != 33 { return nil, fmt.Errorf("Got invalid %d byte eph pubkey %x\n", len(theirEphPubBytes), theirEphPubBytes) } theirEphPub, err := btcec.ParsePubKey(theirEphPubBytes, btcec.S256()) if err != nil { return nil, err } // Once we've parsed and verified their key, generate, and send own // ephemeral key pair for use within this session. myEph, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { return nil, err } if _, err := writeClear(lnConn.Conn, myEph.PubKey().SerializeCompressed()); err != nil { return nil, err } // Now that we have both keys, do non-interactive diffie with ephemeral // pubkeys, sha256 for good luck. sessionKey := fastsha256.Sum256( btcec.GenerateSharedSecret(myEph, theirEphPub), ) lnConn.chachaStream, err = chacha20poly1305.New(sessionKey[:]) // display private key for debug only fmt.Printf("made session key %x\n", sessionKey) lnConn.remoteNonceInt = 1 << 63 lnConn.myNonceInt = 0 lnConn.RemotePub = theirEphPub lnConn.Authed = false return myEph, nil }
func main() { key := readSecretKey(chacha20poly1305.KeySize) // must be 256 bits long key = []byte("a very very very very secret key") c, err := chacha20poly1305.New(key) fmt.Print(c) if err != nil { panic(err) } nonce := readRandomNonce(c.NonceSize()) // must be generated by crypto/rand fmt.Println(nonce) plaintext := []byte("wwz") data := []byte("whoah yeah") ciphertext := c.Seal(nil, nonce, plaintext, data) opentext, _ := c.Open(nil, nonce, ciphertext, data) fmt.Printf("%x\n", ciphertext) fmt.Printf("%s\n", opentext) }
// Dial... func (c *Conn) Dial(address string, remoteId []byte) error { var err error if c.conn != nil { return fmt.Errorf("connection already established") } // Before dialing out to the remote host, verify that `remoteId` is either // a pubkey or a pubkey hash. if len(remoteId) != 33 && len(remoteId) != 20 { return fmt.Errorf("must supply either remote pubkey or " + "pubkey hash") } // First, open the TCP connection itself. c.conn, err = net.Dial("tcp", address) if err != nil { return err } // Calc remote LNId; need this for creating pbx connections just because // LNid is in the struct does not mean it's authed! if len(remoteId) == 20 { copy(c.remoteLNId[:], remoteId[:16]) } else { theirAdr := btcutil.Hash160(remoteId) copy(c.remoteLNId[:], theirAdr[:16]) } // Make up an ephemeral keypair for this session. ourEphemeralPriv, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { return err } ourEphemeralPub := ourEphemeralPriv.PubKey() // Sned 1. Send my ephemeral pubkey. Can add version bits. if _, err = writeClear(c.conn, ourEphemeralPub.SerializeCompressed()); err != nil { return err } // Read, then deserialize their ephemeral public key. theirEphPubBytes, err := readClear(c.conn) if err != nil { return err } theirEphPub, err := btcec.ParsePubKey(theirEphPubBytes, btcec.S256()) if err != nil { return err } // Do non-interactive diffie with ephemeral pubkeys. Sha256 for good // luck. sessionKey := fastsha256.Sum256( btcec.GenerateSharedSecret(ourEphemeralPriv, theirEphPub), ) // Now that we've derive the session key, we can initialize the // chacha20poly1305 AEAD instance which will be used for the remainder of // the session. c.chachaStream, err = chacha20poly1305.New(sessionKey[:]) if err != nil { return err } // display private key for debug only fmt.Printf("made session key %x\n", sessionKey) c.myNonceInt = 1 << 63 c.remoteNonceInt = 0 c.remotePub = theirEphPub c.authed = false // Session is now open and confidential but not yet authenticated... // So auth! if len(remoteId) == 20 { // Only know pubkey hash (20 bytes). err = c.authPKH(remoteId, ourEphemeralPub.SerializeCompressed()) } else { // Must be 33 byte pubkey. err = c.authPubKey(remoteId, ourEphemeralPub.SerializeCompressed()) } if err != nil { return err } return nil }