|
|
|
@ -25,16 +25,16 @@ func oxDeleteNodes(jid string, client *xmpp.Client, iqc chan xmpp.IQ) error {
|
|
|
|
|
query := nodeListRequest.CreateElement("query")
|
|
|
|
|
query.CreateAttr("xmlns", nsDiscoItems)
|
|
|
|
|
nlr, err := nodeListRequest.WriteToString()
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxDeleteNodes: failed to create node list request %w", err)
|
|
|
|
|
}
|
|
|
|
|
iqReply, err := sendIQ(client, iqc, jid, "get", nlr)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxDeleteNodes: failure with node list request iq: %w", err)
|
|
|
|
|
}
|
|
|
|
|
nodeListReply := etree.NewDocument()
|
|
|
|
|
err = nodeListReply.ReadFromBytes(iqReply.Query)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxDeleteNodes: failed to read node list reply iq: %w", err)
|
|
|
|
|
}
|
|
|
|
|
query = nodeListReply.SelectElement("query")
|
|
|
|
@ -60,11 +60,11 @@ func oxDeleteNodes(jid string, client *xmpp.Client, iqc chan xmpp.IQ) error {
|
|
|
|
|
del := pubsub.CreateElement("delete")
|
|
|
|
|
del.CreateAttr("node", node.Value)
|
|
|
|
|
dnr, err := deleteNodeRequest.WriteToString()
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
_, err = sendIQ(client, iqc, jid, "set", dnr)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -78,7 +78,7 @@ func oxDecrypt(m xmpp.Chat, client *xmpp.Client, iqc chan xmpp.IQ, user string,
|
|
|
|
|
for _, r := range m.OtherElem {
|
|
|
|
|
if r.XMLName.Space == nsOx {
|
|
|
|
|
cryptMsgByte, err = base64.StdEncoding.DecodeString(r.InnerXML)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return strError, time.Now(), err
|
|
|
|
|
}
|
|
|
|
|
break
|
|
|
|
@ -86,22 +86,22 @@ func oxDecrypt(m xmpp.Chat, client *xmpp.Client, iqc chan xmpp.IQ, user string,
|
|
|
|
|
}
|
|
|
|
|
oxMsg := crypto.NewPGPMessage(cryptMsgByte)
|
|
|
|
|
keyRing, err := crypto.NewKeyRing(oxPrivKey)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return strError, time.Now(), err
|
|
|
|
|
}
|
|
|
|
|
senderKeyRing, err := oxGetPublicKeyRing(client, iqc, sender)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return strError, time.Now(), err
|
|
|
|
|
}
|
|
|
|
|
decryptMsg, err := keyRing.Decrypt(oxMsg, senderKeyRing, crypto.GetUnixTime())
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return strError, time.Now(), err
|
|
|
|
|
}
|
|
|
|
|
// Remove invalid code points.
|
|
|
|
|
message := validUTF8(string(decryptMsg.Data))
|
|
|
|
|
doc := etree.NewDocument()
|
|
|
|
|
err = doc.ReadFromString(message)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return strError, time.Now(), err
|
|
|
|
|
}
|
|
|
|
|
signcrypt := doc.SelectElement("signcrypt")
|
|
|
|
@ -128,7 +128,7 @@ func oxDecrypt(m xmpp.Chat, client *xmpp.Client, iqc chan xmpp.IQ, user string,
|
|
|
|
|
return strError, time.Now(), errors.New("ox: no stamp attribute")
|
|
|
|
|
}
|
|
|
|
|
msgStamp, err := time.Parse("2006-01-02T15:04:05Z0700", stamp.Value)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return strError, time.Now(), err
|
|
|
|
|
}
|
|
|
|
|
payload := signcrypt.SelectElement("payload")
|
|
|
|
@ -154,19 +154,19 @@ func isOxMsg(m xmpp.Chat) bool {
|
|
|
|
|
func oxImportPrivKey(jid string, privKeyLocation string, client *xmpp.Client, iqc chan xmpp.IQ) error {
|
|
|
|
|
xmppURI := "xmpp:" + jid
|
|
|
|
|
buffer, err := readFile(privKeyLocation)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
key, err := crypto.NewKey(buffer.Bytes())
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
key, err = crypto.NewKeyFromArmored(buffer.String())
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
keyDecoded, err := base64.StdEncoding.DecodeString(buffer.String())
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxImportPrivKey: failed to import private key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
key, err = crypto.NewKey(keyDecoded)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxImportPrivKey: failed to import private key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -176,36 +176,36 @@ func oxImportPrivKey(jid string, privKeyLocation string, client *xmpp.Client, iq
|
|
|
|
|
return errors.New("Key identity is not " + xmppURI)
|
|
|
|
|
}
|
|
|
|
|
pk, err := key.GetPublicKey()
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxImportPrivKey: failed to get public key associated to private key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
pubKey, err := crypto.NewKey(pk)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxImportPrivKey: failed to get public key associated to private key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
fingerprint := strings.ToUpper(pubKey.GetFingerprint())
|
|
|
|
|
_, err = oxRecvPublicKeys(client, iqc, jid, fingerprint)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
err = oxPublishPubKey(jid, client, iqc, pubKey)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxImportPrivKey: failed to publish public key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
location, err := oxGetPrivKeyLoc(jid)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxImportPrivKey: failed to determine private key location: %w", err)
|
|
|
|
|
}
|
|
|
|
|
keySerialized, err := key.Serialize()
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxImportPrivKey: failed to serialize private key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
err = oxStoreKey(location,
|
|
|
|
|
base64.StdEncoding.EncodeToString(keySerialized))
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
pubKeyRing, err := oxGetPublicKeyRing(client, iqc, jid)
|
|
|
|
|
if errors.Unwrap(err) == nil {
|
|
|
|
|
if err == nil {
|
|
|
|
|
pubKeys := pubKeyRing.GetKeys()
|
|
|
|
|
for _, r := range pubKeys {
|
|
|
|
|
if strings.ToUpper(r.GetFingerprint()) == fingerprint {
|
|
|
|
@ -214,7 +214,7 @@ func oxImportPrivKey(jid string, privKeyLocation string, client *xmpp.Client, iq
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
err = oxPublishPubKey(jid, client, iqc, pubKey)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxImportPrivKey: failed to publish public key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
@ -224,7 +224,7 @@ func oxPublishPubKey(jid string, client *xmpp.Client, iqc chan xmpp.IQ, pubKey *
|
|
|
|
|
keyCreated := time.Now().UTC().Format("2006-01-02T15:04:05Z")
|
|
|
|
|
fingerprint := strings.ToUpper(pubKey.GetFingerprint())
|
|
|
|
|
keySerialized, err := pubKey.Serialize()
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxPublishPubKey: failed to serialize pubkey: %w", err)
|
|
|
|
|
}
|
|
|
|
|
pubKeyBase64 := base64.StdEncoding.EncodeToString(keySerialized)
|
|
|
|
@ -254,23 +254,23 @@ func oxPublishPubKey(jid string, client *xmpp.Client, iqc chan xmpp.IQ, pubKey *
|
|
|
|
|
value = field.CreateElement("value")
|
|
|
|
|
value.CreateText("open")
|
|
|
|
|
xmlstring, err := root.WriteToString()
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxPublishPubKey: failed to create publish public key iq xml: %w", err)
|
|
|
|
|
}
|
|
|
|
|
iqReply, err := sendIQ(client, iqc, jid, "set", xmlstring)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxPublishPubKey: iq failure publishing public key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
if iqReply.Type != strResult {
|
|
|
|
|
return errors.New("error while publishing public key")
|
|
|
|
|
}
|
|
|
|
|
ownPubKeyRingFromPubsub, err := oxRecvPublicKeys(client, iqc, jid, fingerprint)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return errors.New("couldn't successfully verify public key upload")
|
|
|
|
|
}
|
|
|
|
|
ownPubKeyFromPubsub := ownPubKeyRingFromPubsub.GetKeys()[0]
|
|
|
|
|
ownPubKeyFromPubsubSerialized, err := ownPubKeyFromPubsub.Serialize()
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return errors.New("couldn't successfully verify public key upload")
|
|
|
|
|
}
|
|
|
|
|
if pubKeyBase64 != base64.StdEncoding.EncodeToString(ownPubKeyFromPubsubSerialized) {
|
|
|
|
@ -302,11 +302,11 @@ func oxPublishPubKey(jid string, client *xmpp.Client, iqc chan xmpp.IQ, pubKey *
|
|
|
|
|
value = field.CreateElement("value")
|
|
|
|
|
value.CreateText("open")
|
|
|
|
|
xmlstring, err = root.WriteToString()
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxPublishPubKey: failed to create xml for iq to publish public key list: %w", err)
|
|
|
|
|
}
|
|
|
|
|
iqReply, err = sendIQ(client, iqc, jid, "set", xmlstring)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxPublishPubKey: iq failure publishing public key list: %w", err)
|
|
|
|
|
}
|
|
|
|
|
if iqReply.Type != strResult {
|
|
|
|
@ -329,7 +329,7 @@ func oxGetPrivKeyLoc(jid string) (string, error) {
|
|
|
|
|
dataDir = homeDir + "/.local/share"
|
|
|
|
|
default:
|
|
|
|
|
homeDir, err = os.UserHomeDir()
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return strError, fmt.Errorf("oxGetPrivKeyLoc: failed to determine user dir: %w", err)
|
|
|
|
|
}
|
|
|
|
|
if homeDir == "" {
|
|
|
|
@ -340,7 +340,7 @@ func oxGetPrivKeyLoc(jid string) (string, error) {
|
|
|
|
|
dataDir += "/go-sendxmpp/oxprivkeys/"
|
|
|
|
|
if _, err = os.Stat(dataDir); os.IsNotExist(err) {
|
|
|
|
|
err = os.MkdirAll(dataDir, defaultDirRights)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return strError, fmt.Errorf("oxGetPrivKeyLoc: could not create folder for private keys: %w", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -362,7 +362,7 @@ func oxGetPubKeyLoc(fingerprint string) (string, error) {
|
|
|
|
|
dataDir = homeDir + "/.local/share"
|
|
|
|
|
default:
|
|
|
|
|
homeDir, err = os.UserHomeDir()
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return strError, fmt.Errorf("oxGetPubKeyLoc: failed to determine user dir: %w", err)
|
|
|
|
|
}
|
|
|
|
|
if homeDir == "" {
|
|
|
|
@ -373,7 +373,7 @@ func oxGetPubKeyLoc(fingerprint string) (string, error) {
|
|
|
|
|
dataDir += "/go-sendxmpp/oxpubkeys/"
|
|
|
|
|
if _, err = os.Stat(dataDir); os.IsNotExist(err) {
|
|
|
|
|
err = os.MkdirAll(dataDir, defaultDirRights)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return strError, fmt.Errorf("oxGetPubKeyLoc: could not create folder for public keys: %w", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -383,30 +383,30 @@ func oxGetPubKeyLoc(fingerprint string) (string, error) {
|
|
|
|
|
|
|
|
|
|
func oxGetPrivKey(jid string, passphrase string) (*crypto.Key, error) {
|
|
|
|
|
dataFile, err := oxGetPrivKeyLoc(jid)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
keyBuffer, err := readFile(dataFile)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
keyString := keyBuffer.String()
|
|
|
|
|
decodedPrivKey, err := base64.StdEncoding.DecodeString(keyString)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxGetPrivKey: failed to decode private key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
key, err := crypto.NewKey(decodedPrivKey)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxGetPrivKey: failed to decode private key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
if passphrase != "" {
|
|
|
|
|
key, err = key.Unlock([]byte(passphrase))
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatal("Ox: couldn't unlock private key.")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
isLocked, err := key.IsLocked()
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxGetPrivKey: failed to check whether private key is locked: %w", err)
|
|
|
|
|
}
|
|
|
|
|
if isLocked {
|
|
|
|
@ -421,7 +421,7 @@ func oxGetPrivKey(jid string, passphrase string) (*crypto.Key, error) {
|
|
|
|
|
func oxStoreKey(location string, key string) error {
|
|
|
|
|
var file *os.File
|
|
|
|
|
file, err := os.Create(location)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxStoreKey: failed to create key location: %w", err)
|
|
|
|
|
}
|
|
|
|
|
if runtime.GOOS != "windows" {
|
|
|
|
@ -430,11 +430,11 @@ func oxStoreKey(location string, key string) error {
|
|
|
|
|
_ = file.Chmod(os.FileMode(defaultFileRightsWin))
|
|
|
|
|
}
|
|
|
|
|
_, err = file.Write([]byte(key))
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxStoreKey: failed to write key to file: %w", err)
|
|
|
|
|
}
|
|
|
|
|
err = file.Close()
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Println("error while closing file:", err)
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
@ -445,38 +445,38 @@ func oxGenPrivKey(jid string, client *xmpp.Client, iqc chan xmpp.IQ,
|
|
|
|
|
) error {
|
|
|
|
|
xmppURI := "xmpp:" + jid
|
|
|
|
|
key, err := crypto.GenerateKey(xmppURI, "", keyType, defaultRSABits)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxGenPrivKey: failed to generate private key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
if passphrase != "" {
|
|
|
|
|
key, err = key.Lock([]byte(passphrase))
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxGenPrivKey: failed to lock key with passphrase: %w", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
keySerialized, err := key.Serialize()
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxGenPrivKey: failed to serialize private key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
location, err := oxGetPrivKeyLoc(jid)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxGenPrivKey: failed to get private key location: %w", err)
|
|
|
|
|
}
|
|
|
|
|
err = oxStoreKey(location,
|
|
|
|
|
base64.StdEncoding.EncodeToString(keySerialized))
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
decodedPubKey, err := key.GetPublicKey()
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxGenPrivKey: failed to decode public key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
pubKey, err := crypto.NewKey(decodedPubKey)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxGenPrivKey: failed to decode public key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
err = oxPublishPubKey(jid, client, iqc, pubKey)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("oxGenPrivKey: failed to publish public key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
@ -491,11 +491,11 @@ func oxRecvPublicKeys(client *xmpp.Client, iqc chan xmpp.IQ, recipient string, f
|
|
|
|
|
opkrPsItems.CreateAttr("node", nsOxPubKeys+":"+fingerprint)
|
|
|
|
|
opkrPsItems.CreateAttr("max_items", "1")
|
|
|
|
|
opkrString, err := opkr.WriteToString()
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxRecvPublicKeys: failed to generate xml for public key request: %w", err)
|
|
|
|
|
}
|
|
|
|
|
oxPublicKey, err := sendIQ(client, iqc, recipient, "get", opkrString)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxRecvPublicKeys: iq error requesting public keys: %w", err)
|
|
|
|
|
}
|
|
|
|
|
if oxPublicKey.Type != strResult {
|
|
|
|
@ -504,11 +504,11 @@ func oxRecvPublicKeys(client *xmpp.Client, iqc chan xmpp.IQ, recipient string, f
|
|
|
|
|
}
|
|
|
|
|
oxPublicKeyXML := etree.NewDocument()
|
|
|
|
|
err = oxPublicKeyXML.ReadFromBytes(oxPublicKey.Query)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxRecvPublicKeys: failed parsing iq reply to public key request: %w", err)
|
|
|
|
|
}
|
|
|
|
|
keyring, err := crypto.NewKeyRing(nil)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxRecvPublicKeys: failed reading public key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
oxPublicKeyXMLPubsub := oxPublicKeyXML.SelectElement("pubsub")
|
|
|
|
@ -533,18 +533,18 @@ func oxRecvPublicKeys(client *xmpp.Client, iqc chan xmpp.IQ, recipient string, f
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
decodedPubKey, err := base64.StdEncoding.DecodeString(data.Text())
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxRecvPublicKeys: failed to decode public key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
key, err := crypto.NewKey(decodedPubKey)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxRecvPublicKeys: failed to decode public key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
if key.IsExpired() {
|
|
|
|
|
return nil, errors.New("Key is expired: " + fingerprint)
|
|
|
|
|
}
|
|
|
|
|
err = keyring.AddKey(key)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxRecvPublicKeys: failed adding public key to keyring: %w", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -553,7 +553,7 @@ func oxRecvPublicKeys(client *xmpp.Client, iqc chan xmpp.IQ, recipient string, f
|
|
|
|
|
|
|
|
|
|
func oxGetPublicKeyRing(client *xmpp.Client, iqc chan xmpp.IQ, recipient string) (*crypto.KeyRing, error) {
|
|
|
|
|
publicKeyRing, err := crypto.NewKeyRing(nil)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxGetPublicKeyRing: failed to create a new keyring: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -565,11 +565,11 @@ func oxGetPublicKeyRing(client *xmpp.Client, iqc chan xmpp.IQ, recipient string)
|
|
|
|
|
oxPubKeyListReqPsItems.CreateAttr("node", nsOxPubKeys)
|
|
|
|
|
oxPubKeyListReqPsItems.CreateAttr("max_items", "1")
|
|
|
|
|
opkl, err := oxPubKeyListReq.WriteToString()
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
oxPublicKeyList, err := sendIQ(client, iqc, recipient, "get", opkl)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
if oxPublicKeyList.Type != strResult {
|
|
|
|
@ -578,13 +578,13 @@ func oxGetPublicKeyRing(client *xmpp.Client, iqc chan xmpp.IQ, recipient string)
|
|
|
|
|
}
|
|
|
|
|
oxPubKeyListXML := etree.NewDocument()
|
|
|
|
|
err = oxPubKeyListXML.ReadFromBytes(oxPublicKeyList.Query)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxGetPublicKeyRing: failed to parse answer to public key list request: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pubKeyRingID := "none"
|
|
|
|
|
newestKey, err := time.Parse(time.RFC3339, "1900-01-01T00:00:00Z")
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxGetPublicKeyRing: failed to set time for newest key to 1900-01-01: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -615,7 +615,7 @@ func oxGetPublicKeyRing(client *xmpp.Client, iqc chan xmpp.IQ, recipient string)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
keyDate, err := time.Parse(time.RFC3339, date.Value)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxGetPublicKeyRing: failed to parse time stamp for key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
if keyDate.After(newestKey) {
|
|
|
|
@ -628,17 +628,17 @@ func oxGetPublicKeyRing(client *xmpp.Client, iqc chan xmpp.IQ, recipient string)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pubKeyRingLocation, err := oxGetPubKeyLoc(pubKeyRingID)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxGetPublicKeyRing: failed to get public key ring location: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pubKeyReadXML := etree.NewDocument()
|
|
|
|
|
err = pubKeyReadXML.ReadFromFile(pubKeyRingLocation)
|
|
|
|
|
if errors.Unwrap(err) == nil {
|
|
|
|
|
if err == nil {
|
|
|
|
|
date := pubKeyReadXML.SelectElement("date")
|
|
|
|
|
if date != nil {
|
|
|
|
|
savedKeysDate, err := time.Parse(time.RFC3339, date.Text())
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxGetPublicKeyRing: failed to parse time for saved key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
if !savedKeysDate.Before(newestKey) {
|
|
|
|
@ -648,16 +648,16 @@ func oxGetPublicKeyRing(client *xmpp.Client, iqc chan xmpp.IQ, recipient string)
|
|
|
|
|
}
|
|
|
|
|
for _, r := range pubKeys {
|
|
|
|
|
keyByte, err := base64.StdEncoding.DecodeString(r.Text())
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxGetPublicKeyRing: failed to decode saved key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
key, err := crypto.NewKey(keyByte)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxGetPublicKeyRing: failed to parse saved key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
if !key.IsExpired() {
|
|
|
|
|
err = publicKeyRing.AddKey(key)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxGetPublicKeyRing: failed to add key to public keyring: %w", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -669,7 +669,7 @@ func oxGetPublicKeyRing(client *xmpp.Client, iqc chan xmpp.IQ, recipient string)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pubKeyRing, err := oxRecvPublicKeys(client, iqc, recipient, pubKeyRingID)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxGetPublicKeyRing: failed to get public keyring: %w", err)
|
|
|
|
|
}
|
|
|
|
|
pubKeySaveXML := etree.NewDocument()
|
|
|
|
@ -677,14 +677,14 @@ func oxGetPublicKeyRing(client *xmpp.Client, iqc chan xmpp.IQ, recipient string)
|
|
|
|
|
date.SetText(newestKey.Format(time.RFC3339))
|
|
|
|
|
for _, key := range pubKeyRing.GetKeys() {
|
|
|
|
|
keySerialized, err := key.Serialize()
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxGetPublicKeyRing: failed to serialize key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
saveKey := pubKeySaveXML.CreateElement("pubkey")
|
|
|
|
|
saveKey.SetText(base64.StdEncoding.EncodeToString(keySerialized))
|
|
|
|
|
}
|
|
|
|
|
err = pubKeySaveXML.WriteToFile(pubKeyRingLocation)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("oxGetPublicKeyRing: failed to create xml for saving public key: %w", err)
|
|
|
|
|
}
|
|
|
|
|
return pubKeyRing, nil
|
|
|
|
@ -695,13 +695,13 @@ func oxEncrypt(client *xmpp.Client, oxPrivKey *crypto.Key, recipient string, key
|
|
|
|
|
return "", nil
|
|
|
|
|
}
|
|
|
|
|
privKeyRing, err := crypto.NewKeyRing(oxPrivKey)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return strError, fmt.Errorf("oxEncrypt: failed to create private keyring: %w", err)
|
|
|
|
|
}
|
|
|
|
|
ownJid := strings.Split(client.JID(), "/")[0]
|
|
|
|
|
if recipient != ownJid {
|
|
|
|
|
opk, err := oxPrivKey.GetPublicKey()
|
|
|
|
|
if errors.Unwrap(err) == nil {
|
|
|
|
|
if err == nil {
|
|
|
|
|
ownKey, _ := crypto.NewKey(opk)
|
|
|
|
|
_ = keyRing.AddKey(ownKey)
|
|
|
|
|
}
|
|
|
|
@ -721,12 +721,12 @@ func oxEncrypt(client *xmpp.Client, oxPrivKey *crypto.Key, recipient string, key
|
|
|
|
|
oxCryptMessageScPayloadBody.CreateAttr("xmlns", nsJabberClient)
|
|
|
|
|
oxCryptMessageScPayloadBody.CreateText(message)
|
|
|
|
|
ocm, err := oxCryptMessage.WriteToString()
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return strError, fmt.Errorf("oxEncrypt: failed to create xml for ox crypt message: %w", err)
|
|
|
|
|
}
|
|
|
|
|
plainMessage := crypto.NewPlainMessage([]byte(ocm))
|
|
|
|
|
pgpMessage, err := keyRing.Encrypt(plainMessage, privKeyRing)
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return strError, fmt.Errorf("oxEncrypt: failed to create pgp message: %w", err)
|
|
|
|
|
}
|
|
|
|
|
om := etree.NewDocument()
|
|
|
|
@ -745,7 +745,7 @@ func oxEncrypt(client *xmpp.Client, oxPrivKey *crypto.Key, recipient string, key
|
|
|
|
|
omMessageBody := omMessage.CreateElement("body")
|
|
|
|
|
omMessageBody.CreateText(oxAltBody)
|
|
|
|
|
oms, err := om.WriteToString()
|
|
|
|
|
if errors.Unwrap(err) != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
return strError, fmt.Errorf("oxEncrypt: failed to create xml for ox message: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|