func (r *memRoom) GenerateMessageKey(ctx scope.Context, kms security.KMS) (proto.RoomMessageKey, error) { nonce, err := kms.GenerateNonce(security.AES128.KeySize()) if err != nil { return nil, err } mkey, err := kms.GenerateEncryptedKey(security.AES128, "room", r.name) if err != nil { return nil, err } kp := r.managerKey.KeyPair() r.messageKey = &roomMessageKey{ GrantManager: &proto.GrantManager{ Capabilities: &capabilities{}, Managers: r.managerKey, KeyEncryptingKey: &r.sec.KeyEncryptingKey, SubjectKeyPair: &kp, SubjectNonce: nonce, }, timestamp: time.Now(), nonce: nonce, key: *mkey, } r.messageKey.id = fmt.Sprintf("%s", r.messageKey.timestamp) return r.messageKey, nil }
func NewPM(kms security.KMS, client *Client, initiatorNick string, receiver UserID, receiverNick string) ( *PM, *security.ManagedKey, error) { if client.Account == nil { return nil, nil, ErrAccessDenied } pmID, err := snowflake.New() if err != nil { return nil, nil, err } iv, err := kms.GenerateNonce(RoomMessageKeyType.BlockSize()) if err != nil { return nil, nil, err } encryptedSystemKey, err := kms.GenerateEncryptedKey(RoomMessageKeyType, "pm", pmID.String()) if err != nil { return nil, nil, err } pmKey := encryptedSystemKey.Clone() if err := kms.DecryptKey(&pmKey); err != nil { return nil, nil, fmt.Errorf("pm key decrypt: %s", err) } //pmKey.IV = iv userKey := client.Account.UserKey() if err := userKey.Decrypt(client.Authorization.ClientKey); err != nil { return nil, nil, fmt.Errorf("initiator account key decrypt: %s", err) } encryptedInitiatorKey := pmKey.Clone() encryptedInitiatorKey.IV = iv if err := encryptedInitiatorKey.Encrypt(&userKey); err != nil { return nil, nil, fmt.Errorf("initiator pm key encrypt: %s", err) } var ( mac [16]byte key [32]byte ) copy(key[:], pmKey.Plaintext) poly1305.Sum(&mac, []byte(receiver), &key) pm := &PM{ ID: pmID, Initiator: client.Account.ID(), InitiatorNick: initiatorNick, Receiver: receiver, ReceiverNick: receiverNick, ReceiverMAC: mac[:], IV: iv, EncryptedSystemKey: encryptedSystemKey, EncryptedInitiatorKey: &encryptedInitiatorKey, } return pm, &pmKey, nil }
func (e *etcdCluster) setSecret(kms security.KMS, name string, bytes int) ([]byte, error) { // Generate our own key. secret, err := kms.GenerateNonce(bytes) if err != nil { return nil, err } // Try to stake our claim on this secret. if _, err := e.c.Create(e.key("/secrets/%s", name), hex.EncodeToString(secret), 0); err != nil { if etcdErr, ok := err.(*etcd.EtcdError); ok && etcdErr.ErrorCode == 105 { // Lost the race, try to use GetSecret again. return e.GetSecret(kms, name, bytes) } return nil, err } return secret, nil }
func (r *Room) generateMessageKey(b *Backend, kms security.KMS) (*RoomMessageKeyBinding, error) { // Generate unique ID for storing new key in DB. keyID, err := snowflake.New() if err != nil { return nil, err } // Use KMS to generate nonce and key. nonce, err := kms.GenerateNonce(proto.RoomManagerKeyType.KeySize()) if err != nil { return nil, err } mkey, err := kms.GenerateEncryptedKey(proto.RoomManagerKeyType, "room", r.Name) if err != nil { return nil, err } return NewRoomMessageKeyBinding(r.Bind(b), keyID, mkey, nonce), nil }
func GeneratePasswordResetRequest( kms security.KMS, accountID snowflake.Snowflake) (*PasswordResetRequest, error) { id, err := snowflake.New() if err != nil { return nil, err } key, err := kms.GenerateNonce(sha256.BlockSize) if err != nil { return nil, err } now := time.Now() req := &PasswordResetRequest{ ID: id, AccountID: accountID, Key: key, Requested: now, Expires: now.Add(PasswordResetRequestLifetime), } return req, nil }
func (tc *TestCluster) GetSecret(kms security.KMS, name string, bytes int) ([]byte, error) { tc.Lock() defer tc.Unlock() if secret, ok := tc.secrets[name]; ok { if len(secret) != bytes { return nil, fmt.Errorf("secret inconsistent: expected %d bytes, got %d", bytes, len(secret)) } return secret, nil } secret, err := kms.GenerateNonce(bytes) if err != nil { return nil, err } if tc.secrets == nil { tc.secrets = map[string][]byte{name: secret} } else { tc.secrets[name] = secret } return secret, nil }
func NewRoomSecurity(kms security.KMS, roomName string) (*RoomSecurity, error) { kpType := security.Curve25519 // Use one KMS request to obtain all the randomness we need: // - key-encrypting-key IV // - private key for grants to accounts // - nonce for manager grants to accounts randomData, err := kms.GenerateNonce( RoomManagerKeyType.BlockSize() + kpType.PrivateKeySize() + kpType.NonceSize()) if err != nil { return nil, fmt.Errorf("rng error: %s", err) } randomReader := bytes.NewReader(randomData) // Generate IV with random data. iv := make([]byte, RoomManagerKeyType.BlockSize()) if _, err := io.ReadFull(randomReader, iv); err != nil { return nil, fmt.Errorf("rng error: %s", err) } // Generate private key using randomReader. keyPair, err := kpType.Generate(randomReader) if err != nil { return nil, fmt.Errorf("keypair generation error: %s", err) } // Generate nonce with random data. nonce := make([]byte, kpType.NonceSize()) if _, err := io.ReadFull(randomReader, nonce); err != nil { return nil, fmt.Errorf("rng error: %s", err) } // Generate key-encrypting-key. This will be returned encrypted, using the // name of the room as its context. encryptedKek, err := kms.GenerateEncryptedKey(RoomManagerKeyType, "room", roomName) if err != nil { return nil, fmt.Errorf("key generation error: %s", err) } // Decrypt key-encrypting-key so we can encrypt keypair. kek := encryptedKek.Clone() if err = kms.DecryptKey(&kek); err != nil { return nil, fmt.Errorf("key decryption error: %s", err) } // Encrypt private key. keyPair.IV = iv if err = keyPair.Encrypt(&kek); err != nil { return nil, fmt.Errorf("keypair encryption error: %s", err) } // Generate message authentication code, for verifying a given key-encryption-key. var ( mac [16]byte key [32]byte ) copy(key[:], kek.Plaintext) poly1305.Sum(&mac, iv, &key) sec := &RoomSecurity{ Nonce: nonce, MAC: mac[:], KeyEncryptingKey: *encryptedKek, KeyPair: *keyPair, } return sec, nil }
// 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 }
func (b *AccountManagerBinding) GenerateOTP(ctx scope.Context, heim *proto.Heim, kms security.KMS, account proto.Account) (*proto.OTP, error) { encryptedKey, err := kms.GenerateEncryptedKey(OTPKeyType, "account", account.ID().String()) if err != nil { return nil, err } key := encryptedKey.Clone() if err := kms.DecryptKey(&key); err != nil { return nil, err } iv, err := kms.GenerateNonce(OTPKeyType.BlockSize()) if err != nil { return nil, err } t, err := b.DbMap.Begin() if err != nil { return nil, err } rawOTP, err := b.getRawOTP(t, account.ID()) if err != nil && err != proto.ErrOTPNotEnrolled { rollback(ctx, t) return nil, err } if err == nil { if rawOTP.Validated { rollback(ctx, t) return nil, proto.ErrOTPAlreadyEnrolled } row := &OTP{AccountID: account.ID().String()} if _, err := t.Delete(row); err != nil { rollback(ctx, t) return nil, err } } otp, err := heim.NewOTP(account) if err != nil { rollback(ctx, t) return nil, err } digest, encryptedURI, err := security.EncryptGCM(&key, iv, []byte(otp.URI), nil) if err != nil { rollback(ctx, t) return nil, err } row := &OTP{ AccountID: account.ID().String(), IV: iv, EncryptedKey: encryptedKey.Ciphertext, Digest: digest, EncryptedURI: encryptedURI, } if err := t.Insert(row); err != nil { // TODO: this could fail in the case of a race condition // by the time that matters we should be on postgres 9.5 and using a proper upsert rollback(ctx, t) return nil, err } if err := t.Commit(); err != nil { return nil, err } return otp, nil }