func (sec *AccountSecurity) ResetPassword(kms security.KMS, password string) (*AccountSecurity, error) { kek := sec.SystemKey.Clone() if err := kms.DecryptKey(&kek); err != nil { return nil, fmt.Errorf("key decryption error: %s", err) } kek.IV = make([]byte, ClientKeyType.BlockSize()) copy(kek.IV, sec.Nonce) clientKey := security.KeyFromPasscode([]byte(password), sec.Nonce, sec.UserKey.KeyType) if err := kek.Encrypt(clientKey); err != nil { return nil, fmt.Errorf("key encryption error: %s", err) } var ( mac [16]byte key [32]byte ) copy(key[:], clientKey.Plaintext) poly1305.Sum(&mac, sec.Nonce, &key) nsec := &AccountSecurity{ Nonce: sec.Nonce, MAC: mac[:], SystemKey: sec.SystemKey, UserKey: kek, KeyPair: sec.KeyPair, } return nsec, nil }
func (c *Client) AuthenticateWithPasscode(ctx scope.Context, room ManagedRoom, passcode string) (string, error) { mkey, err := room.MessageKey(ctx) if err != nil { return "", err } if mkey == nil { return "", nil } capability, err := mkey.PasscodeCapability(ctx, passcode) if err != nil { return "", err } if capability == nil { return "passcode incorrect", nil } holderKey := security.KeyFromPasscode([]byte(passcode), mkey.Nonce(), security.AES128) roomKey, err := decryptRoomKey(holderKey, capability) if err != nil { return "", err } // TODO: convert to account grant if signed in // TODO: load and return all historic keys c.Authorization.AddMessageKey(mkey.KeyID(), roomKey) c.Authorization.CurrentMessageKeyID = mkey.KeyID() return "", nil }
func (gs *GrantManager) RevokeFromPasscode(ctx scope.Context, passcode string) error { cid, err := security.SharedSecretCapabilityID( security.KeyFromPasscode([]byte(passcode), gs.SubjectNonce, security.AES128), gs.SubjectNonce) if err != nil { return err } return gs.Capabilities.Remove(ctx, cid) }
func TestNewAccountSecurity(t *testing.T) { kms := security.LocalKMS() kms.SetMasterKey(make([]byte, security.AES256.KeySize())) unlock := func(sec *AccountSecurity, password string) (*security.ManagedKeyPair, error) { return sec.Unlock(security.KeyFromPasscode([]byte(password), sec.Nonce, sec.UserKey.KeyType)) } Convey("Encryption and decryption of generated keys", t, func() { sec, clientKey, err := NewAccountSecurity(kms, "hunter2") So(err, ShouldBeNil) So(sec.SystemKey.Encrypted(), ShouldBeTrue) So(sec.UserKey.Encrypted(), ShouldBeTrue) So(sec.KeyPair.Encrypted(), ShouldBeTrue) So(len(sec.Nonce), ShouldEqual, sec.KeyPair.NonceSize()) So(clientKey.Encrypted(), ShouldBeFalse) kek := sec.SystemKey.Clone() So(kms.DecryptKey(&kek), ShouldBeNil) skp := sec.KeyPair.Clone() So(skp.Decrypt(&kek), ShouldBeNil) kp, err := unlock(sec, "") So(err, ShouldEqual, ErrAccessDenied) So(kp, ShouldBeNil) kp, err = unlock(sec, "hunter2") So(err, ShouldBeNil) So(kp.PrivateKey, ShouldResemble, skp.PrivateKey) }) Convey("Password resets", t, func() { sec, _, err := NewAccountSecurity(kms, "hunter2") So(err, ShouldBeNil) nsec, err := sec.ResetPassword(kms, "hunter3") So(err, ShouldBeNil) skp, err := unlock(sec, "hunter2") So(err, ShouldBeNil) _, err = unlock(nsec, "hunter2") So(err, ShouldEqual, ErrAccessDenied) kp, err := unlock(nsec, "hunter3") So(err, ShouldBeNil) So(kp.PrivateKey, ShouldResemble, skp.PrivateKey) }) }
func (gs *GrantManager) GrantToPasscode( ctx scope.Context, manager Account, managerKey *security.ManagedKey, passcode string) error { _, public, private, err := gs.Authority(ctx, manager, managerKey) if err != nil { return err } c, err := security.GrantSharedSecretCapability( security.KeyFromPasscode([]byte(passcode), gs.SubjectNonce, security.AES128), gs.SubjectNonce, public, private) if err != nil { return err } return gs.Capabilities.Save(ctx, nil, c) }
func (gs *GrantManager) PasscodeCapability( ctx scope.Context, passcode string) (*security.SharedSecretCapability, error) { cid, err := security.SharedSecretCapabilityID( security.KeyFromPasscode([]byte(passcode), gs.SubjectNonce, security.AES128), gs.SubjectNonce) if err != nil { return nil, err } c, err := gs.Capabilities.Get(ctx, cid) if err != nil { if err == ErrCapabilityNotFound { return nil, nil } return nil, err } return &security.SharedSecretCapability{Capability: c}, nil }
func (a *memAccount) KeyFromPassword(password string) *security.ManagedKey { return security.KeyFromPasscode([]byte(password), a.sec.Nonce, a.sec.UserKey.KeyType) }
func (ab *AccountBinding) KeyFromPassword(password string) *security.ManagedKey { return security.KeyFromPasscode([]byte(password), ab.Account.Nonce, proto.ClientKeyType) }
// NewAccountSecurity initializes the nonce and account secrets for a new account // with the given password. Returns an encrypted key-encrypting-key, encrypted // key-pair, nonce, and error. func NewAccountSecurity( kms security.KMS, password string) (*AccountSecurity, *security.ManagedKey, error) { kpType := security.Curve25519 // Use one KMS request to obtain all the randomness we need: // - nonce // - private key randomData, err := kms.GenerateNonce(kpType.NonceSize() + kpType.PrivateKeySize()) if err != nil { return nil, nil, fmt.Errorf("rng error: %s", err) } randomReader := bytes.NewReader(randomData) // Generate nonce with random data. Use to populate IV. nonce := make([]byte, kpType.NonceSize()) if _, err := io.ReadFull(randomReader, nonce); err != nil { return nil, nil, fmt.Errorf("rng error: %s", err) } iv := make([]byte, ClientKeyType.BlockSize()) copy(iv, nonce) // Generate key-encrypting-key using KMS. This will be returned encrypted, // using the base64 encoding of the nonce as its context. nonceBase64 := base64.URLEncoding.EncodeToString(nonce) systemKey, err := kms.GenerateEncryptedKey(ClientKeyType, "nonce", nonceBase64) if err != nil { return nil, nil, fmt.Errorf("key generation error: %s", err) } // Generate private key using randomReader. keyPair, err := kpType.Generate(randomReader) if err != nil { return nil, nil, fmt.Errorf("keypair generation error: %s", err) } // Decrypt key-encrypting-key so we can encrypt keypair, and so we can re-encrypt // it using the user's key. kek := systemKey.Clone() if err = kms.DecryptKey(&kek); err != nil { return nil, nil, fmt.Errorf("key decryption error: %s", err) } // Encrypt private key. keyPair.IV = iv if err = keyPair.Encrypt(&kek); err != nil { return nil, nil, fmt.Errorf("keypair encryption error: %s", err) } // Clone key-encrypting-key and encrypt with client key. clientKey := security.KeyFromPasscode([]byte(password), nonce, ClientKeyType) userKey := kek.Clone() userKey.IV = iv if err := userKey.Encrypt(clientKey); err != nil { return nil, nil, fmt.Errorf("key encryption error: %s", err) } // Generate message authentication code, for verifying passwords. var ( mac [16]byte key [32]byte ) copy(key[:], clientKey.Plaintext) poly1305.Sum(&mac, nonce, &key) sec := &AccountSecurity{ Nonce: nonce, MAC: mac[:], SystemKey: *systemKey, UserKey: userKey, KeyPair: *keyPair, } return sec, clientKey, nil }