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  }