1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
  | 
diff --git a/spectre.go b/spectre.go
index 4f5ba3d5e7c8fb5e803c12093d7390c9ce25f5e1..b640fbf763656b6d73d3ee5ba25a06f45c93f7cc 100644
--- a/spectre.go
+++ b/spectre.go
@@ -1,12 +1,5 @@
 package spectre
 
-import (
-	"crypto/hmac"
-	"crypto/sha256"
-	"golang.org/x/crypto/scrypt"
-	"strings"
-)
-
 // Spectre is a spectre client
 type Spectre struct {
 	name   string
@@ -26,7 +19,7 @@ 	}
 	for _, opt := range opts {
 		opt(s)
 	}
-	s.key, err = s.userKey()
+	s.key, err = userKey(s.name, s.secret, s.scoper)
 	return
 }
 
@@ -40,75 +33,9 @@ 		s.scoper = scoper
 	}
 }
 
-func (s *Spectre) userKey() ([]byte, error) {
-	nameBytes := []byte(s.name)
-	secretBytes := []byte(s.secret)
-	keyScope := []byte(s.scoper.Scope(Authentication))
-
-	nameBytesLen := len(nameBytes)
-	keySalt := append(keyScope,
-		byte(nameBytesLen>>24),
-		byte(nameBytesLen>>16),
-		byte(nameBytesLen>>8),
-		byte(nameBytesLen),
-	)
-	keySalt = append(keySalt, nameBytes...)
-
-	return scrypt.Key(secretBytes, keySalt, 32768, 8, 2, 64)
-}
-
-func (s *Spectre) siteKey(name string, counter int, scope Scope) []byte {
-	nameBytes := []byte(name)
-	scopeBytes := []byte(s.scoper.Scope(scope))
-
-	nameBytesLen := len(nameBytes)
-	keySalt := append(scopeBytes,
-		byte(nameBytesLen>>24),
-		byte(nameBytesLen>>16),
-		byte(nameBytesLen>>8),
-		byte(nameBytesLen),
-	)
-	keySalt = append(keySalt, nameBytes...)
-	keySalt = append(keySalt,
-		byte(counter>>24),
-		byte(counter>>16),
-		byte(counter>>8),
-		byte(counter),
-	)
-
-	sign := hmac.New(sha256.New, s.key)
-	sign.Write(keySalt)
-
-	return sign.Sum(nil)
-}
-
 // Site returns a site password based on Options
 func (s *Spectre) Site(siteName string, opts ...SiteOption) string {
-	siteOpts := &options{
-		template: "",
-		counter:  1,
-		scope:    Authentication,
-	}
-	for _, opt := range opts {
-		opt(siteOpts)
-	}
-
-	if siteOpts.template == "" {
-		siteOpts.template = siteOpts.scope.DefaultTemplate()
-	}
-
-	siteKey := s.siteKey(siteName, siteOpts.counter, siteOpts.scope)
-
-	templateSet := templates[siteOpts.template]
-	template := templateSet[int(siteKey[0])%len(templateSet)]
-
-	var out strings.Builder
-	for idx, b := range template {
-		chars := characters[string(b)]
-		char := chars[int(siteKey[idx+1])%len(chars)]
-		out.WriteByte(char)
-	}
-	return out.String()
+	return site(s.key, s.scoper, siteName, opts...)
 }
 
 type options struct {
  |