95 lines
2.8 KiB
Go
95 lines
2.8 KiB
Go
// Copyright (c) 2020 Tulir Asokan
|
|
//
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
package crypto
|
|
|
|
import (
|
|
"maunium.net/go/mautrix"
|
|
"maunium.net/go/mautrix/crypto/olm"
|
|
"maunium.net/go/mautrix/id"
|
|
)
|
|
|
|
type OlmAccount struct {
|
|
Internal olm.Account
|
|
signingKey id.SigningKey
|
|
identityKey id.IdentityKey
|
|
Shared bool
|
|
}
|
|
|
|
func NewOlmAccount() *OlmAccount {
|
|
return &OlmAccount{
|
|
Internal: *olm.NewAccount(),
|
|
}
|
|
}
|
|
|
|
func (account *OlmAccount) Keys() (id.SigningKey, id.IdentityKey) {
|
|
if len(account.signingKey) == 0 || len(account.identityKey) == 0 {
|
|
account.signingKey, account.identityKey = account.Internal.IdentityKeys()
|
|
}
|
|
return account.signingKey, account.identityKey
|
|
}
|
|
|
|
func (account *OlmAccount) SigningKey() id.SigningKey {
|
|
if len(account.signingKey) == 0 {
|
|
account.signingKey, account.identityKey = account.Internal.IdentityKeys()
|
|
}
|
|
return account.signingKey
|
|
}
|
|
|
|
func (account *OlmAccount) IdentityKey() id.IdentityKey {
|
|
if len(account.identityKey) == 0 {
|
|
account.signingKey, account.identityKey = account.Internal.IdentityKeys()
|
|
}
|
|
return account.identityKey
|
|
}
|
|
|
|
func (account *OlmAccount) getInitialKeys(userID id.UserID, deviceID id.DeviceID) *mautrix.DeviceKeys {
|
|
deviceKeys := &mautrix.DeviceKeys{
|
|
UserID: userID,
|
|
DeviceID: deviceID,
|
|
Algorithms: []id.Algorithm{id.AlgorithmMegolmV1, id.AlgorithmOlmV1},
|
|
Keys: map[id.DeviceKeyID]string{
|
|
id.NewDeviceKeyID(id.KeyAlgorithmCurve25519, deviceID): string(account.IdentityKey()),
|
|
id.NewDeviceKeyID(id.KeyAlgorithmEd25519, deviceID): string(account.SigningKey()),
|
|
},
|
|
}
|
|
|
|
signature, err := account.Internal.SignJSON(deviceKeys)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
deviceKeys.Signatures = mautrix.Signatures{
|
|
userID: {
|
|
id.NewKeyID(id.KeyAlgorithmEd25519, deviceID.String()): signature,
|
|
},
|
|
}
|
|
return deviceKeys
|
|
}
|
|
|
|
func (account *OlmAccount) getOneTimeKeys(userID id.UserID, deviceID id.DeviceID, currentOTKCount int) map[id.KeyID]mautrix.OneTimeKey {
|
|
newCount := int(account.Internal.MaxNumberOfOneTimeKeys()/2) - currentOTKCount
|
|
if newCount > 0 {
|
|
account.Internal.GenOneTimeKeys(uint(newCount))
|
|
}
|
|
oneTimeKeys := make(map[id.KeyID]mautrix.OneTimeKey)
|
|
// TODO do we need unsigned curve25519 one-time keys at all?
|
|
// this just signs all of them
|
|
for keyID, key := range account.Internal.OneTimeKeys() {
|
|
key := mautrix.OneTimeKey{Key: key}
|
|
signature, _ := account.Internal.SignJSON(key)
|
|
key.Signatures = mautrix.Signatures{
|
|
userID: {
|
|
id.NewKeyID(id.KeyAlgorithmEd25519, deviceID.String()): signature,
|
|
},
|
|
}
|
|
key.IsSigned = true
|
|
oneTimeKeys[id.NewKeyID(id.KeyAlgorithmSignedCurve25519, keyID)] = key
|
|
}
|
|
account.Internal.MarkKeysAsPublished()
|
|
return oneTimeKeys
|
|
}
|