mirror of https://github.com/mautrix/go.git
155 lines
4.1 KiB
Go
155 lines
4.1 KiB
Go
//go:build goolm
|
|
|
|
package olm
|
|
|
|
import (
|
|
"encoding/json"
|
|
|
|
"github.com/tidwall/sjson"
|
|
|
|
"maunium.net/go/mautrix/crypto/canonicaljson"
|
|
"maunium.net/go/mautrix/crypto/goolm/account"
|
|
"maunium.net/go/mautrix/id"
|
|
)
|
|
|
|
// Account stores a device account for end to end encrypted messaging.
|
|
type Account struct {
|
|
account.Account
|
|
}
|
|
|
|
// NewAccount creates a new Account.
|
|
func NewAccount() *Account {
|
|
a, err := account.NewAccount(nil)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
ac := &Account{}
|
|
ac.Account = *a
|
|
return ac
|
|
}
|
|
|
|
func NewBlankAccount() *Account {
|
|
return &Account{}
|
|
}
|
|
|
|
// Clear clears the memory used to back this Account.
|
|
func (a *Account) Clear() error {
|
|
a.Account = account.Account{}
|
|
return nil
|
|
}
|
|
|
|
// Pickle returns an Account as a base64 string. Encrypts the Account using the
|
|
// supplied key.
|
|
func (a *Account) Pickle(key []byte) []byte {
|
|
if len(key) == 0 {
|
|
panic(NoKeyProvided)
|
|
}
|
|
pickled, err := a.Account.Pickle(key)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return pickled
|
|
}
|
|
|
|
// IdentityKeysJSON returns the public parts of the identity keys for the Account.
|
|
func (a *Account) IdentityKeysJSON() []byte {
|
|
identityKeys, err := a.Account.IdentityKeysJSON()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return identityKeys
|
|
}
|
|
|
|
// Sign returns the signature of a message using the ed25519 key for this
|
|
// Account.
|
|
func (a *Account) Sign(message []byte) []byte {
|
|
if len(message) == 0 {
|
|
panic(EmptyInput)
|
|
}
|
|
signature, err := a.Account.Sign(message)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return signature
|
|
}
|
|
|
|
// SignJSON signs the given JSON object following the Matrix specification:
|
|
// https://matrix.org/docs/spec/appendices#signing-json
|
|
func (a *Account) SignJSON(obj interface{}) (string, error) {
|
|
objJSON, err := json.Marshal(obj)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
objJSON, _ = sjson.DeleteBytes(objJSON, "unsigned")
|
|
objJSON, _ = sjson.DeleteBytes(objJSON, "signatures")
|
|
return string(a.Sign(canonicaljson.CanonicalJSONAssumeValid(objJSON))), nil
|
|
}
|
|
|
|
// MaxNumberOfOneTimeKeys returns the largest number of one time keys this
|
|
// Account can store.
|
|
func (a *Account) MaxNumberOfOneTimeKeys() uint {
|
|
return uint(account.MaxOneTimeKeys)
|
|
}
|
|
|
|
// GenOneTimeKeys generates a number of new one time keys. If the total number
|
|
// of keys stored by this Account exceeds MaxNumberOfOneTimeKeys then the old
|
|
// keys are discarded.
|
|
func (a *Account) GenOneTimeKeys(num uint) {
|
|
err := a.Account.GenOneTimeKeys(nil, num)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
// NewOutboundSession creates a new out-bound session for sending messages to a
|
|
// given curve25519 identityKey and oneTimeKey. Returns error on failure.
|
|
func (a *Account) NewOutboundSession(theirIdentityKey, theirOneTimeKey id.Curve25519) (*Session, error) {
|
|
if len(theirIdentityKey) == 0 || len(theirOneTimeKey) == 0 {
|
|
return nil, EmptyInput
|
|
}
|
|
s := &Session{}
|
|
newSession, err := a.Account.NewOutboundSession(theirIdentityKey, theirOneTimeKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
s.OlmSession = *newSession
|
|
return s, nil
|
|
}
|
|
|
|
// NewInboundSession creates a new in-bound session for sending/receiving
|
|
// messages from an incoming PRE_KEY message. Returns error on failure.
|
|
func (a *Account) NewInboundSession(oneTimeKeyMsg string) (*Session, error) {
|
|
if len(oneTimeKeyMsg) == 0 {
|
|
return nil, EmptyInput
|
|
}
|
|
s := &Session{}
|
|
newSession, err := a.Account.NewInboundSession(nil, []byte(oneTimeKeyMsg))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
s.OlmSession = *newSession
|
|
return s, nil
|
|
}
|
|
|
|
// NewInboundSessionFrom creates a new in-bound session for sending/receiving
|
|
// messages from an incoming PRE_KEY message. Returns error on failure.
|
|
func (a *Account) NewInboundSessionFrom(theirIdentityKey id.Curve25519, oneTimeKeyMsg string) (*Session, error) {
|
|
if len(theirIdentityKey) == 0 || len(oneTimeKeyMsg) == 0 {
|
|
return nil, EmptyInput
|
|
}
|
|
s := &Session{}
|
|
newSession, err := a.Account.NewInboundSession(&theirIdentityKey, []byte(oneTimeKeyMsg))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
s.OlmSession = *newSession
|
|
return s, nil
|
|
}
|
|
|
|
// RemoveOneTimeKeys removes the one time keys that the session used from the
|
|
// Account. Returns error on failure.
|
|
func (a *Account) RemoveOneTimeKeys(s *Session) error {
|
|
a.Account.RemoveOneTimeKeys(&s.OlmSession)
|
|
return nil
|
|
}
|