code.pfad.fr/gohmekit@v0.2.1/pairing/crypto/srp.go (about) 1 package crypto 2 3 import ( 4 "crypto/sha512" 5 6 "github.com/tadglines/go-pkgs/crypto/srp" 7 ) 8 9 type SRPSession struct { 10 session *srp.ServerSession 11 } 12 13 // keyDerivativeFuncRFC2945 returns the SRP-6a key derivative function which does 14 // x = H(s | H(I | ":" | P)) 15 // 16 // taken from github.com/brutella/hc@v1.2.4/hap/pair/srp.go. 17 func keyDerivativeFuncRFC2945(h srp.HashFunc, username []byte) srp.KeyDerivationFunc { 18 return func(salt, pin []byte) []byte { 19 h := h() 20 h.Write(username) 21 h.Write([]byte(":")) 22 h.Write(pin) 23 t2 := h.Sum(nil) 24 h.Reset() 25 h.Write(salt) 26 h.Write(t2) 27 return h.Sum(nil) 28 } 29 } 30 31 func NewSRPSession(pin []byte) (*SRPSession, []byte, error) { 32 username := []byte("Pair-Setup") 33 srp, err := srp.NewSRP("rfc5054.3072", sha512.New, keyDerivativeFuncRFC2945(sha512.New, username)) 34 if err != nil { 35 return nil, nil, err 36 } 37 38 srp.SaltLength = 16 39 salt, v, err := srp.ComputeVerifier(pin) 40 if err != nil { 41 return nil, nil, err 42 } 43 44 return &SRPSession{srp.NewServerSession(username, salt, v)}, salt, nil 45 } 46 47 func (s SRPSession) PublicKey() []byte { 48 return s.session.GetB() 49 } 50 51 func (s SRPSession) PairSetupSharedSecret(otherPublicKey []byte) ([]byte, error) { 52 return s.session.ComputeKey(otherPublicKey) 53 } 54 55 func (s SRPSession) ExchangeProof(clientProof []byte) ([]byte, bool) { 56 if !s.session.VerifyClientAuthenticator(clientProof) { 57 return nil, false 58 } 59 return s.session.ComputeAuthenticator(clientProof), true 60 }