7
7
package crypto
8
8
9
9
import (
10
+ "bytes"
10
11
"encoding/json"
12
+ "fmt"
11
13
12
14
"github.com/tidwall/sjson"
13
15
14
16
"maunium.net/go/mautrix"
15
17
"maunium.net/go/mautrix/crypto/canonicaljson"
18
+ "maunium.net/go/mautrix/crypto/goolm/account"
16
19
"maunium.net/go/mautrix/crypto/olm"
17
20
"maunium.net/go/mautrix/crypto/signatures"
18
21
"maunium.net/go/mautrix/id"
19
22
)
20
23
21
24
type OlmAccount struct {
22
- Internal olm.Account
25
+ InternalLibolm olm.Account
26
+ InternalGoolm olm.Account
23
27
signingKey id.SigningKey
24
28
identityKey id.IdentityKey
25
29
Shared bool
26
30
KeyBackupVersion id.KeyBackupVersion
27
31
}
28
32
29
33
func NewOlmAccount () * OlmAccount {
30
- account , err := olm .NewAccount ()
34
+ libolmAccount , err := olm .NewAccount ()
35
+ if err != nil {
36
+ panic (err )
37
+ }
38
+ pickled , err := libolmAccount .Pickle ([]byte ("key" ))
39
+ if err != nil {
40
+ panic (err )
41
+ }
42
+ goolmAccount , err := account .AccountFromPickled (pickled , []byte ("key" ))
31
43
if err != nil {
32
44
panic (err )
33
45
}
34
46
return & OlmAccount {
35
- Internal : account ,
47
+ InternalLibolm : libolmAccount ,
48
+ InternalGoolm : goolmAccount ,
36
49
}
37
50
}
38
51
39
52
func (account * OlmAccount ) Keys () (id.SigningKey , id.IdentityKey ) {
40
53
if len (account .signingKey ) == 0 || len (account .identityKey ) == 0 {
41
54
var err error
42
- account .signingKey , account .identityKey , err = account .Internal .IdentityKeys ()
55
+ account .signingKey , account .identityKey , err = account .InternalLibolm .IdentityKeys ()
56
+ if err != nil {
57
+ panic (err )
58
+ }
59
+ goolmSigningKey , goolmIdentityKey , err := account .InternalGoolm .IdentityKeys ()
43
60
if err != nil {
44
61
panic (err )
45
62
}
63
+ if account .signingKey != goolmSigningKey {
64
+ panic ("account signing keys not equal" )
65
+ }
66
+ if account .identityKey != goolmIdentityKey {
67
+ panic ("account identity keys not equal" )
68
+ }
46
69
}
47
70
return account .signingKey , account .identityKey
48
71
}
49
72
50
73
func (account * OlmAccount ) SigningKey () id.SigningKey {
51
74
if len (account .signingKey ) == 0 {
52
75
var err error
53
- account .signingKey , account .identityKey , err = account .Internal .IdentityKeys ()
76
+ account .signingKey , account .identityKey , err = account .InternalLibolm .IdentityKeys ()
77
+ if err != nil {
78
+ panic (err )
79
+ }
80
+ goolmSigningKey , goolmIdentityKey , err := account .InternalGoolm .IdentityKeys ()
54
81
if err != nil {
55
82
panic (err )
56
83
}
84
+ if account .signingKey != goolmSigningKey {
85
+ panic ("account signing keys not equal" )
86
+ }
87
+ if account .identityKey != goolmIdentityKey {
88
+ panic ("account identity keys not equal" )
89
+ }
57
90
}
58
91
return account .signingKey
59
92
}
60
93
61
94
func (account * OlmAccount ) IdentityKey () id.IdentityKey {
62
95
if len (account .identityKey ) == 0 {
63
96
var err error
64
- account .signingKey , account .identityKey , err = account .Internal .IdentityKeys ()
97
+ account .signingKey , account .identityKey , err = account .InternalLibolm .IdentityKeys ()
98
+ if err != nil {
99
+ panic (err )
100
+ }
101
+ goolmSigningKey , goolmIdentityKey , err := account .InternalGoolm .IdentityKeys ()
65
102
if err != nil {
66
103
panic (err )
67
104
}
105
+ if account .signingKey != goolmSigningKey {
106
+ panic ("account signing keys not equal" )
107
+ }
108
+ if account .identityKey != goolmIdentityKey {
109
+ panic ("account identity keys not equal" )
110
+ }
68
111
}
69
112
return account .identityKey
70
113
}
@@ -78,7 +121,15 @@ func (account *OlmAccount) SignJSON(obj any) (string, error) {
78
121
}
79
122
objJSON , _ = sjson .DeleteBytes (objJSON , "unsigned" )
80
123
objJSON , _ = sjson .DeleteBytes (objJSON , "signatures" )
81
- signed , err := account .Internal .Sign (canonicaljson .CanonicalJSONAssumeValid (objJSON ))
124
+ signed , err := account .InternalLibolm .Sign (canonicaljson .CanonicalJSONAssumeValid (objJSON ))
125
+ goolmSigned , goolmErr := account .InternalGoolm .Sign (canonicaljson .CanonicalJSONAssumeValid (objJSON ))
126
+ if err != nil {
127
+ if goolmErr == nil {
128
+ panic ("libolm errored, but goolm did not on account.SignJSON" )
129
+ }
130
+ } else if ! bytes .Equal (signed , goolmSigned ) {
131
+ panic ("libolm and goolm signed are not equal in account.SignJSON" )
132
+ }
82
133
return string (signed ), err
83
134
}
84
135
@@ -102,19 +153,36 @@ func (account *OlmAccount) getInitialKeys(userID id.UserID, deviceID id.DeviceID
102
153
return deviceKeys
103
154
}
104
155
105
- func (account * OlmAccount ) getOneTimeKeys (userID id.UserID , deviceID id.DeviceID , currentOTKCount int ) map [id.KeyID ]mautrix.OneTimeKey {
106
- newCount := int (account . Internal .MaxNumberOfOneTimeKeys ()/ 2 ) - currentOTKCount
156
+ func (a * OlmAccount ) getOneTimeKeys (userID id.UserID , deviceID id.DeviceID , currentOTKCount int ) map [id.KeyID ]mautrix.OneTimeKey {
157
+ newCount := int (a . InternalLibolm .MaxNumberOfOneTimeKeys ()/ 2 ) - currentOTKCount
107
158
if newCount > 0 {
108
- account .Internal .GenOneTimeKeys (uint (newCount ))
159
+ a .InternalLibolm .GenOneTimeKeys (uint (newCount ))
160
+
161
+ pickled , err := a .InternalLibolm .Pickle ([]byte ("key" ))
162
+ if err != nil {
163
+ panic (err )
164
+ }
165
+ a .InternalGoolm , err = account .AccountFromPickled (pickled , []byte ("key" ))
166
+ if err != nil {
167
+ panic (err )
168
+ }
109
169
}
110
170
oneTimeKeys := make (map [id.KeyID ]mautrix.OneTimeKey )
111
- internalKeys , err := account .Internal .OneTimeKeys ()
171
+ internalKeys , err := a .InternalLibolm .OneTimeKeys ()
172
+ if err != nil {
173
+ panic (err )
174
+ }
175
+ goolmInternalKeys , err := a .InternalGoolm .OneTimeKeys ()
112
176
if err != nil {
113
177
panic (err )
114
178
}
115
179
for keyID , key := range internalKeys {
180
+ if goolmInternalKeys [keyID ] != key {
181
+ panic (fmt .Sprintf ("key %s not found in getOneTimeKeys" , keyID ))
182
+ }
183
+
116
184
key := mautrix.OneTimeKey {Key : key }
117
- signature , _ := account .SignJSON (key )
185
+ signature , _ := a .SignJSON (key )
118
186
key .Signatures = signatures .NewSingleSignature (userID , id .KeyAlgorithmEd25519 , deviceID .String (), signature )
119
187
key .IsSigned = true
120
188
oneTimeKeys [id .NewKeyID (id .KeyAlgorithmSignedCurve25519 , keyID )] = key
0 commit comments