mirror of
https://mau.dev/mautrix/go.git
synced 2026-03-14 14:25:53 +01:00
olm/pk: make an interface
Signed-off-by: Sumner Evans <sumner@beeper.com>
This commit is contained in:
parent
d18dcfc7eb
commit
3b65d98c0c
10 changed files with 222 additions and 175 deletions
|
|
@ -19,16 +19,16 @@ import (
|
|||
|
||||
// CrossSigningKeysCache holds the three cross-signing keys for the current user.
|
||||
type CrossSigningKeysCache struct {
|
||||
MasterKey *olm.PkSigning
|
||||
SelfSigningKey *olm.PkSigning
|
||||
UserSigningKey *olm.PkSigning
|
||||
MasterKey olm.PKSigning
|
||||
SelfSigningKey olm.PKSigning
|
||||
UserSigningKey olm.PKSigning
|
||||
}
|
||||
|
||||
func (cskc *CrossSigningKeysCache) PublicKeys() *CrossSigningPublicKeysCache {
|
||||
return &CrossSigningPublicKeysCache{
|
||||
MasterKey: cskc.MasterKey.PublicKey,
|
||||
SelfSigningKey: cskc.SelfSigningKey.PublicKey,
|
||||
UserSigningKey: cskc.UserSigningKey.PublicKey,
|
||||
MasterKey: cskc.MasterKey.PublicKey(),
|
||||
SelfSigningKey: cskc.SelfSigningKey.PublicKey(),
|
||||
UserSigningKey: cskc.UserSigningKey.PublicKey(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -40,28 +40,28 @@ type CrossSigningSeeds struct {
|
|||
|
||||
func (mach *OlmMachine) ExportCrossSigningKeys() CrossSigningSeeds {
|
||||
return CrossSigningSeeds{
|
||||
MasterKey: mach.CrossSigningKeys.MasterKey.Seed,
|
||||
SelfSigningKey: mach.CrossSigningKeys.SelfSigningKey.Seed,
|
||||
UserSigningKey: mach.CrossSigningKeys.UserSigningKey.Seed,
|
||||
MasterKey: mach.CrossSigningKeys.MasterKey.Seed(),
|
||||
SelfSigningKey: mach.CrossSigningKeys.SelfSigningKey.Seed(),
|
||||
UserSigningKey: mach.CrossSigningKeys.UserSigningKey.Seed(),
|
||||
}
|
||||
}
|
||||
|
||||
func (mach *OlmMachine) ImportCrossSigningKeys(keys CrossSigningSeeds) (err error) {
|
||||
var keysCache CrossSigningKeysCache
|
||||
if keysCache.MasterKey, err = olm.NewPkSigningFromSeed(keys.MasterKey); err != nil {
|
||||
if keysCache.MasterKey, err = olm.NewPKSigningFromSeed(keys.MasterKey); err != nil {
|
||||
return
|
||||
}
|
||||
if keysCache.SelfSigningKey, err = olm.NewPkSigningFromSeed(keys.SelfSigningKey); err != nil {
|
||||
if keysCache.SelfSigningKey, err = olm.NewPKSigningFromSeed(keys.SelfSigningKey); err != nil {
|
||||
return
|
||||
}
|
||||
if keysCache.UserSigningKey, err = olm.NewPkSigningFromSeed(keys.UserSigningKey); err != nil {
|
||||
if keysCache.UserSigningKey, err = olm.NewPKSigningFromSeed(keys.UserSigningKey); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
mach.Log.Debug().
|
||||
Str("master", keysCache.MasterKey.PublicKey.String()).
|
||||
Str("self_signing", keysCache.SelfSigningKey.PublicKey.String()).
|
||||
Str("user_signing", keysCache.UserSigningKey.PublicKey.String()).
|
||||
Str("master", keysCache.MasterKey.PublicKey().String()).
|
||||
Str("self_signing", keysCache.SelfSigningKey.PublicKey().String()).
|
||||
Str("user_signing", keysCache.UserSigningKey.PublicKey().String()).
|
||||
Msg("Imported own cross-signing keys")
|
||||
|
||||
mach.CrossSigningKeys = &keysCache
|
||||
|
|
@ -73,19 +73,19 @@ func (mach *OlmMachine) ImportCrossSigningKeys(keys CrossSigningSeeds) (err erro
|
|||
func (mach *OlmMachine) GenerateCrossSigningKeys() (*CrossSigningKeysCache, error) {
|
||||
var keysCache CrossSigningKeysCache
|
||||
var err error
|
||||
if keysCache.MasterKey, err = olm.NewPkSigning(); err != nil {
|
||||
if keysCache.MasterKey, err = olm.NewPKSigning(); err != nil {
|
||||
return nil, fmt.Errorf("failed to generate master key: %w", err)
|
||||
}
|
||||
if keysCache.SelfSigningKey, err = olm.NewPkSigning(); err != nil {
|
||||
if keysCache.SelfSigningKey, err = olm.NewPKSigning(); err != nil {
|
||||
return nil, fmt.Errorf("failed to generate self-signing key: %w", err)
|
||||
}
|
||||
if keysCache.UserSigningKey, err = olm.NewPkSigning(); err != nil {
|
||||
if keysCache.UserSigningKey, err = olm.NewPKSigning(); err != nil {
|
||||
return nil, fmt.Errorf("failed to generate user-signing key: %w", err)
|
||||
}
|
||||
mach.Log.Debug().
|
||||
Str("master", keysCache.MasterKey.PublicKey.String()).
|
||||
Str("self_signing", keysCache.SelfSigningKey.PublicKey.String()).
|
||||
Str("user_signing", keysCache.UserSigningKey.PublicKey.String()).
|
||||
Str("master", keysCache.MasterKey.PublicKey().String()).
|
||||
Str("self_signing", keysCache.SelfSigningKey.PublicKey().String()).
|
||||
Str("user_signing", keysCache.UserSigningKey.PublicKey().String()).
|
||||
Msg("Generated cross-signing keys")
|
||||
return &keysCache, nil
|
||||
}
|
||||
|
|
@ -93,12 +93,12 @@ func (mach *OlmMachine) GenerateCrossSigningKeys() (*CrossSigningKeysCache, erro
|
|||
// PublishCrossSigningKeys signs and uploads the public keys of the given cross-signing keys to the server.
|
||||
func (mach *OlmMachine) PublishCrossSigningKeys(ctx context.Context, keys *CrossSigningKeysCache, uiaCallback mautrix.UIACallback) error {
|
||||
userID := mach.Client.UserID
|
||||
masterKeyID := id.NewKeyID(id.KeyAlgorithmEd25519, keys.MasterKey.PublicKey.String())
|
||||
masterKeyID := id.NewKeyID(id.KeyAlgorithmEd25519, keys.MasterKey.PublicKey().String())
|
||||
masterKey := mautrix.CrossSigningKeys{
|
||||
UserID: userID,
|
||||
Usage: []id.CrossSigningUsage{id.XSUsageMaster},
|
||||
Keys: map[id.KeyID]id.Ed25519{
|
||||
masterKeyID: keys.MasterKey.PublicKey,
|
||||
masterKeyID: keys.MasterKey.PublicKey(),
|
||||
},
|
||||
}
|
||||
masterSig, err := mach.account.Internal.SignJSON(masterKey)
|
||||
|
|
@ -111,27 +111,27 @@ func (mach *OlmMachine) PublishCrossSigningKeys(ctx context.Context, keys *Cross
|
|||
UserID: userID,
|
||||
Usage: []id.CrossSigningUsage{id.XSUsageSelfSigning},
|
||||
Keys: map[id.KeyID]id.Ed25519{
|
||||
id.NewKeyID(id.KeyAlgorithmEd25519, keys.SelfSigningKey.PublicKey.String()): keys.SelfSigningKey.PublicKey,
|
||||
id.NewKeyID(id.KeyAlgorithmEd25519, keys.SelfSigningKey.PublicKey().String()): keys.SelfSigningKey.PublicKey(),
|
||||
},
|
||||
}
|
||||
selfSig, err := keys.MasterKey.SignJSON(selfKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to sign self-signing key: %w", err)
|
||||
}
|
||||
selfKey.Signatures = signatures.NewSingleSignature(userID, id.KeyAlgorithmEd25519, keys.MasterKey.PublicKey.String(), selfSig)
|
||||
selfKey.Signatures = signatures.NewSingleSignature(userID, id.KeyAlgorithmEd25519, keys.MasterKey.PublicKey().String(), selfSig)
|
||||
|
||||
userKey := mautrix.CrossSigningKeys{
|
||||
UserID: userID,
|
||||
Usage: []id.CrossSigningUsage{id.XSUsageUserSigning},
|
||||
Keys: map[id.KeyID]id.Ed25519{
|
||||
id.NewKeyID(id.KeyAlgorithmEd25519, keys.UserSigningKey.PublicKey.String()): keys.UserSigningKey.PublicKey,
|
||||
id.NewKeyID(id.KeyAlgorithmEd25519, keys.UserSigningKey.PublicKey().String()): keys.UserSigningKey.PublicKey(),
|
||||
},
|
||||
}
|
||||
userSig, err := keys.MasterKey.SignJSON(userKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to sign user-signing key: %w", err)
|
||||
}
|
||||
userKey.Signatures = signatures.NewSingleSignature(userID, id.KeyAlgorithmEd25519, keys.MasterKey.PublicKey.String(), userSig)
|
||||
userKey.Signatures = signatures.NewSingleSignature(userID, id.KeyAlgorithmEd25519, keys.MasterKey.PublicKey().String(), userSig)
|
||||
|
||||
err = mach.Client.UploadCrossSigningKeys(ctx, &mautrix.UploadCrossSigningKeysReq{
|
||||
Master: masterKey,
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ func (mach *OlmMachine) SignUser(ctx context.Context, userID id.UserID, masterKe
|
|||
Str("signature", signature).
|
||||
Msg("Signed master key of user with our user-signing key")
|
||||
|
||||
if err := mach.CryptoStore.PutSignature(ctx, userID, masterKey, mach.Client.UserID, mach.CrossSigningKeys.UserSigningKey.PublicKey, signature); err != nil {
|
||||
if err := mach.CryptoStore.PutSignature(ctx, userID, masterKey, mach.Client.UserID, mach.CrossSigningKeys.UserSigningKey.PublicKey(), signature); err != nil {
|
||||
return fmt.Errorf("error storing signature in crypto store: %w", err)
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ func (mach *OlmMachine) SignOwnMasterKey(ctx context.Context) error {
|
|||
|
||||
userID := mach.Client.UserID
|
||||
deviceID := mach.Client.DeviceID
|
||||
masterKey := mach.CrossSigningKeys.MasterKey.PublicKey
|
||||
masterKey := mach.CrossSigningKeys.MasterKey.PublicKey()
|
||||
|
||||
masterKeyObj := mautrix.ReqKeysSignatures{
|
||||
UserID: userID,
|
||||
|
|
@ -149,7 +149,7 @@ func (mach *OlmMachine) SignOwnDevice(ctx context.Context, device *id.Device) er
|
|||
Str("signature", signature).
|
||||
Msg("Signed own device key with self-signing key")
|
||||
|
||||
if err := mach.CryptoStore.PutSignature(ctx, device.UserID, device.SigningKey, mach.Client.UserID, mach.CrossSigningKeys.SelfSigningKey.PublicKey, signature); err != nil {
|
||||
if err := mach.CryptoStore.PutSignature(ctx, device.UserID, device.SigningKey, mach.Client.UserID, mach.CrossSigningKeys.SelfSigningKey.PublicKey(), signature); err != nil {
|
||||
return fmt.Errorf("error storing signature in crypto store: %w", err)
|
||||
}
|
||||
|
||||
|
|
@ -180,12 +180,12 @@ func (mach *OlmMachine) getFullDeviceKeys(ctx context.Context, device *id.Device
|
|||
}
|
||||
|
||||
// signAndUpload signs the given key signatures object and uploads it to the server.
|
||||
func (mach *OlmMachine) signAndUpload(ctx context.Context, req mautrix.ReqKeysSignatures, userID id.UserID, signedThing string, key *olm.PkSigning) (string, error) {
|
||||
func (mach *OlmMachine) signAndUpload(ctx context.Context, req mautrix.ReqKeysSignatures, userID id.UserID, signedThing string, key olm.PKSigning) (string, error) {
|
||||
signature, err := key.SignJSON(req)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to sign JSON: %w", err)
|
||||
}
|
||||
req.Signatures = signatures.NewSingleSignature(mach.Client.UserID, id.KeyAlgorithmEd25519, key.PublicKey.String(), signature)
|
||||
req.Signatures = signatures.NewSingleSignature(mach.Client.UserID, id.KeyAlgorithmEd25519, key.PublicKey().String(), signature)
|
||||
|
||||
resp, err := mach.Client.UploadSignatures(ctx, &mautrix.ReqUploadSignatures{
|
||||
userID: map[string]mautrix.ReqKeysSignatures{
|
||||
|
|
|
|||
|
|
@ -110,24 +110,24 @@ func (mach *OlmMachine) GenerateAndUploadCrossSigningKeys(ctx context.Context, u
|
|||
|
||||
// UploadCrossSigningKeysToSSSS stores the given cross-signing keys on the server encrypted with the given key.
|
||||
func (mach *OlmMachine) UploadCrossSigningKeysToSSSS(ctx context.Context, key *ssss.Key, keys *CrossSigningKeysCache) error {
|
||||
if err := mach.SSSS.SetEncryptedAccountData(ctx, event.AccountDataCrossSigningMaster, keys.MasterKey.Seed, key); err != nil {
|
||||
if err := mach.SSSS.SetEncryptedAccountData(ctx, event.AccountDataCrossSigningMaster, keys.MasterKey.Seed(), key); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := mach.SSSS.SetEncryptedAccountData(ctx, event.AccountDataCrossSigningSelf, keys.SelfSigningKey.Seed, key); err != nil {
|
||||
if err := mach.SSSS.SetEncryptedAccountData(ctx, event.AccountDataCrossSigningSelf, keys.SelfSigningKey.Seed(), key); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := mach.SSSS.SetEncryptedAccountData(ctx, event.AccountDataCrossSigningUser, keys.UserSigningKey.Seed, key); err != nil {
|
||||
if err := mach.SSSS.SetEncryptedAccountData(ctx, event.AccountDataCrossSigningUser, keys.UserSigningKey.Seed(), key); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Also store these locally
|
||||
if err := mach.CryptoStore.PutCrossSigningKey(ctx, mach.Client.UserID, id.XSUsageMaster, keys.MasterKey.PublicKey); err != nil {
|
||||
if err := mach.CryptoStore.PutCrossSigningKey(ctx, mach.Client.UserID, id.XSUsageMaster, keys.MasterKey.PublicKey()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := mach.CryptoStore.PutCrossSigningKey(ctx, mach.Client.UserID, id.XSUsageSelfSigning, keys.SelfSigningKey.PublicKey); err != nil {
|
||||
if err := mach.CryptoStore.PutCrossSigningKey(ctx, mach.Client.UserID, id.XSUsageSelfSigning, keys.SelfSigningKey.PublicKey()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := mach.CryptoStore.PutCrossSigningKey(ctx, mach.Client.UserID, id.XSUsageUserSigning, keys.UserSigningKey.PublicKey); err != nil {
|
||||
if err := mach.CryptoStore.PutCrossSigningKey(ctx, mach.Client.UserID, id.XSUsageUserSigning, keys.UserSigningKey.PublicKey()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,13 +37,13 @@ func getOlmMachine(t *testing.T) *OlmMachine {
|
|||
}
|
||||
|
||||
userID := id.UserID("@mautrix")
|
||||
mk, _ := olm.NewPkSigning()
|
||||
ssk, _ := olm.NewPkSigning()
|
||||
usk, _ := olm.NewPkSigning()
|
||||
mk, _ := olm.NewPKSigning()
|
||||
ssk, _ := olm.NewPKSigning()
|
||||
usk, _ := olm.NewPKSigning()
|
||||
|
||||
sqlStore.PutCrossSigningKey(context.TODO(), userID, id.XSUsageMaster, mk.PublicKey)
|
||||
sqlStore.PutCrossSigningKey(context.TODO(), userID, id.XSUsageSelfSigning, ssk.PublicKey)
|
||||
sqlStore.PutCrossSigningKey(context.TODO(), userID, id.XSUsageUserSigning, usk.PublicKey)
|
||||
sqlStore.PutCrossSigningKey(context.TODO(), userID, id.XSUsageMaster, mk.PublicKey())
|
||||
sqlStore.PutCrossSigningKey(context.TODO(), userID, id.XSUsageSelfSigning, ssk.PublicKey())
|
||||
sqlStore.PutCrossSigningKey(context.TODO(), userID, id.XSUsageUserSigning, usk.PublicKey())
|
||||
|
||||
return &OlmMachine{
|
||||
CryptoStore: sqlStore,
|
||||
|
|
@ -70,10 +70,10 @@ func TestTrustOwnDevice(t *testing.T) {
|
|||
t.Error("Own device trusted while it shouldn't be")
|
||||
}
|
||||
|
||||
m.CryptoStore.PutSignature(context.TODO(), ownDevice.UserID, m.CrossSigningKeys.SelfSigningKey.PublicKey,
|
||||
ownDevice.UserID, m.CrossSigningKeys.MasterKey.PublicKey, "sig1")
|
||||
m.CryptoStore.PutSignature(context.TODO(), ownDevice.UserID, m.CrossSigningKeys.SelfSigningKey.PublicKey(),
|
||||
ownDevice.UserID, m.CrossSigningKeys.MasterKey.PublicKey(), "sig1")
|
||||
m.CryptoStore.PutSignature(context.TODO(), ownDevice.UserID, ownDevice.SigningKey,
|
||||
ownDevice.UserID, m.CrossSigningKeys.SelfSigningKey.PublicKey, "sig2")
|
||||
ownDevice.UserID, m.CrossSigningKeys.SelfSigningKey.PublicKey(), "sig2")
|
||||
|
||||
if trusted, _ := m.IsUserTrusted(context.TODO(), ownDevice.UserID); !trusted {
|
||||
t.Error("Own user not trusted while they should be")
|
||||
|
|
@ -90,22 +90,22 @@ func TestTrustOtherUser(t *testing.T) {
|
|||
t.Error("Other user trusted while they shouldn't be")
|
||||
}
|
||||
|
||||
theirMasterKey, _ := olm.NewPkSigning()
|
||||
m.CryptoStore.PutCrossSigningKey(context.TODO(), otherUser, id.XSUsageMaster, theirMasterKey.PublicKey)
|
||||
theirMasterKey, _ := olm.NewPKSigning()
|
||||
m.CryptoStore.PutCrossSigningKey(context.TODO(), otherUser, id.XSUsageMaster, theirMasterKey.PublicKey())
|
||||
|
||||
m.CryptoStore.PutSignature(context.TODO(), m.Client.UserID, m.CrossSigningKeys.UserSigningKey.PublicKey,
|
||||
m.Client.UserID, m.CrossSigningKeys.MasterKey.PublicKey, "sig1")
|
||||
m.CryptoStore.PutSignature(context.TODO(), m.Client.UserID, m.CrossSigningKeys.UserSigningKey.PublicKey(),
|
||||
m.Client.UserID, m.CrossSigningKeys.MasterKey.PublicKey(), "sig1")
|
||||
|
||||
// sign them with self-signing instead of user-signing key
|
||||
m.CryptoStore.PutSignature(context.TODO(), otherUser, theirMasterKey.PublicKey,
|
||||
m.Client.UserID, m.CrossSigningKeys.SelfSigningKey.PublicKey, "invalid_sig")
|
||||
m.CryptoStore.PutSignature(context.TODO(), otherUser, theirMasterKey.PublicKey(),
|
||||
m.Client.UserID, m.CrossSigningKeys.SelfSigningKey.PublicKey(), "invalid_sig")
|
||||
|
||||
if trusted, _ := m.IsUserTrusted(context.TODO(), otherUser); trusted {
|
||||
t.Error("Other user trusted before their master key has been signed with our user-signing key")
|
||||
}
|
||||
|
||||
m.CryptoStore.PutSignature(context.TODO(), otherUser, theirMasterKey.PublicKey,
|
||||
m.Client.UserID, m.CrossSigningKeys.UserSigningKey.PublicKey, "sig2")
|
||||
m.CryptoStore.PutSignature(context.TODO(), otherUser, theirMasterKey.PublicKey(),
|
||||
m.Client.UserID, m.CrossSigningKeys.UserSigningKey.PublicKey(), "sig2")
|
||||
|
||||
if trusted, _ := m.IsUserTrusted(context.TODO(), otherUser); !trusted {
|
||||
t.Error("Other user not trusted while they should be")
|
||||
|
|
@ -127,29 +127,29 @@ func TestTrustOtherDevice(t *testing.T) {
|
|||
t.Error("Other device trusted while it shouldn't be")
|
||||
}
|
||||
|
||||
theirMasterKey, _ := olm.NewPkSigning()
|
||||
m.CryptoStore.PutCrossSigningKey(context.TODO(), otherUser, id.XSUsageMaster, theirMasterKey.PublicKey)
|
||||
theirSSK, _ := olm.NewPkSigning()
|
||||
m.CryptoStore.PutCrossSigningKey(context.TODO(), otherUser, id.XSUsageSelfSigning, theirSSK.PublicKey)
|
||||
theirMasterKey, _ := olm.NewPKSigning()
|
||||
m.CryptoStore.PutCrossSigningKey(context.TODO(), otherUser, id.XSUsageMaster, theirMasterKey.PublicKey())
|
||||
theirSSK, _ := olm.NewPKSigning()
|
||||
m.CryptoStore.PutCrossSigningKey(context.TODO(), otherUser, id.XSUsageSelfSigning, theirSSK.PublicKey())
|
||||
|
||||
m.CryptoStore.PutSignature(context.TODO(), m.Client.UserID, m.CrossSigningKeys.UserSigningKey.PublicKey,
|
||||
m.Client.UserID, m.CrossSigningKeys.MasterKey.PublicKey, "sig1")
|
||||
m.CryptoStore.PutSignature(context.TODO(), otherUser, theirMasterKey.PublicKey,
|
||||
m.Client.UserID, m.CrossSigningKeys.UserSigningKey.PublicKey, "sig2")
|
||||
m.CryptoStore.PutSignature(context.TODO(), m.Client.UserID, m.CrossSigningKeys.UserSigningKey.PublicKey(),
|
||||
m.Client.UserID, m.CrossSigningKeys.MasterKey.PublicKey(), "sig1")
|
||||
m.CryptoStore.PutSignature(context.TODO(), otherUser, theirMasterKey.PublicKey(),
|
||||
m.Client.UserID, m.CrossSigningKeys.UserSigningKey.PublicKey(), "sig2")
|
||||
|
||||
if trusted, _ := m.IsUserTrusted(context.TODO(), otherUser); !trusted {
|
||||
t.Error("Other user not trusted while they should be")
|
||||
}
|
||||
|
||||
m.CryptoStore.PutSignature(context.TODO(), otherUser, theirSSK.PublicKey,
|
||||
otherUser, theirMasterKey.PublicKey, "sig3")
|
||||
m.CryptoStore.PutSignature(context.TODO(), otherUser, theirSSK.PublicKey(),
|
||||
otherUser, theirMasterKey.PublicKey(), "sig3")
|
||||
|
||||
if m.IsDeviceTrusted(theirDevice) {
|
||||
t.Error("Other device trusted before it has been signed with user's SSK")
|
||||
}
|
||||
|
||||
m.CryptoStore.PutSignature(context.TODO(), otherUser, theirDevice.SigningKey,
|
||||
otherUser, theirSSK.PublicKey, "sig4")
|
||||
otherUser, theirSSK.PublicKey(), "sig4")
|
||||
|
||||
if !m.IsDeviceTrusted(theirDevice) {
|
||||
t.Error("Other device not trusted while it should be")
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@ func NewDecryptionFromPrivate(privateKey crypto.Curve25519PrivateKey) (*Decrypti
|
|||
return s, nil
|
||||
}
|
||||
|
||||
// PubKey returns the public key base 64 encoded.
|
||||
func (s Decryption) PubKey() id.Curve25519 {
|
||||
// PublicKey returns the public key base 64 encoded.
|
||||
func (s Decryption) PublicKey() id.Curve25519 {
|
||||
return s.KeyPair.B64Encoded()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,14 +30,14 @@ func TestEncryptionDecryption(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal([]byte(decryption.PubKey()), alicePublic) {
|
||||
if !bytes.Equal([]byte(decryption.PublicKey()), alicePublic) {
|
||||
t.Fatal("public key not correct")
|
||||
}
|
||||
if !bytes.Equal(decryption.PrivateKey(), alicePrivate) {
|
||||
t.Fatal("private key not correct")
|
||||
}
|
||||
|
||||
encryption, err := pk.NewEncryption(decryption.PubKey())
|
||||
encryption, err := pk.NewEncryption(decryption.PublicKey())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -66,7 +66,10 @@ func TestSigning(t *testing.T) {
|
|||
}
|
||||
message := []byte("We hold these truths to be self-evident, that all men are created equal, that they are endowed by their Creator with certain unalienable Rights, that among these are Life, Liberty and the pursuit of Happiness.")
|
||||
signing, _ := pk.NewSigningFromSeed(seed)
|
||||
signature := signing.Sign(message)
|
||||
signature, err := signing.Sign(message)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
signatureDecoded, err := goolm.Base64Decode(signature)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
@ -101,7 +104,7 @@ func TestDecryptionPickling(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal([]byte(decryption.PubKey()), alicePublic) {
|
||||
if !bytes.Equal([]byte(decryption.PublicKey()), alicePublic) {
|
||||
t.Fatal("public key not correct")
|
||||
}
|
||||
if !bytes.Equal(decryption.PrivateKey(), alicePrivate) {
|
||||
|
|
@ -125,7 +128,7 @@ func TestDecryptionPickling(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal([]byte(newDecription.PubKey()), alicePublic) {
|
||||
if !bytes.Equal([]byte(newDecription.PublicKey()), alicePublic) {
|
||||
t.Fatal("public key not correct")
|
||||
}
|
||||
if !bytes.Equal(newDecription.PrivateKey(), alicePrivate) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,11 @@ package pk
|
|||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/tidwall/sjson"
|
||||
|
||||
"maunium.net/go/mautrix/crypto/canonicaljson"
|
||||
"maunium.net/go/mautrix/crypto/goolm"
|
||||
"maunium.net/go/mautrix/crypto/goolm/crypto"
|
||||
"maunium.net/go/mautrix/id"
|
||||
|
|
@ -10,15 +14,15 @@ import (
|
|||
|
||||
// Signing is used for signing a pk
|
||||
type Signing struct {
|
||||
KeyPair crypto.Ed25519KeyPair `json:"key_pair"`
|
||||
Seed []byte `json:"seed"`
|
||||
keyPair crypto.Ed25519KeyPair
|
||||
seed []byte
|
||||
}
|
||||
|
||||
// NewSigningFromSeed constructs a new Signing based on a seed.
|
||||
func NewSigningFromSeed(seed []byte) (*Signing, error) {
|
||||
s := &Signing{}
|
||||
s.Seed = seed
|
||||
s.KeyPair = crypto.Ed25519GenerateFromSeed(seed)
|
||||
s.seed = seed
|
||||
s.keyPair = crypto.Ed25519GenerateFromSeed(seed)
|
||||
return s, nil
|
||||
}
|
||||
|
||||
|
|
@ -32,13 +36,34 @@ func NewSigning() (*Signing, error) {
|
|||
return NewSigningFromSeed(seed)
|
||||
}
|
||||
|
||||
// Sign returns the signature of the message base64 encoded.
|
||||
func (s Signing) Sign(message []byte) []byte {
|
||||
signature := s.KeyPair.Sign(message)
|
||||
return goolm.Base64Encode(signature)
|
||||
// Seed returns the seed of the key pair.
|
||||
func (s Signing) Seed() []byte {
|
||||
return s.seed
|
||||
}
|
||||
|
||||
// PublicKey returns the public key of the key pair base 64 encoded.
|
||||
func (s Signing) PublicKey() id.Ed25519 {
|
||||
return s.KeyPair.B64Encoded()
|
||||
return s.keyPair.B64Encoded()
|
||||
}
|
||||
|
||||
// Sign returns the signature of the message base64 encoded.
|
||||
func (s Signing) Sign(message []byte) ([]byte, error) {
|
||||
signature := s.keyPair.Sign(message)
|
||||
return goolm.Base64Encode(signature), nil
|
||||
}
|
||||
|
||||
// SignJSON creates a signature for the given object after encoding it to
|
||||
// canonical JSON.
|
||||
func (s Signing) SignJSON(obj any) (string, error) {
|
||||
objJSON, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
objJSON, _ = sjson.DeleteBytes(objJSON, "unsigned")
|
||||
objJSON, _ = sjson.DeleteBytes(objJSON, "signatures")
|
||||
signature, err := s.Sign(canonicaljson.CanonicalJSONAssumeValid(objJSON))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(signature), nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,71 +1,29 @@
|
|||
// Copyright (c) 2024 Sumner Evans
|
||||
//
|
||||
// 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/.
|
||||
|
||||
// When the goolm build flag is enabled, this file will make [PKSigning]
|
||||
// constructors use the goolm constuctors.
|
||||
|
||||
//go:build goolm
|
||||
|
||||
package olm
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
import "maunium.net/go/mautrix/crypto/goolm/pk"
|
||||
|
||||
"github.com/tidwall/sjson"
|
||||
|
||||
"maunium.net/go/mautrix/crypto/canonicaljson"
|
||||
"maunium.net/go/mautrix/crypto/goolm/pk"
|
||||
"maunium.net/go/mautrix/id"
|
||||
)
|
||||
|
||||
// PkSigning stores a key pair for signing messages.
|
||||
type PkSigning struct {
|
||||
pk.Signing
|
||||
PublicKey id.Ed25519
|
||||
Seed []byte
|
||||
// NewPKSigningFromSeed creates a new PKSigning object using the given seed.
|
||||
func NewPKSigningFromSeed(seed []byte) (PKSigning, error) {
|
||||
return pk.NewSigningFromSeed(seed)
|
||||
}
|
||||
|
||||
// Clear clears the underlying memory of a PkSigning object.
|
||||
func (p *PkSigning) Clear() {
|
||||
p.Signing = pk.Signing{}
|
||||
// NewPKSigning creates a new [PKSigning] object, containing a key pair for
|
||||
// signing messages.
|
||||
func NewPKSigning() (PKSigning, error) {
|
||||
return pk.NewSigning()
|
||||
}
|
||||
|
||||
// NewPkSigningFromSeed creates a new PkSigning object using the given seed.
|
||||
func NewPkSigningFromSeed(seed []byte) (*PkSigning, error) {
|
||||
p := &PkSigning{}
|
||||
signing, err := pk.NewSigningFromSeed(seed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.Signing = *signing
|
||||
p.Seed = seed
|
||||
p.PublicKey = p.Signing.PublicKey()
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// NewPkSigning creates a new PkSigning object, containing a key pair for signing messages.
|
||||
func NewPkSigning() (*PkSigning, error) {
|
||||
p := &PkSigning{}
|
||||
signing, err := pk.NewSigning()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.Signing = *signing
|
||||
p.Seed = signing.Seed
|
||||
p.PublicKey = p.Signing.PublicKey()
|
||||
return p, err
|
||||
}
|
||||
|
||||
// Sign creates a signature for the given message using this key.
|
||||
func (p *PkSigning) Sign(message []byte) ([]byte, error) {
|
||||
return p.Signing.Sign(message), nil
|
||||
}
|
||||
|
||||
// SignJSON creates a signature for the given object after encoding it to canonical JSON.
|
||||
func (p *PkSigning) 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")
|
||||
signature, err := p.Sign(canonicaljson.CanonicalJSONAssumeValid(objJSON))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(signature), nil
|
||||
func NewPKDecryption(privateKey []byte) (PKDecryption, error) {
|
||||
return pk.NewDecryption()
|
||||
}
|
||||
|
|
|
|||
41
crypto/olm/pk_interface.go
Normal file
41
crypto/olm/pk_interface.go
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright (c) 2024 Sumner Evans
|
||||
//
|
||||
// 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 olm
|
||||
|
||||
import (
|
||||
"maunium.net/go/mautrix/crypto/goolm/pk"
|
||||
"maunium.net/go/mautrix/id"
|
||||
)
|
||||
|
||||
// PKSigning is an interface for signing messages.
|
||||
type PKSigning interface {
|
||||
// Seed returns the seed of the key.
|
||||
Seed() []byte
|
||||
|
||||
// PublicKey returns the public key.
|
||||
PublicKey() id.Ed25519
|
||||
|
||||
// Sign creates a signature for the given message using this key.
|
||||
Sign(message []byte) ([]byte, error)
|
||||
|
||||
// SignJSON creates a signature for the given object after encoding it to
|
||||
// canonical JSON.
|
||||
SignJSON(obj any) (string, error)
|
||||
}
|
||||
|
||||
var _ PKSigning = (*pk.Signing)(nil)
|
||||
|
||||
// PKDecryption is an interface for decrypting messages.
|
||||
type PKDecryption interface {
|
||||
// PublicKey returns the public key.
|
||||
PublicKey() id.Curve25519
|
||||
|
||||
// Decrypt verifies and decrypts the given message.
|
||||
Decrypt(ciphertext, mac []byte, key id.Curve25519) ([]byte, error)
|
||||
}
|
||||
|
||||
var _ PKDecryption = (*pk.Decryption)(nil)
|
||||
|
|
@ -1,3 +1,9 @@
|
|||
// Copyright (c) 2024 Sumner Evans
|
||||
//
|
||||
// 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/.
|
||||
|
||||
//go:build !goolm
|
||||
|
||||
package olm
|
||||
|
|
@ -18,14 +24,17 @@ import (
|
|||
"maunium.net/go/mautrix/id"
|
||||
)
|
||||
|
||||
// PkSigning stores a key pair for signing messages.
|
||||
type PkSigning struct {
|
||||
// LibOlmPKSigning stores a key pair for signing messages.
|
||||
type LibOlmPKSigning struct {
|
||||
int *C.OlmPkSigning
|
||||
mem []byte
|
||||
PublicKey id.Ed25519
|
||||
Seed []byte
|
||||
publicKey id.Ed25519
|
||||
seed []byte
|
||||
}
|
||||
|
||||
// Ensure that LibOlmPKSigning implements PKSigning.
|
||||
var _ PKSigning = (*LibOlmPKSigning)(nil)
|
||||
|
||||
func pkSigningSize() uint {
|
||||
return uint(C.olm_pk_signing_size())
|
||||
}
|
||||
|
|
@ -42,48 +51,57 @@ func pkSigningSignatureLength() uint {
|
|||
return uint(C.olm_pk_signature_length())
|
||||
}
|
||||
|
||||
func NewBlankPkSigning() *PkSigning {
|
||||
func newBlankPKSigning() *LibOlmPKSigning {
|
||||
memory := make([]byte, pkSigningSize())
|
||||
return &PkSigning{
|
||||
return &LibOlmPKSigning{
|
||||
int: C.olm_pk_signing(unsafe.Pointer(&memory[0])),
|
||||
mem: memory,
|
||||
}
|
||||
}
|
||||
|
||||
// Clear clears the underlying memory of a PkSigning object.
|
||||
func (p *PkSigning) Clear() {
|
||||
C.olm_clear_pk_signing((*C.OlmPkSigning)(p.int))
|
||||
}
|
||||
|
||||
// NewPkSigningFromSeed creates a new PkSigning object using the given seed.
|
||||
func NewPkSigningFromSeed(seed []byte) (*PkSigning, error) {
|
||||
p := NewBlankPkSigning()
|
||||
p.Clear()
|
||||
// NewPKSigningFromSeed creates a new [PKSigning] object using the given seed.
|
||||
func NewPKSigningFromSeed(seed []byte) (PKSigning, error) {
|
||||
p := newBlankPKSigning()
|
||||
p.clear()
|
||||
pubKey := make([]byte, pkSigningPublicKeyLength())
|
||||
if C.olm_pk_signing_key_from_seed((*C.OlmPkSigning)(p.int),
|
||||
unsafe.Pointer(&pubKey[0]), C.size_t(len(pubKey)),
|
||||
unsafe.Pointer(&seed[0]), C.size_t(len(seed))) == errorVal() {
|
||||
return nil, p.lastError()
|
||||
}
|
||||
p.PublicKey = id.Ed25519(pubKey)
|
||||
p.Seed = seed
|
||||
p.publicKey = id.Ed25519(pubKey)
|
||||
p.seed = seed
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// NewPkSigning creates a new PkSigning object, containing a key pair for signing messages.
|
||||
func NewPkSigning() (*PkSigning, error) {
|
||||
// NewPKSigning creates a new LibOlmPKSigning object, containing a key pair for
|
||||
// signing messages.
|
||||
func NewPKSigning() (PKSigning, error) {
|
||||
// Generate the seed
|
||||
seed := make([]byte, pkSigningSeedLength())
|
||||
_, err := rand.Read(seed)
|
||||
if err != nil {
|
||||
panic(NotEnoughGoRandom)
|
||||
}
|
||||
pk, err := NewPkSigningFromSeed(seed)
|
||||
pk, err := NewPKSigningFromSeed(seed)
|
||||
return pk, err
|
||||
}
|
||||
|
||||
func (p *LibOlmPKSigning) PublicKey() id.Ed25519 {
|
||||
return p.publicKey
|
||||
}
|
||||
|
||||
func (p *LibOlmPKSigning) Seed() []byte {
|
||||
return p.seed
|
||||
}
|
||||
|
||||
// clear clears the underlying memory of a LibOlmPKSigning object.
|
||||
func (p *LibOlmPKSigning) clear() {
|
||||
C.olm_clear_pk_signing((*C.OlmPkSigning)(p.int))
|
||||
}
|
||||
|
||||
// Sign creates a signature for the given message using this key.
|
||||
func (p *PkSigning) Sign(message []byte) ([]byte, error) {
|
||||
func (p *LibOlmPKSigning) Sign(message []byte) ([]byte, error) {
|
||||
signature := make([]byte, pkSigningSignatureLength())
|
||||
if C.olm_pk_sign((*C.OlmPkSigning)(p.int), (*C.uint8_t)(unsafe.Pointer(&message[0])), C.size_t(len(message)),
|
||||
(*C.uint8_t)(unsafe.Pointer(&signature[0])), C.size_t(len(signature))) == errorVal() {
|
||||
|
|
@ -93,7 +111,7 @@ func (p *PkSigning) Sign(message []byte) ([]byte, error) {
|
|||
}
|
||||
|
||||
// SignJSON creates a signature for the given object after encoding it to canonical JSON.
|
||||
func (p *PkSigning) SignJSON(obj interface{}) (string, error) {
|
||||
func (p *LibOlmPKSigning) SignJSON(obj interface{}) (string, error) {
|
||||
objJSON, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
|
@ -107,12 +125,13 @@ func (p *PkSigning) SignJSON(obj interface{}) (string, error) {
|
|||
return string(signature), nil
|
||||
}
|
||||
|
||||
// lastError returns the last error that happened in relation to this PkSigning object.
|
||||
func (p *PkSigning) lastError() error {
|
||||
// lastError returns the last error that happened in relation to this
|
||||
// LibOlmPKSigning object.
|
||||
func (p *LibOlmPKSigning) lastError() error {
|
||||
return convertError(C.GoString(C.olm_pk_signing_last_error((*C.OlmPkSigning)(p.int))))
|
||||
}
|
||||
|
||||
type PkDecryption struct {
|
||||
type LibOlmPKDecryption struct {
|
||||
int *C.OlmPkDecryption
|
||||
mem []byte
|
||||
PublicKey []byte
|
||||
|
|
@ -126,13 +145,13 @@ func pkDecryptionPublicKeySize() uint {
|
|||
return uint(C.olm_pk_key_length())
|
||||
}
|
||||
|
||||
func NewPkDecryption(privateKey []byte) (*PkDecryption, error) {
|
||||
func NewPkDecryption(privateKey []byte) (*LibOlmPKDecryption, error) {
|
||||
memory := make([]byte, pkDecryptionSize())
|
||||
p := &PkDecryption{
|
||||
p := &LibOlmPKDecryption{
|
||||
int: C.olm_pk_decryption(unsafe.Pointer(&memory[0])),
|
||||
mem: memory,
|
||||
}
|
||||
p.Clear()
|
||||
p.clear()
|
||||
pubKey := make([]byte, pkDecryptionPublicKeySize())
|
||||
|
||||
if C.olm_pk_key_from_private((*C.OlmPkDecryption)(p.int),
|
||||
|
|
@ -145,7 +164,7 @@ func NewPkDecryption(privateKey []byte) (*PkDecryption, error) {
|
|||
return p, nil
|
||||
}
|
||||
|
||||
func (p *PkDecryption) Decrypt(ephemeralKey []byte, mac []byte, ciphertext []byte) ([]byte, error) {
|
||||
func (p *LibOlmPKDecryption) Decrypt(ephemeralKey []byte, mac []byte, ciphertext []byte) ([]byte, error) {
|
||||
maxPlaintextLength := uint(C.olm_pk_max_plaintext_length((*C.OlmPkDecryption)(p.int), C.size_t(len(ciphertext))))
|
||||
plaintext := make([]byte, maxPlaintextLength)
|
||||
|
||||
|
|
@ -162,11 +181,12 @@ func (p *PkDecryption) Decrypt(ephemeralKey []byte, mac []byte, ciphertext []byt
|
|||
}
|
||||
|
||||
// Clear clears the underlying memory of a PkDecryption object.
|
||||
func (p *PkDecryption) Clear() {
|
||||
func (p *LibOlmPKDecryption) clear() {
|
||||
C.olm_clear_pk_decryption((*C.OlmPkDecryption)(p.int))
|
||||
}
|
||||
|
||||
// lastError returns the last error that happened in relation to this PkDecryption object.
|
||||
func (p *PkDecryption) lastError() error {
|
||||
// lastError returns the last error that happened in relation to this
|
||||
// LibOlmPKDecryption object.
|
||||
func (p *LibOlmPKDecryption) lastError() error {
|
||||
return convertError(C.GoString(C.olm_pk_decryption_last_error((*C.OlmPkDecryption)(p.int))))
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue