From 23b2437ad1ddc79345dcedbb79342b366391cdf8 Mon Sep 17 00:00:00 2001 From: Martin Dosch Date: Thu, 28 Apr 2022 11:35:14 +0200 Subject: [PATCH] Ox: Also publish pubkey for imported privkeys Check whether the public key is already in pubsub, if not publish it. --- ox.go | 195 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 109 insertions(+), 86 deletions(-) diff --git a/ox.go b/ox.go index e536903..321096c 100644 --- a/ox.go +++ b/ox.go @@ -61,6 +61,112 @@ func oxImportPrivKey(jid string, privKeyLocation string, client *xmpp.Client) er if err != nil { log.Fatal(err) } + pubKeyRing, err := oxGetPublicKeyRing(client, jid) + if err == nil { + pubKeys := pubKeyRing.GetKeys() + for _, r := range pubKeys { + if strings.ToUpper(r.GetFingerprint()) == fingerprint { + return nil + } + } + } + err = oxPublishPubKey(jid, client, pubKey) + if err != nil { + return err + } + return nil +} + +func oxPublishPubKey(jid string, client *xmpp.Client, pubKey *crypto.Key) error { + keyCreated := time.Now().UTC().Format("2006-01-02T15:04:05Z") + fingerprint := strings.ToUpper(pubKey.GetFingerprint()) + keySerialized, err := pubKey.Serialize() + if err != nil { + return err + } + pubKeyBase64 := base64.StdEncoding.EncodeToString(keySerialized) + root := etree.NewDocument() + pubsub := root.CreateElement("pubsub") + pubsub.CreateAttr("xmlns", nsPubsub) + publish := pubsub.CreateElement("publish") + publish.CreateAttr("node", nsOxPubKeys+":"+fingerprint) + item := publish.CreateElement("item") + item.CreateAttr("id", keyCreated) + pubkey := item.CreateElement("pubkey") + pubkey.CreateAttr("xmlns", nsOx) + data := pubkey.CreateElement("data") + data.CreateText(pubKeyBase64) + publishoptions := pubsub.CreateElement("publish-options") + x := publishoptions.CreateElement("x") + x.CreateAttr("xmlns", nsJabberData) + x.CreateAttr("type", "submit") + field := x.CreateElement("field") + field.CreateAttr("var", "FORM_TYPE") + field.CreateAttr("type", "hidden") + value := field.CreateElement("value") + value.CreateText(pubsubPubOptions) + field = x.CreateElement("field") + field.CreateAttr("var", "pubsub#access_model") + value = field.CreateElement("value") + value.CreateText("open") + xmlstring, err := root.WriteToString() + if err != nil { + return err + } + iqReply, err := sendIQ(client, jid, "set", xmlstring) + if err != nil { + return err + } + if iqReply.Type != "result" { + return errors.New("Error while publishing public key") + } + ownPubKeyRingFromPubsub, err := oxRecvPublicKeys(client, jid, fingerprint) + if err != nil { + return errors.New("Couldn't successfully verify public key upload") + } + ownPubKeyFromPubsub := ownPubKeyRingFromPubsub.GetKeys()[0] + ownPubKeyFromPubsubSerialized, err := ownPubKeyFromPubsub.Serialize() + if err != nil { + return errors.New("Couldn't successfully verify public key upload") + } + if pubKeyBase64 != base64.StdEncoding.EncodeToString(ownPubKeyFromPubsubSerialized) { + return errors.New("Couldn't successfully verify public key upload") + } + root = etree.NewDocument() + pubsub = root.CreateElement("pubsub") + pubsub.CreateAttr("xmlns", nsPubsub) + publish = pubsub.CreateElement("publish") + publish.CreateAttr("node", nsOxPubKeys) + item = publish.CreateElement("item") + pubkeyslist := item.CreateElement("public-keys-list") + pubkeyslist.CreateAttr("xmlns", nsOx) + pubkeymeta := pubkeyslist.CreateElement("pubkey-metadata") + pubkeymeta.CreateAttr("v4-fingerprint", fingerprint) + pubkeymeta.CreateAttr("date", keyCreated) + publishoptions = pubsub.CreateElement("publish-options") + x = publishoptions.CreateElement("x") + x.CreateAttr("xmlns", nsJabberData) + x.CreateAttr("type", "submit") + field = x.CreateElement("field") + field.CreateAttr("var", "FORM_TYPE") + field.CreateAttr("type", "hidden") + value = field.CreateElement("value") + value.CreateText(pubsubPubOptions) + field = x.CreateElement("field") + field.CreateAttr("var", "pubsub#access_model") + value = field.CreateElement("value") + value.CreateText("open") + xmlstring, err = root.WriteToString() + if err != nil { + return err + } + iqReply, err = sendIQ(client, jid, "set", xmlstring) + if err != nil { + return err + } + if iqReply.Type != "result" { + return errors.New("Couldn't publish public key list") + } return nil } @@ -193,11 +299,6 @@ func oxGenPrivKey(jid string, client *xmpp.Client, passphrase string, if err != nil { return err } - decodedPubKey, err := key.GetPublicKey() - if err != nil { - return err - } - pubKeyBase64 := base64.StdEncoding.EncodeToString(decodedPubKey) if passphrase != "" { key, err = key.Lock([]byte(passphrase)) if err != nil { @@ -217,96 +318,18 @@ func oxGenPrivKey(jid string, client *xmpp.Client, passphrase string, if err != nil { log.Fatal(err) } - keyCreated := time.Now().UTC().Format("2006-01-02T15:04:05Z") - pubKey, err := crypto.NewKey(decodedPubKey) - if err != nil { - return err - } - fingerprint := strings.ToUpper(pubKey.GetFingerprint()) - root := etree.NewDocument() - pubsub := root.CreateElement("pubsub") - pubsub.CreateAttr("xmlns", nsPubsub) - publish := pubsub.CreateElement("publish") - publish.CreateAttr("node", nsOxPubKeys+":"+fingerprint) - item := publish.CreateElement("item") - item.CreateAttr("id", keyCreated) - pubkey := item.CreateElement("pubkey") - pubkey.CreateAttr("xmlns", nsOx) - data := pubkey.CreateElement("data") - data.CreateText(pubKeyBase64) - publishoptions := pubsub.CreateElement("publish-options") - x := publishoptions.CreateElement("x") - x.CreateAttr("xmlns", nsJabberData) - x.CreateAttr("type", "submit") - field := x.CreateElement("field") - field.CreateAttr("var", "FORM_TYPE") - field.CreateAttr("type", "hidden") - value := field.CreateElement("value") - value.CreateText(pubsubPubOptions) - field = x.CreateElement("field") - field.CreateAttr("var", "pubsub#access_model") - value = field.CreateElement("value") - value.CreateText("open") - xmlstring, err := root.WriteToString() - if err != nil { - return err - } - iqReply, err := sendIQ(client, jid, "set", xmlstring) + decodedPubKey, err := key.GetPublicKey() if err != nil { return err } - if iqReply.Type != "result" { - return errors.New("Error while publishing public key") - } - - ownPubKeyRingFromPubsub, err := oxRecvPublicKeys(client, jid, fingerprint) - if err != nil { - return errors.New("Couldn't successfully verify public key upload") - } - ownPubKeyFromPubsub := ownPubKeyRingFromPubsub.GetKeys()[0] - ownPubKeyFromPubsubSerialized, err := ownPubKeyFromPubsub.Serialize() - if err != nil { - return errors.New("Couldn't successfully verify public key upload") - } - if pubKeyBase64 != base64.StdEncoding.EncodeToString(ownPubKeyFromPubsubSerialized) { - return errors.New("Couldn't successfully verify public key upload") - } - - root = etree.NewDocument() - pubsub = root.CreateElement("pubsub") - pubsub.CreateAttr("xmlns", nsPubsub) - publish = pubsub.CreateElement("publish") - publish.CreateAttr("node", nsOxPubKeys) - item = publish.CreateElement("item") - pubkeyslist := item.CreateElement("public-keys-list") - pubkeyslist.CreateAttr("xmlns", nsOx) - pubkeymeta := pubkeyslist.CreateElement("pubkey-metadata") - pubkeymeta.CreateAttr("v4-fingerprint", fingerprint) - pubkeymeta.CreateAttr("date", keyCreated) - publishoptions = pubsub.CreateElement("publish-options") - x = publishoptions.CreateElement("x") - x.CreateAttr("xmlns", nsJabberData) - x.CreateAttr("type", "submit") - field = x.CreateElement("field") - field.CreateAttr("var", "FORM_TYPE") - field.CreateAttr("type", "hidden") - value = field.CreateElement("value") - value.CreateText(pubsubPubOptions) - field = x.CreateElement("field") - field.CreateAttr("var", "pubsub#access_model") - value = field.CreateElement("value") - value.CreateText("open") - xmlstring, err = root.WriteToString() + pubKey, err := crypto.NewKey(decodedPubKey) if err != nil { return err } - iqReply, err = sendIQ(client, jid, "set", xmlstring) + err = oxPublishPubKey(jid, client, pubKey) if err != nil { return err } - if iqReply.Type != "result" { - return errors.New("Couldn't publish public key list") - } return nil }