// NewSession sets up a new session. The Last field should be sent // to the client. The returned public key should be sent to the // user for generating a shared MAC key. The authenticator should ensure // some mechanism for expiring sessions exists. func NewSession(pub []byte) (*Authenticator, []byte, error) { next := util.RandBytes(sessionLength) if next == nil { return nil, nil, errors.New("auth: PRNG failure") } ephemeral, err := public.GenerateKey() if err != nil || !ephemeral.Valid() { return nil, nil, errors.New("auth: failed to set up session key") } // Validated that the key was correct previously. ephemeralPublic, _ := public.MarshalPublic(ephemeral.PublicKey) peer, err := public.UnmarshalPublic(pub) if err != nil { return nil, nil, err } shared := public.KeyExchange(ephemeral, peer) return &Authenticator{ Type: TypeSession, Last: hex.EncodeToString(next), Secret: shared, }, ephemeralPublic, nil }
// KeySession sets up a new session from the user's private key and the // server's ephemeral public key. func KeySession(priv, pub []byte) (*Session, bool) { privKey, err := public.UnmarshalPrivate(priv) if err != nil { return nil, false } defer privKey.Zero() pubKey, err := public.UnmarshalPublic(pub) if err != nil { return nil, false } shared := public.KeyExchange(privKey, pubKey) return &Session{shared: shared}, true }
func testCreateOTP(t *testing.T) string { if sessionAuth == nil { t.Fatal("auth: session not established") } last, err := hex.DecodeString(sessionAuth.Last) if err != nil { t.Fatalf("%v", err) } sessionPublic, err := public.UnmarshalPublic(sessionPub) if err != nil { t.Fatalf("%v", err) } shared := public.KeyExchange(peerPrivate, sessionPublic) h := hmac.New(sha256.New, shared) h.Write(last) last = append(last, h.Sum(nil)...) return hex.EncodeToString(last) }