diff --git a/peer/cwtch_peer.go b/peer/cwtch_peer.go index 49f3624..d84cc2c 100644 --- a/peer/cwtch_peer.go +++ b/peer/cwtch_peer.go @@ -36,7 +36,7 @@ type cwtchPeer struct { Log chan string `json:"-"` connectionsManager *connections.Manager profilefile string - password [32]byte + key [32]byte salt [128]byte } @@ -74,44 +74,45 @@ type CwtchPeerInterface interface { Shutdown() } -// CreateKey derives a key and salt for use in encrypting the Profile -func CreateKey(key string) ([32]byte, [128]byte) { +// createKey derives a key and salt for use in encrypting cwtchPeers +func createKey(password string) ([32]byte, [128]byte) { var salt [128]byte if _, err := io.ReadFull(rand.Reader, salt[:]); err != nil { panic(err) } - dk := pbkdf2.Key([]byte(key), salt[:], 4096, 32, sha3.New512) + dk := pbkdf2.Key([]byte(password), salt[:], 4096, 32, sha3.New512) var dkr [32]byte copy(dkr[:], dk) return dkr, salt } -//EncryptMessage takes a message and encrypts the message under the group key. -func EncryptProfile(p *cwtchPeer, password [32]byte) []byte { +//encryptProfile encrypts the cwtchPeer via the specified key. +func encryptProfile(p *cwtchPeer, key [32]byte) []byte { var nonce [24]byte + if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil { panic(err) } - //copy Peer struct, then remove password and save the copy + + //copy the struct, then remove the key and salt before saving the copy cpc := &cwtchPeer{} deepcopier.Copy(p).To(cpc) - var blankpass [32]byte + var blankkey [32]byte var blanksalt [128]byte - cpc.password = blankpass + cpc.key = blankkey cpc.salt = blanksalt bytes, _ := json.Marshal(cpc) - - encrypted := secretbox.Seal(nonce[:], []byte(bytes), &nonce, &password) + encrypted := secretbox.Seal(nonce[:], []byte(bytes), &nonce, &key) return encrypted } -//EncryptMessage takes a message and encrypts the message under the group key. -func DecryptProfile(ciphertext []byte, password [32]byte) (error, *cwtchPeer) { +//decryptProfile decrypts the passed ciphertext into a cwtchPeer via the specified key. +func decryptProfile(ciphertext []byte, key [32]byte) (error, *cwtchPeer) { var decryptNonce [24]byte copy(decryptNonce[:], ciphertext[:24]) - decrypted, ok := secretbox.Open(nil, ciphertext[24:], &decryptNonce, &password) + decrypted, ok := secretbox.Open(nil, ciphertext[24:], &decryptNonce, &key) if ok { cp := &cwtchPeer{} err := json.Unmarshal(decrypted, &cp) @@ -149,8 +150,8 @@ func NewCwtchPeer(name string, password string) CwtchPeerInterface { cp := new(cwtchPeer) cp.Profile = model.GenerateNewProfile(name) cp.setup() - pass, salt := CreateKey(password) - cp.password = pass + key, salt := createKey(password) + cp.key = key cp.salt = salt return cp } @@ -158,7 +159,9 @@ func NewCwtchPeer(name string, password string) CwtchPeerInterface { // Save saves the cwtchPeer profile state to a file. func (cp *cwtchPeer) Save(profilefile string) error { cp.mutex.Lock() - encryptedbytes := EncryptProfile(cp, cp.password) + encryptedbytes := encryptProfile(cp, cp.key) + + // the salt for the derived key is appended to the front of the file encryptedbytes = append(cp.salt[:], encryptedbytes...) err := ioutil.WriteFile(profilefile, encryptedbytes, 0600) cp.profilefile = profilefile @@ -170,18 +173,23 @@ func (cp *cwtchPeer) Save(profilefile string) error { func LoadCwtchPeer(profilefile string, password string) (CwtchPeerInterface, error) { encryptedbytes, _ := ioutil.ReadFile(profilefile) - //get the salt - salt, encryptedbytes := encryptedbytes[0:128], encryptedbytes[128:] - - dk := pbkdf2.Key([]byte(password), salt, 4096, 32, sha3.New512) var dkr [32]byte - copy(dkr[:], dk) + var salty [128]byte - err, cp := DecryptProfile(encryptedbytes, dkr) + //Separate the salt from the encrypted bytes, then generate the derived key + salt, encryptedbytes := encryptedbytes[0:128], encryptedbytes[128:] + dk := pbkdf2.Key([]byte(password), salt, 4096, 32, sha3.New512) + + //cast to arrays + copy(dkr[:], dk) + copy(salty[:], salt) + + err, cp := decryptProfile(encryptedbytes, dkr) if err == nil { cp.setup() cp.profilefile = profilefile - cp.password = dkr + cp.key = dkr + cp.salt = salty return cp, nil } else { return nil, err