/
kex2_secret.go
63 lines (50 loc) · 1.64 KB
/
kex2_secret.go
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
// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.
package libkb
import (
"strings"
"github.com/keybase/client/go/kex2"
"golang.org/x/crypto/scrypt"
)
const kexPhraseVersion = "four"
type Kex2Secret struct {
phrase string
secret kex2.Secret
}
func NewKex2Secret(mobile bool) (*Kex2Secret, error) {
words, err := SecWordList(Kex2PhraseEntropy)
if err != nil {
return nil, err
}
phrase := strings.Join(words, " ")
// If we are provisioning a mobile device, we want to use an easier to compute secret. In order to
// communicate that to the two devices involved in kex without breaking the existing protocol,
// we have added an extra word that is not in the dictionary. Up to date clients can see this
// word and use the lighter version of scrypt.
if mobile {
phrase += " " + kexPhraseVersion
}
return NewKex2SecretFromPhrase(phrase)
}
func NewKex2SecretFromPhrase(phrase string) (*Kex2Secret, error) {
scryptCost := Kex2ScryptCost
// Detect if the phrase contains the magic word that indicates that we are provisioning a mobile
// device. If so, then we use the lighter cost version of scrypt.
words := strings.Split(phrase, " ")
if len(words) > 0 && words[len(words)-1] == kexPhraseVersion {
scryptCost = Kex2ScryptLiteCost
}
key, err := scrypt.Key([]byte(phrase), nil, scryptCost, Kex2ScryptR, Kex2ScryptP, Kex2ScryptKeylen)
if err != nil {
return nil, err
}
res := &Kex2Secret{phrase: phrase}
copy(res.secret[:], key)
return res, nil
}
func (s *Kex2Secret) Secret() kex2.Secret {
return s.secret
}
func (s *Kex2Secret) Phrase() string {
return s.phrase
}