-
-
Notifications
You must be signed in to change notification settings - Fork 67
/
cross_sign_ssss.go
119 lines (103 loc) · 4.06 KB
/
cross_sign_ssss.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Copyright (c) 2020 Nikos Filippakis
//
// 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 (
"fmt"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/crypto/ssss"
"maunium.net/go/mautrix/crypto/utils"
"maunium.net/go/mautrix/event"
)
// FetchCrossSigningKeysFromSSSS fetches all the cross-signing keys from SSSS, decrypts them using the given key and stores them in the olm machine.
func (mach *OlmMachine) FetchCrossSigningKeysFromSSSS(key *ssss.Key) error {
masterKey, err := mach.retrieveDecryptXSigningKey(event.AccountDataCrossSigningMaster, key)
if err != nil {
return err
}
selfSignKey, err := mach.retrieveDecryptXSigningKey(event.AccountDataCrossSigningSelf, key)
if err != nil {
return err
}
userSignKey, err := mach.retrieveDecryptXSigningKey(event.AccountDataCrossSigningUser, key)
if err != nil {
return err
}
return mach.ImportCrossSigningKeys(CrossSigningSeeds{
MasterKey: masterKey[:],
SelfSigningKey: selfSignKey[:],
UserSigningKey: userSignKey[:],
})
}
// retrieveDecryptXSigningKey retrieves the requested cross-signing key from SSSS and decrypts it using the given SSSS key.
func (mach *OlmMachine) retrieveDecryptXSigningKey(keyName event.Type, key *ssss.Key) ([utils.AESCTRKeyLength]byte, error) {
var decryptedKey [utils.AESCTRKeyLength]byte
var encData ssss.EncryptedAccountDataEventContent
// retrieve and parse the account data for this key type from SSSS
err := mach.Client.GetAccountData(keyName.Type, &encData)
if err != nil {
return decryptedKey, err
}
decrypted, err := encData.Decrypt(keyName.Type, key)
if err != nil {
return decryptedKey, err
}
copy(decryptedKey[:], decrypted)
return decryptedKey, nil
}
// GenerateAndUploadCrossSigningKeys generates a new key with all corresponding cross-signing keys.
//
// A passphrase can be provided to generate the SSSS key. If the passphrase is empty, a random key
// is used. The base58-formatted recovery key is the first return parameter.
//
// The account password of the user is required for uploading keys to the server.
func (mach *OlmMachine) GenerateAndUploadCrossSigningKeys(userPassword, passphrase string) (string, error) {
key, err := mach.SSSS.GenerateAndUploadKey(passphrase)
if err != nil {
return "", fmt.Errorf("failed to generate and upload SSSS key: %w", err)
}
// generate the three cross-signing keys
keysCache, err := mach.GenerateCrossSigningKeys()
if err != nil {
return "", err
}
recoveryKey := key.RecoveryKey()
// Store the private keys in SSSS
if err := mach.UploadCrossSigningKeysToSSSS(key, keysCache); err != nil {
return recoveryKey, fmt.Errorf("failed to upload cross-signing keys to SSSS: %w", err)
}
// Publish cross-signing keys
err = mach.PublishCrossSigningKeys(keysCache, func(uiResp *mautrix.RespUserInteractive) interface{} {
return &mautrix.ReqUIAuthLogin{
BaseAuthData: mautrix.BaseAuthData{
Type: mautrix.AuthTypePassword,
Session: uiResp.Session,
},
User: mach.Client.UserID.String(),
Password: userPassword,
}
})
if err != nil {
return recoveryKey, fmt.Errorf("failed to publish cross-signing keys: %w", err)
}
err = mach.SSSS.SetDefaultKeyID(key.ID)
if err != nil {
return recoveryKey, fmt.Errorf("failed to mark %s as the default key: %w", key.ID, err)
}
return recoveryKey, nil
}
// UploadCrossSigningKeysToSSSS stores the given cross-signing keys on the server encrypted with the given key.
func (mach *OlmMachine) UploadCrossSigningKeysToSSSS(key *ssss.Key, keys *CrossSigningKeysCache) error {
if err := mach.SSSS.SetEncryptedAccountData(event.AccountDataCrossSigningMaster, keys.MasterKey.Seed, key); err != nil {
return err
}
if err := mach.SSSS.SetEncryptedAccountData(event.AccountDataCrossSigningSelf, keys.SelfSigningKey.Seed, key); err != nil {
return err
}
if err := mach.SSSS.SetEncryptedAccountData(event.AccountDataCrossSigningUser, keys.UserSigningKey.Seed, key); err != nil {
return err
}
return nil
}