func GenerateSessionKeys() (pub, priv []byte, err error) { pub, priv, err = dhgroup14.GenerateKeyPair(rand.Reader) if err != nil { return } return }
// Handshake runs handshake if it has not yet been run. Most users of this // package need not call Handshake explicitly: the first Read or Write will // call it automatically. func (c *Conn) Handshake() error { c.handshakeMutex.Lock() defer c.handshakeMutex.Unlock() if c.handshakePerformed { return nil } var nonces [32 + 32 + dhgroup14.SharedKeySize]byte if _, err := io.ReadFull(rand.Reader, nonces[:64]); err != nil { return err } nonceC := nonces[0:32] nonceS := nonces[32:64] // Send and receive random nonces. if c.isClient { if err := c.sendBytes(nonceC); err != nil { return err } if err := c.receiveBytes(nonceS); err != nil { return err } } else { if err := c.receiveBytes(nonceC); err != nil { return err } if err := c.sendBytes(nonceS); err != nil { return err } } // Generate dhmac_C and dhmac_S. dk1 := pbkdf2.Key(c.secretKey, nonces[:64], 1, 64, sha256.New) dhmacC := dk1[0:32] dhmacS := dk1[32:64] var myDHMac, theirDHMac []byte if c.isClient { myDHMac = dhmacC theirDHMac = dhmacS } else { myDHMac = dhmacS theirDHMac = dhmacC } // Generate DH key pair. myPublicKey, myPrivateKey, err := dhgroup14.GenerateKeyPair(rand.Reader) if err != nil { return err } // Prepare my public key for sending. var myAuthPublicKey [256 + 32]byte copy(myAuthPublicKey[:], myPublicKey) // Authenticate my public key. h := hmac.New(sha256.New, myDHMac) h.Write(myAuthPublicKey[0:256]) h.Sum(myAuthPublicKey[256:256]) var theirAuthPublicKey [256 + 32]byte if c.isClient { // If client, send our authenticated public key. if err := c.sendBytes(myAuthPublicKey[:]); err != nil { return err } } // Receive their authenticated public key. if err := c.receiveBytes(theirAuthPublicKey[:]); err != nil { return err } // Check their public key authenticator. var sum [32]byte h = hmac.New(sha256.New, theirDHMac) h.Write(theirAuthPublicKey[0:256]) if subtle.ConstantTimeCompare(h.Sum(sum[:0]), theirAuthPublicKey[256:]) != 1 { return errors.New("spipe: authentication failed") } if !c.isClient { // If server, send our authenticated public key. if err := c.sendBytes(myAuthPublicKey[:]); err != nil { return err } } // Calculate DH shared key. theirPublicKey := theirAuthPublicKey[:256] dhSharedKey, err := dhgroup14.SharedKey(rand.Reader, theirPublicKey, myPrivateKey) if err != nil { return err } // Derive final encryption and MAC keys. copy(nonces[64:], dhSharedKey) dk2 := pbkdf2.Key(c.secretKey, nonces[:], 1, 128, sha256.New) eC, hC, eS, hS := dk2[0:32], dk2[32:64], dk2[64:96], dk2[96:128] // Set reader and writer depending on our role. if c.isClient { c.w = newEncryptor(c.conn, eC, hC) c.r = newDecryptor(c.conn, eS, hS) } else { c.w = newEncryptor(c.conn, eS, hS) c.r = newDecryptor(c.conn, eC, hC) } c.handshakePerformed = true return nil }