@ -6,6 +6,7 @@ package main
import (
import (
"encoding/base64"
"encoding/base64"
"errors"
"fmt"
"fmt"
"log"
"log"
"os"
"os"
@ -15,7 +16,7 @@ import (
"github.com/ProtonMail/gopenpgp/v2/crypto" // MIT License
"github.com/ProtonMail/gopenpgp/v2/crypto" // MIT License
"github.com/beevik/etree" // BSD-2-clause
"github.com/beevik/etree" // BSD-2-clause
"github.com/ xmppo /go-xmpp" // BSD-3-Clause
"github.com/ mattn /go-xmpp" // BSD-3-Clause
)
)
func oxDeleteNodes ( jid string , client * xmpp . Client , iqc chan xmpp . IQ ) error {
func oxDeleteNodes ( jid string , client * xmpp . Client , iqc chan xmpp . IQ ) error {
@ -24,25 +25,25 @@ func oxDeleteNodes(jid string, client *xmpp.Client, iqc chan xmpp.IQ) error {
query := nodeListRequest . CreateElement ( "query" )
query := nodeListRequest . CreateElement ( "query" )
query . CreateAttr ( "xmlns" , nsDiscoItems )
query . CreateAttr ( "xmlns" , nsDiscoItems )
nlr , err := nodeListRequest . WriteToString ( )
nlr , err := nodeListRequest . WriteToString ( )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxDeleteNodes: failed to create node list request %w" , err )
return fmt . Errorf ( "oxDeleteNodes: failed to create node list request %w" , err )
}
}
iqReply , err := sendIQ ( client , iqc , jid , "get" , nlr )
iqReply , err := sendIQ ( client , iqc , jid , "get" , nlr )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxDeleteNodes: failure with node list request iq: %w" , err )
return fmt . Errorf ( "oxDeleteNodes: failure with node list request iq: %w" , err )
}
}
nodeListReply := etree . NewDocument ( )
nodeListReply := etree . NewDocument ( )
err = nodeListReply . ReadFromBytes ( iqReply . Query )
err = nodeListReply . ReadFromBytes ( iqReply . Query )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxDeleteNodes: failed to read node list reply iq: %w" , err )
return fmt . Errorf ( "oxDeleteNodes: failed to read node list reply iq: %w" , err )
}
}
query = nodeListReply . SelectElement ( "query" )
query = nodeListReply . SelectElement ( "query" )
if query == nil {
if query == nil {
return fmt. Errorf ( "error parsing iq reply" )
return errors. New ( "error parsing iq reply" )
}
}
items := query . SelectElements ( "item" )
items := query . SelectElements ( "item" )
if items == nil {
if items == nil {
return fmt. Errorf ( "error parsing iq reply" )
return errors. New ( "error parsing iq reply" )
}
}
for _ , item := range items {
for _ , item := range items {
node := item . SelectAttr ( "node" )
node := item . SelectAttr ( "node" )
@ -59,11 +60,11 @@ func oxDeleteNodes(jid string, client *xmpp.Client, iqc chan xmpp.IQ) error {
del := pubsub . CreateElement ( "delete" )
del := pubsub . CreateElement ( "delete" )
del . CreateAttr ( "node" , node . Value )
del . CreateAttr ( "node" , node . Value )
dnr , err := deleteNodeRequest . WriteToString ( )
dnr , err := deleteNodeRequest . WriteToString ( )
if err != nil {
if err ors. Unwrap ( err ) != nil {
continue
continue
}
}
_ , err = sendIQ ( client , iqc , jid , "set" , dnr )
_ , err = sendIQ ( client , iqc , jid , "set" , dnr )
if err != nil {
if err ors. Unwrap ( err ) != nil {
continue
continue
}
}
}
}
@ -77,7 +78,7 @@ func oxDecrypt(m xmpp.Chat, client *xmpp.Client, iqc chan xmpp.IQ, user string,
for _ , r := range m . OtherElem {
for _ , r := range m . OtherElem {
if r . XMLName . Space == nsOx {
if r . XMLName . Space == nsOx {
cryptMsgByte , err = base64 . StdEncoding . DecodeString ( r . InnerXML )
cryptMsgByte , err = base64 . StdEncoding . DecodeString ( r . InnerXML )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return strError , time . Now ( ) , err
return strError , time . Now ( ) , err
}
}
break
break
@ -85,54 +86,54 @@ func oxDecrypt(m xmpp.Chat, client *xmpp.Client, iqc chan xmpp.IQ, user string,
}
}
oxMsg := crypto . NewPGPMessage ( cryptMsgByte )
oxMsg := crypto . NewPGPMessage ( cryptMsgByte )
keyRing , err := crypto . NewKeyRing ( oxPrivKey )
keyRing , err := crypto . NewKeyRing ( oxPrivKey )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return strError , time . Now ( ) , err
return strError , time . Now ( ) , err
}
}
senderKeyRing , err := oxGetPublicKeyRing ( client , iqc , sender )
senderKeyRing , err := oxGetPublicKeyRing ( client , iqc , sender )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return strError , time . Now ( ) , err
return strError , time . Now ( ) , err
}
}
decryptMsg , err := keyRing . Decrypt ( oxMsg , senderKeyRing , crypto . GetUnixTime ( ) )
decryptMsg , err := keyRing . Decrypt ( oxMsg , senderKeyRing , crypto . GetUnixTime ( ) )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return strError , time . Now ( ) , err
return strError , time . Now ( ) , err
}
}
// Remove invalid code points.
// Remove invalid code points.
message := validUTF8 ( string ( decryptMsg . Data ) )
message := validUTF8 ( string ( decryptMsg . Data ) )
doc := etree . NewDocument ( )
doc := etree . NewDocument ( )
err = doc . ReadFromString ( message )
err = doc . ReadFromString ( message )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return strError , time . Now ( ) , err
return strError , time . Now ( ) , err
}
}
signcrypt := doc . SelectElement ( "signcrypt" )
signcrypt := doc . SelectElement ( "signcrypt" )
if signcrypt == nil {
if signcrypt == nil {
return strError , time . Now ( ) , fmt. Errorf ( "ox: no signcrypt element" )
return strError , time . Now ( ) , errors. New ( "ox: no signcrypt element" )
}
}
to := signcrypt . SelectElement ( "to" )
to := signcrypt . SelectElement ( "to" )
if to == nil {
if to == nil {
return strError , time . Now ( ) , fmt. Errorf ( "ox: no to element" )
return strError , time . Now ( ) , errors. New ( "ox: no to element" )
}
}
jid := to . SelectAttr ( "jid" )
jid := to . SelectAttr ( "jid" )
if jid == nil {
if jid == nil {
return strError , time . Now ( ) , fmt. Errorf ( "ox: no jid attribute" )
return strError , time . Now ( ) , errors. New ( "ox: no jid attribute" )
}
}
if strings . Split ( jid . Value , "/" ) [ 0 ] != user {
if strings . Split ( jid . Value , "/" ) [ 0 ] != user {
return strError , time . Now ( ) , fmt. Errorf ( "ox: encrypted for wrong user" )
return strError , time . Now ( ) , errors. New ( "ox: encrypted for wrong user" )
}
}
timestamp := signcrypt . SelectElement ( "time" )
timestamp := signcrypt . SelectElement ( "time" )
if timestamp == nil {
if timestamp == nil {
return strError , time . Now ( ) , fmt. Errorf ( "ox: no time element" )
return strError , time . Now ( ) , errors. New ( "ox: no time element" )
}
}
stamp := timestamp . SelectAttr ( "stamp" )
stamp := timestamp . SelectAttr ( "stamp" )
if stamp == nil {
if stamp == nil {
return strError , time . Now ( ) , fmt. Errorf ( "ox: no stamp attribute" )
return strError , time . Now ( ) , errors. New ( "ox: no stamp attribute" )
}
}
msgStamp , err := time . Parse ( "2006-01-02T15:04:05Z0700" , stamp . Value )
msgStamp , err := time . Parse ( "2006-01-02T15:04:05Z0700" , stamp . Value )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return strError , time . Now ( ) , err
return strError , time . Now ( ) , err
}
}
payload := signcrypt . SelectElement ( "payload" )
payload := signcrypt . SelectElement ( "payload" )
if payload == nil {
if payload == nil {
return strError , time . Now ( ) , fmt. Errorf ( "ox: no payload element" )
return strError , time . Now ( ) , errors. New ( "ox: no payload element" )
}
}
body := payload . SelectElement ( "body" )
body := payload . SelectElement ( "body" )
if body == nil {
if body == nil {
@ -153,58 +154,58 @@ func isOxMsg(m xmpp.Chat) bool {
func oxImportPrivKey ( jid string , privKeyLocation string , client * xmpp . Client , iqc chan xmpp . IQ ) error {
func oxImportPrivKey ( jid string , privKeyLocation string , client * xmpp . Client , iqc chan xmpp . IQ ) error {
xmppURI := "xmpp:" + jid
xmppURI := "xmpp:" + jid
buffer , err := readFile ( privKeyLocation )
buffer , err := readFile ( privKeyLocation )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return err
return err
}
}
key , err := crypto . NewKey ( buffer . Bytes ( ) )
key , err := crypto . NewKey ( buffer . Bytes ( ) )
if err != nil {
if err ors. Unwrap ( err ) != nil {
key , err = crypto . NewKeyFromArmored ( buffer . String ( ) )
key , err = crypto . NewKeyFromArmored ( buffer . String ( ) )
if err != nil {
if err ors. Unwrap ( err ) != nil {
keyDecoded , err := base64 . StdEncoding . DecodeString ( buffer . String ( ) )
keyDecoded , err := base64 . StdEncoding . DecodeString ( buffer . String ( ) )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxImportPrivKey: failed to import private key: %w" , err )
return fmt . Errorf ( "oxImportPrivKey: failed to import private key: %w" , err )
}
}
key , err = crypto . NewKey ( keyDecoded )
key , err = crypto . NewKey ( keyDecoded )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxImportPrivKey: failed to import private key: %w" , err )
return fmt . Errorf ( "oxImportPrivKey: failed to import private key: %w" , err )
}
}
}
}
}
}
entity := key . GetEntity ( )
entity := key . GetEntity ( )
if entity . Identities [ xmppURI ] == nil {
if entity . Identities [ xmppURI ] == nil {
return fmt. Errorf ( "key identity is not %s" , xmppURI )
return errors. New ( "Key identity is not " + xmppURI )
}
}
pk , err := key . GetPublicKey ( )
pk , err := key . GetPublicKey ( )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxImportPrivKey: failed to get public key associated to private key: %w" , err )
return fmt . Errorf ( "oxImportPrivKey: failed to get public key associated to private key: %w" , err )
}
}
pubKey , err := crypto . NewKey ( pk )
pubKey , err := crypto . NewKey ( pk )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxImportPrivKey: failed to get public key associated to private key: %w" , err )
return fmt . Errorf ( "oxImportPrivKey: failed to get public key associated to private key: %w" , err )
}
}
fingerprint := strings . ToUpper ( pubKey . GetFingerprint ( ) )
fingerprint := strings . ToUpper ( pubKey . GetFingerprint ( ) )
_ , err = oxRecvPublicKeys ( client , iqc , jid , fingerprint )
_ , err = oxRecvPublicKeys ( client , iqc , jid , fingerprint )
if err != nil {
if err ors. Unwrap ( err ) != nil {
err = oxPublishPubKey ( jid , client , iqc , pubKey )
err = oxPublishPubKey ( jid , client , iqc , pubKey )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxImportPrivKey: failed to publish public key: %w" , err )
return fmt . Errorf ( "oxImportPrivKey: failed to publish public key: %w" , err )
}
}
}
}
location , err := oxGetPrivKeyLoc ( jid )
location , err := oxGetPrivKeyLoc ( jid )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxImportPrivKey: failed to determine private key location: %w" , err )
return fmt . Errorf ( "oxImportPrivKey: failed to determine private key location: %w" , err )
}
}
keySerialized , err := key . Serialize ( )
keySerialized , err := key . Serialize ( )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxImportPrivKey: failed to serialize private key: %w" , err )
return fmt . Errorf ( "oxImportPrivKey: failed to serialize private key: %w" , err )
}
}
err = oxStoreKey ( location ,
err = oxStoreKey ( location ,
base64 . StdEncoding . EncodeToString ( keySerialized ) )
base64 . StdEncoding . EncodeToString ( keySerialized ) )
if err != nil {
if err ors. Unwrap ( err ) != nil {
log . Fatal ( err )
log . Fatal ( err )
}
}
pubKeyRing , err := oxGetPublicKeyRing ( client , iqc , jid )
pubKeyRing , err := oxGetPublicKeyRing ( client , iqc , jid )
if err == nil {
if err ors. Unwrap ( err ) == nil {
pubKeys := pubKeyRing . GetKeys ( )
pubKeys := pubKeyRing . GetKeys ( )
for _ , r := range pubKeys {
for _ , r := range pubKeys {
if strings . ToUpper ( r . GetFingerprint ( ) ) == fingerprint {
if strings . ToUpper ( r . GetFingerprint ( ) ) == fingerprint {
@ -213,7 +214,7 @@ func oxImportPrivKey(jid string, privKeyLocation string, client *xmpp.Client, iq
}
}
}
}
err = oxPublishPubKey ( jid , client , iqc , pubKey )
err = oxPublishPubKey ( jid , client , iqc , pubKey )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxImportPrivKey: failed to publish public key: %w" , err )
return fmt . Errorf ( "oxImportPrivKey: failed to publish public key: %w" , err )
}
}
return nil
return nil
@ -223,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" )
keyCreated := time . Now ( ) . UTC ( ) . Format ( "2006-01-02T15:04:05Z" )
fingerprint := strings . ToUpper ( pubKey . GetFingerprint ( ) )
fingerprint := strings . ToUpper ( pubKey . GetFingerprint ( ) )
keySerialized , err := pubKey . Serialize ( )
keySerialized , err := pubKey . Serialize ( )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxPublishPubKey: failed to serialize pubkey: %w" , err )
return fmt . Errorf ( "oxPublishPubKey: failed to serialize pubkey: %w" , err )
}
}
pubKeyBase64 := base64 . StdEncoding . EncodeToString ( keySerialized )
pubKeyBase64 := base64 . StdEncoding . EncodeToString ( keySerialized )
@ -253,27 +254,27 @@ func oxPublishPubKey(jid string, client *xmpp.Client, iqc chan xmpp.IQ, pubKey *
value = field . CreateElement ( "value" )
value = field . CreateElement ( "value" )
value . CreateText ( "open" )
value . CreateText ( "open" )
xmlstring , err := root . WriteToString ( )
xmlstring , err := root . WriteToString ( )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxPublishPubKey: failed to create publish public key iq xml: %w" , err )
return fmt . Errorf ( "oxPublishPubKey: failed to create publish public key iq xml: %w" , err )
}
}
iqReply , err := sendIQ ( client , iqc , jid , "set" , xmlstring )
iqReply , err := sendIQ ( client , iqc , jid , "set" , xmlstring )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxPublishPubKey: iq failure publishing public key: %w" , err )
return fmt . Errorf ( "oxPublishPubKey: iq failure publishing public key: %w" , err )
}
}
if iqReply . Type != strResult {
if iqReply . Type != strResult {
return fmt. Errorf ( "error while publishing public key" )
return errors. New ( "error while publishing public key" )
}
}
ownPubKeyRingFromPubsub , err := oxRecvPublicKeys ( client , iqc , jid , fingerprint )
ownPubKeyRingFromPubsub , err := oxRecvPublicKeys ( client , iqc , jid , fingerprint )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt. Errorf ( "couldn't successfully verify public key upload" )
return errors. New ( "couldn't successfully verify public key upload" )
}
}
ownPubKeyFromPubsub := ownPubKeyRingFromPubsub . GetKeys ( ) [ 0 ]
ownPubKeyFromPubsub := ownPubKeyRingFromPubsub . GetKeys ( ) [ 0 ]
ownPubKeyFromPubsubSerialized , err := ownPubKeyFromPubsub . Serialize ( )
ownPubKeyFromPubsubSerialized , err := ownPubKeyFromPubsub . Serialize ( )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt. Errorf ( "couldn't successfully verify public key upload" )
return errors. New ( "couldn't successfully verify public key upload" )
}
}
if pubKeyBase64 != base64 . StdEncoding . EncodeToString ( ownPubKeyFromPubsubSerialized ) {
if pubKeyBase64 != base64 . StdEncoding . EncodeToString ( ownPubKeyFromPubsubSerialized ) {
return fmt. Errorf ( "couldn't successfully verify public key upload" )
return errors. New ( "couldn't successfully verify public key upload" )
}
}
root = etree . NewDocument ( )
root = etree . NewDocument ( )
root . WriteSettings . AttrSingleQuote = true
root . WriteSettings . AttrSingleQuote = true
@ -301,59 +302,80 @@ func oxPublishPubKey(jid string, client *xmpp.Client, iqc chan xmpp.IQ, pubKey *
value = field . CreateElement ( "value" )
value = field . CreateElement ( "value" )
value . CreateText ( "open" )
value . CreateText ( "open" )
xmlstring , err = root . WriteToString ( )
xmlstring , err = root . WriteToString ( )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxPublishPubKey: failed to create xml for iq to publish public key list: %w" , err )
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 )
iqReply , err = sendIQ ( client , iqc , jid , "set" , xmlstring )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxPublishPubKey: iq failure publishing public key list: %w" , err )
return fmt . Errorf ( "oxPublishPubKey: iq failure publishing public key list: %w" , err )
}
}
if iqReply . Type != strResult {
if iqReply . Type != strResult {
return fmt. Errorf ( "couldn't publish public key list" )
return errors. New ( "couldn't publish public key list" )
}
}
return nil
return nil
}
}
func oxGetPrivKeyLoc ( jid string ) ( string , error ) {
func oxGetPrivKeyLoc ( jid string ) ( string , error ) {
dataDir , err := getDataPath ( strings . Replace ( strings . Replace ( jid , "@" , "_at_" , - 1 ) , "." , "_" , - 1 ) )
var err error
if err != nil {
var homeDir , dataDir string
return strError , fmt . Errorf ( "oxGetPrivKeyLoc: %w" , err )
switch {
}
case os . Getenv ( "$XDG_DATA_HOME" ) != "" :
oldDataDir , err := getDataPath ( "oxprivkeys/" )
dataDir = os . Getenv ( "$XDG_DATA_HOME" )
if err != nil {
case os . Getenv ( "$XDG_HOME" ) != "" :
return strError , fmt . Errorf ( "oxGetPrivKeyLoc: %w" , err )
homeDir = os . Getenv ( "$XDG_HOME" )
}
dataDir = homeDir + "/.local/share"
// TODO: Remove handling of oldDataFile in a later version when it's very likely that there are no
case os . Getenv ( "$HOME" ) != "" :
// more versions in use using the oldDataFile (<0.8.3).
homeDir = os . Getenv ( "$HOME" )
oldDataFile := oldDataDir + base64 . StdEncoding . EncodeToString ( [ ] byte ( jid ) )
dataDir = homeDir + "/.local/share"
oldDataFile2 := oldDataDir + strings . Replace ( jid , "@" , "_at_" , - 1 )
default :
oldDataFile3 := oldDataDir + strings . Replace ( strings . Replace ( jid , "@" , "_at_" , - 1 ) , "." , "_" , - 1 )
homeDir , err = os . UserHomeDir ( )
dataFile := dataDir + "oxprivkey"
if errors . Unwrap ( err ) != nil {
if _ , err := os . Stat ( oldDataFile ) ; err == nil {
return strError , fmt . Errorf ( "oxGetPrivKeyLoc: failed to determine user dir: %w" , err )
err := os . Rename ( oldDataFile , dataFile )
if err != nil {
return dataFile , err
}
}
}
if homeDir == "" {
if _ , err := os . Stat ( oldDataFile2 ) ; err == nil {
return strError , errors . New ( "oxGetPrivKeyLoc: received empty string for home directory" )
err := os . Rename ( oldDataFile2 , dataFile )
if err != nil {
return dataFile , err
}
}
dataDir = homeDir + "/.local/share"
}
}
if _ , err := os . Stat ( oldDataFile3 ) ; err == nil {
dataDir += "/go-sendxmpp/oxprivkeys/"
err := os . Rename ( oldDataFile3 , dataFile )
if _ , err = os . Stat ( dataDir ) ; os . IsNotExist ( err ) {
if err != nil {
err = os . MkdirAll ( dataDir , defaultDirRights )
return dataFile , err
if errors . Unwrap ( err ) != nil {
return strError , fmt . Errorf ( "oxGetPrivKeyLoc: could not create folder for private keys: %w" , err )
}
}
}
}
dataFile := dataDir + base64 . StdEncoding . EncodeToString ( [ ] byte ( jid ) )
return dataFile , nil
return dataFile , nil
}
}
func oxGetPubKeyLoc ( fingerprint string ) ( string , error ) {
func oxGetPubKeyLoc ( fingerprint string ) ( string , error ) {
dataDir , err := getDataPath ( "oxpubkeys/" )
var err error
if err != nil {
var homeDir , dataDir string
return strError , fmt . Errorf ( "oxGetPubKeyLoc: %w" , err )
switch {
case os . Getenv ( "$XDG_DATA_HOME" ) != "" :
dataDir = os . Getenv ( "$XDG_DATA_HOME" )
case os . Getenv ( "$XDG_HOME" ) != "" :
homeDir = os . Getenv ( "$XDG_HOME" )
dataDir = homeDir + "/.local/share"
case os . Getenv ( "$HOME" ) != "" :
homeDir = os . Getenv ( "$HOME" )
dataDir = homeDir + "/.local/share"
default :
homeDir , err = os . UserHomeDir ( )
if errors . Unwrap ( err ) != nil {
return strError , fmt . Errorf ( "oxGetPubKeyLoc: failed to determine user dir: %w" , err )
}
if homeDir == "" {
return strError , errors . New ( "oxGetPubKeyLoc: received empty string for home directory" )
}
dataDir = homeDir + "/.local/share"
}
dataDir += "/go-sendxmpp/oxpubkeys/"
if _ , err = os . Stat ( dataDir ) ; os . IsNotExist ( err ) {
err = os . MkdirAll ( dataDir , defaultDirRights )
if errors . Unwrap ( err ) != nil {
return strError , fmt . Errorf ( "oxGetPubKeyLoc: could not create folder for public keys: %w" , err )
}
}
}
dataFile := dataDir + fingerprint
dataFile := dataDir + fingerprint
return dataFile , nil
return dataFile , nil
@ -361,37 +383,37 @@ func oxGetPubKeyLoc(fingerprint string) (string, error) {
func oxGetPrivKey ( jid string , passphrase string ) ( * crypto . Key , error ) {
func oxGetPrivKey ( jid string , passphrase string ) ( * crypto . Key , error ) {
dataFile , err := oxGetPrivKeyLoc ( jid )
dataFile , err := oxGetPrivKeyLoc ( jid )
if err != nil {
if err ors. Unwrap ( err ) != nil {
log . Fatal ( err )
log . Fatal ( err )
}
}
keyBuffer , err := readFile ( dataFile )
keyBuffer , err := readFile ( dataFile )
if err != nil {
if err ors. Unwrap ( err ) != nil {
log . Fatal ( err )
log . Fatal ( err )
}
}
keyString := keyBuffer . String ( )
keyString := keyBuffer . String ( )
decodedPrivKey , err := base64 . StdEncoding . DecodeString ( keyString )
decodedPrivKey , err := base64 . StdEncoding . DecodeString ( keyString )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxGetPrivKey: failed to decode private key: %w" , err )
return nil , fmt . Errorf ( "oxGetPrivKey: failed to decode private key: %w" , err )
}
}
key , err := crypto . NewKey ( decodedPrivKey )
key , err := crypto . NewKey ( decodedPrivKey )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxGetPrivKey: failed to decode private key: %w" , err )
return nil , fmt . Errorf ( "oxGetPrivKey: failed to decode private key: %w" , err )
}
}
if passphrase != "" {
if passphrase != "" {
key , err = key . Unlock ( [ ] byte ( passphrase ) )
key , err = key . Unlock ( [ ] byte ( passphrase ) )
if err != nil {
if err ors. Unwrap ( err ) != nil {
log . Fatal ( "Ox: couldn't unlock private key." )
log . Fatal ( "Ox: couldn't unlock private key." )
}
}
}
}
isLocked , err := key . IsLocked ( )
isLocked , err := key . IsLocked ( )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxGetPrivKey: failed to check whether private key is locked: %w" , err )
return nil , fmt . Errorf ( "oxGetPrivKey: failed to check whether private key is locked: %w" , err )
}
}
if isLocked {
if isLocked {
log . Fatal ( "Ox: private key is locked." )
log . Fatal ( "Ox: private key is locked." )
}
}
if key . IsExpired ( ) {
if key . IsExpired ( ) {
return nil , fmt. Errorf ( "ox: private key is expired: %s" , key . GetFingerprint ( ) )
return nil , errors. New ( "Ox: private key is expired: " + key . GetFingerprint ( ) )
}
}
return key , nil
return key , nil
}
}
@ -399,7 +421,7 @@ func oxGetPrivKey(jid string, passphrase string) (*crypto.Key, error) {
func oxStoreKey ( location string , key string ) error {
func oxStoreKey ( location string , key string ) error {
var file * os . File
var file * os . File
file , err := os . Create ( location )
file , err := os . Create ( location )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxStoreKey: failed to create key location: %w" , err )
return fmt . Errorf ( "oxStoreKey: failed to create key location: %w" , err )
}
}
if runtime . GOOS != "windows" {
if runtime . GOOS != "windows" {
@ -408,11 +430,11 @@ func oxStoreKey(location string, key string) error {
_ = file . Chmod ( os . FileMode ( defaultFileRightsWin ) )
_ = file . Chmod ( os . FileMode ( defaultFileRightsWin ) )
}
}
_ , err = file . Write ( [ ] byte ( key ) )
_ , err = file . Write ( [ ] byte ( key ) )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxStoreKey: failed to write key to file: %w" , err )
return fmt . Errorf ( "oxStoreKey: failed to write key to file: %w" , err )
}
}
err = file . Close ( )
err = file . Close ( )
if err != nil {
if err ors. Unwrap ( err ) != nil {
fmt . Println ( "error while closing file:" , err )
fmt . Println ( "error while closing file:" , err )
}
}
return nil
return nil
@ -423,38 +445,38 @@ func oxGenPrivKey(jid string, client *xmpp.Client, iqc chan xmpp.IQ,
) error {
) error {
xmppURI := "xmpp:" + jid
xmppURI := "xmpp:" + jid
key , err := crypto . GenerateKey ( xmppURI , "" , keyType , defaultRSABits )
key , err := crypto . GenerateKey ( xmppURI , "" , keyType , defaultRSABits )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxGenPrivKey: failed to generate private key: %w" , err )
return fmt . Errorf ( "oxGenPrivKey: failed to generate private key: %w" , err )
}
}
if passphrase != "" {
if passphrase != "" {
key , err = key . Lock ( [ ] byte ( passphrase ) )
key , err = key . Lock ( [ ] byte ( passphrase ) )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxGenPrivKey: failed to lock key with passphrase: %w" , err )
return fmt . Errorf ( "oxGenPrivKey: failed to lock key with passphrase: %w" , err )
}
}
}
}
keySerialized , err := key . Serialize ( )
keySerialized , err := key . Serialize ( )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxGenPrivKey: failed to serialize private key: %w" , err )
return fmt . Errorf ( "oxGenPrivKey: failed to serialize private key: %w" , err )
}
}
location , err := oxGetPrivKeyLoc ( jid )
location , err := oxGetPrivKeyLoc ( jid )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxGenPrivKey: failed to get private key location: %w" , err )
return fmt . Errorf ( "oxGenPrivKey: failed to get private key location: %w" , err )
}
}
err = oxStoreKey ( location ,
err = oxStoreKey ( location ,
base64 . StdEncoding . EncodeToString ( keySerialized ) )
base64 . StdEncoding . EncodeToString ( keySerialized ) )
if err != nil {
if err ors. Unwrap ( err ) != nil {
log . Fatal ( err )
log . Fatal ( err )
}
}
decodedPubKey , err := key . GetPublicKey ( )
decodedPubKey , err := key . GetPublicKey ( )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxGenPrivKey: failed to decode public key: %w" , err )
return fmt . Errorf ( "oxGenPrivKey: failed to decode public key: %w" , err )
}
}
pubKey , err := crypto . NewKey ( decodedPubKey )
pubKey , err := crypto . NewKey ( decodedPubKey )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxGenPrivKey: failed to decode public key: %w" , err )
return fmt . Errorf ( "oxGenPrivKey: failed to decode public key: %w" , err )
}
}
err = oxPublishPubKey ( jid , client , iqc , pubKey )
err = oxPublishPubKey ( jid , client , iqc , pubKey )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return fmt . Errorf ( "oxGenPrivKey: failed to publish public key: %w" , err )
return fmt . Errorf ( "oxGenPrivKey: failed to publish public key: %w" , err )
}
}
return nil
return nil
@ -469,37 +491,40 @@ func oxRecvPublicKeys(client *xmpp.Client, iqc chan xmpp.IQ, recipient string, f
opkrPsItems . CreateAttr ( "node" , nsOxPubKeys + ":" + fingerprint )
opkrPsItems . CreateAttr ( "node" , nsOxPubKeys + ":" + fingerprint )
opkrPsItems . CreateAttr ( "max_items" , "1" )
opkrPsItems . CreateAttr ( "max_items" , "1" )
opkrString , err := opkr . WriteToString ( )
opkrString , err := opkr . WriteToString ( )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxRecvPublicKeys: failed to generate xml for public key request: %w" , err )
return nil , fmt . Errorf ( "oxRecvPublicKeys: failed to generate xml for public key request: %w" , err )
}
}
oxPublicKey , err := sendIQ ( client , iqc , recipient , "get" , opkrString )
oxPublicKey , err := sendIQ ( client , iqc , recipient , "get" , opkrString )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxRecvPublicKeys: iq error requesting public keys: %w" , err )
return nil , fmt . Errorf ( "oxRecvPublicKeys: iq error requesting public keys: %w" , err )
}
}
if oxPublicKey . Type != strResult {
if oxPublicKey . Type != strResult {
return nil , fmt. Errorf ( "error while requesting public key for %s" ,
return nil , errors. New ( "error while requesting public key for " +
recipient )
recipient )
}
}
oxPublicKeyXML := etree . NewDocument ( )
oxPublicKeyXML := etree . NewDocument ( )
err = oxPublicKeyXML . ReadFromBytes ( oxPublicKey . Query )
err = oxPublicKeyXML . ReadFromBytes ( oxPublicKey . Query )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxRecvPublicKeys: failed parsing iq reply to public key request: %w" , err )
return nil , fmt . Errorf ( "oxRecvPublicKeys: failed parsing iq reply to public key request: %w" , err )
}
}
keyring , err := crypto . NewKeyRing ( nil )
keyring , err := crypto . NewKeyRing ( nil )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxRecvPublicKeys: failed reading public key: %w" , err )
return nil , fmt . Errorf ( "oxRecvPublicKeys: failed reading public key: %w" , err )
}
}
oxPublicKeyXMLPubsub := oxPublicKeyXML . SelectElement ( "pubsub" )
oxPublicKeyXMLPubsub := oxPublicKeyXML . SelectElement ( "pubsub" )
if oxPublicKeyXMLPubsub == nil {
if oxPublicKeyXMLPubsub == nil {
return nil , fmt . Errorf ( "ox: no pubsub element in reply to public key request" )
return nil , errors . New ( "ox: no pubsub element in reply to public " +
"key request" )
}
}
oxPublicKeyXMLItems := oxPublicKeyXMLPubsub . SelectElement ( "items" )
oxPublicKeyXMLItems := oxPublicKeyXMLPubsub . SelectElement ( "items" )
if oxPublicKeyXMLItems == nil {
if oxPublicKeyXMLItems == nil {
return nil , fmt . Errorf ( "ox: no items element in reply to public key request" )
return nil , errors . New ( "ox: no items element in reply to public " +
"key request" )
}
}
oxPublicKeyXMLItem := oxPublicKeyXMLItems . SelectElement ( "item" )
oxPublicKeyXMLItem := oxPublicKeyXMLItems . SelectElement ( "item" )
if oxPublicKeyXMLItem == nil {
if oxPublicKeyXMLItem == nil {
return nil , fmt . Errorf ( "ox: no item element in reply to public key request" )
return nil , errors . New ( "ox: no item element in reply to public " +
"key request" )
}
}
oxPublicKeyXMLPubkeys := oxPublicKeyXMLItem . SelectElements ( "pubkey" )
oxPublicKeyXMLPubkeys := oxPublicKeyXMLItem . SelectElements ( "pubkey" )
for _ , r := range oxPublicKeyXMLPubkeys {
for _ , r := range oxPublicKeyXMLPubkeys {
@ -508,18 +533,18 @@ func oxRecvPublicKeys(client *xmpp.Client, iqc chan xmpp.IQ, recipient string, f
continue
continue
}
}
decodedPubKey , err := base64 . StdEncoding . DecodeString ( data . Text ( ) )
decodedPubKey , err := base64 . StdEncoding . DecodeString ( data . Text ( ) )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxRecvPublicKeys: failed to decode public key: %w" , err )
return nil , fmt . Errorf ( "oxRecvPublicKeys: failed to decode public key: %w" , err )
}
}
key , err := crypto . NewKey ( decodedPubKey )
key , err := crypto . NewKey ( decodedPubKey )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxRecvPublicKeys: failed to decode public key: %w" , err )
return nil , fmt . Errorf ( "oxRecvPublicKeys: failed to decode public key: %w" , err )
}
}
if key . IsExpired ( ) {
if key . IsExpired ( ) {
return nil , fmt. Errorf ( "key is expired: %s" , fingerprint )
return nil , errors. New ( "Key is expired: " + fingerprint )
}
}
err = keyring . AddKey ( key )
err = keyring . AddKey ( key )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxRecvPublicKeys: failed adding public key to keyring: %w" , err )
return nil , fmt . Errorf ( "oxRecvPublicKeys: failed adding public key to keyring: %w" , err )
}
}
}
}
@ -528,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 ) {
func oxGetPublicKeyRing ( client * xmpp . Client , iqc chan xmpp . IQ , recipient string ) ( * crypto . KeyRing , error ) {
publicKeyRing , err := crypto . NewKeyRing ( nil )
publicKeyRing , err := crypto . NewKeyRing ( nil )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to create a new keyring: %w" , err )
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to create a new keyring: %w" , err )
}
}
@ -540,44 +565,44 @@ func oxGetPublicKeyRing(client *xmpp.Client, iqc chan xmpp.IQ, recipient string)
oxPubKeyListReqPsItems . CreateAttr ( "node" , nsOxPubKeys )
oxPubKeyListReqPsItems . CreateAttr ( "node" , nsOxPubKeys )
oxPubKeyListReqPsItems . CreateAttr ( "max_items" , "1" )
oxPubKeyListReqPsItems . CreateAttr ( "max_items" , "1" )
opkl , err := oxPubKeyListReq . WriteToString ( )
opkl , err := oxPubKeyListReq . WriteToString ( )
if err != nil {
if err ors. Unwrap ( err ) != nil {
log . Fatal ( err )
log . Fatal ( err )
}
}
oxPublicKeyList , err := sendIQ ( client , iqc , recipient , "get" , opkl )
oxPublicKeyList , err := sendIQ ( client , iqc , recipient , "get" , opkl )
if err != nil {
if err ors. Unwrap ( err ) != nil {
log . Fatal ( err )
log . Fatal ( err )
}
}
if oxPublicKeyList . Type != strResult {
if oxPublicKeyList . Type != strResult {
return nil , fmt. Errorf ( "error while requesting public openpgp keys for %s" ,
return nil , errors. New ( "error while requesting public openpgp keys for " +
recipient )
recipient )
}
}
oxPubKeyListXML := etree . NewDocument ( )
oxPubKeyListXML := etree . NewDocument ( )
err = oxPubKeyListXML . ReadFromBytes ( oxPublicKeyList . Query )
err = oxPubKeyListXML . ReadFromBytes ( oxPublicKeyList . Query )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to parse answer to public key list request: %w" , err )
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to parse answer to public key list request: %w" , err )
}
}
pubKeyRingID := "none"
pubKeyRingID := "none"
newestKey , err := time . Parse ( time . RFC3339 , "1900-01-01T00:00:00Z" )
newestKey , err := time . Parse ( time . RFC3339 , "1900-01-01T00:00:00Z" )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to set time for newest key to 1900-01-01: %w" , err )
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to set time for newest key to 1900-01-01: %w" , err )
}
}
oxPubKeyListXMLPubsub := oxPubKeyListXML . SelectElement ( "pubsub" )
oxPubKeyListXMLPubsub := oxPubKeyListXML . SelectElement ( "pubsub" )
if oxPubKeyListXMLPubsub == nil {
if oxPubKeyListXMLPubsub == nil {
return nil , fmt. Errorf ( "ox: no pubsub element in public key list" )
return nil , errors. New ( "ox: no pubsub element in public key list" )
}
}
oxPubKeyListXMLPubsubItems := oxPubKeyListXMLPubsub . SelectElement ( "items" )
oxPubKeyListXMLPubsubItems := oxPubKeyListXMLPubsub . SelectElement ( "items" )
if oxPubKeyListXMLPubsubItems == nil {
if oxPubKeyListXMLPubsubItems == nil {
return nil , fmt. Errorf ( "ox: no items element in public key list" )
return nil , errors. New ( "ox: no items element in public key list" )
}
}
oxPubKeyListXMLPubsubItemsItem := oxPubKeyListXMLPubsubItems . SelectElement ( "item" )
oxPubKeyListXMLPubsubItemsItem := oxPubKeyListXMLPubsubItems . SelectElement ( "item" )
if oxPubKeyListXMLPubsubItemsItem == nil {
if oxPubKeyListXMLPubsubItemsItem == nil {
return nil , fmt. Errorf ( "ox: no item element in public key list" )
return nil , errors. New ( "ox: no item element in public key list" )
}
}
oxPubKeyListXMLPubsubItemsItemPkl := oxPubKeyListXMLPubsubItemsItem . SelectElement ( "public-keys-list" )
oxPubKeyListXMLPubsubItemsItemPkl := oxPubKeyListXMLPubsubItemsItem . SelectElement ( "public-keys-list" )
if oxPubKeyListXMLPubsubItemsItemPkl == nil {
if oxPubKeyListXMLPubsubItemsItemPkl == nil {
return nil , fmt. Errorf ( "ox: no public-keys-list element" )
return nil , errors. New ( "ox: no public-keys-list element" )
}
}
oxPubKeyListXMLPubsubItemsItemPklPm := oxPubKeyListXMLPubsubItemsItemPkl . SelectElements ( "pubkey-metadata" )
oxPubKeyListXMLPubsubItemsItemPklPm := oxPubKeyListXMLPubsubItemsItemPkl . SelectElements ( "pubkey-metadata" )
for _ , r := range oxPubKeyListXMLPubsubItemsItemPklPm {
for _ , r := range oxPubKeyListXMLPubsubItemsItemPklPm {
@ -590,7 +615,7 @@ func oxGetPublicKeyRing(client *xmpp.Client, iqc chan xmpp.IQ, recipient string)
continue
continue
}
}
keyDate , err := time . Parse ( time . RFC3339 , date . Value )
keyDate , err := time . Parse ( time . RFC3339 , date . Value )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to parse time stamp for key: %w" , err )
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to parse time stamp for key: %w" , err )
}
}
if keyDate . After ( newestKey ) {
if keyDate . After ( newestKey ) {
@ -599,40 +624,40 @@ func oxGetPublicKeyRing(client *xmpp.Client, iqc chan xmpp.IQ, recipient string)
}
}
}
}
if pubKeyRingID == "none" {
if pubKeyRingID == "none" {
return nil , fmt. Errorf ( "server didn't provide public key fingerprints for %s" , recipient )
return nil , errors. New ( "server didn't provide public key fingerprints for " + recipient )
}
}
pubKeyRingLocation , err := oxGetPubKeyLoc ( pubKeyRingID )
pubKeyRingLocation , err := oxGetPubKeyLoc ( pubKeyRingID )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to get public key ring location: %w" , err )
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to get public key ring location: %w" , err )
}
}
pubKeyReadXML := etree . NewDocument ( )
pubKeyReadXML := etree . NewDocument ( )
err = pubKeyReadXML . ReadFromFile ( pubKeyRingLocation )
err = pubKeyReadXML . ReadFromFile ( pubKeyRingLocation )
if err == nil {
if err ors. Unwrap ( err ) == nil {
date := pubKeyReadXML . SelectElement ( "date" )
date := pubKeyReadXML . SelectElement ( "date" )
if date != nil {
if date != nil {
savedKeysDate , err := time . Parse ( time . RFC3339 , date . Text ( ) )
savedKeysDate , err := time . Parse ( time . RFC3339 , date . Text ( ) )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to parse time for saved key: %w" , err )
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to parse time for saved key: %w" , err )
}
}
if ! savedKeysDate . Before ( newestKey ) {
if ! savedKeysDate . Before ( newestKey ) {
pubKeys := pubKeyReadXML . SelectElements ( "pubkey" )
pubKeys := pubKeyReadXML . SelectElements ( "pubkey" )
if pubKeys == nil {
if pubKeys == nil {
return nil , fmt. Errorf ( "couldn't read public keys from cache" )
return nil , errors. New ( "couldn't read public keys from cache" )
}
}
for _ , r := range pubKeys {
for _ , r := range pubKeys {
keyByte , err := base64 . StdEncoding . DecodeString ( r . Text ( ) )
keyByte , err := base64 . StdEncoding . DecodeString ( r . Text ( ) )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to decode saved key: %w" , err )
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to decode saved key: %w" , err )
}
}
key , err := crypto . NewKey ( keyByte )
key , err := crypto . NewKey ( keyByte )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to parse saved key: %w" , err )
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to parse saved key: %w" , err )
}
}
if ! key . IsExpired ( ) {
if ! key . IsExpired ( ) {
err = publicKeyRing . AddKey ( key )
err = publicKeyRing . AddKey ( key )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to add key to public keyring: %w" , err )
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to add key to public keyring: %w" , err )
}
}
}
}
@ -644,7 +669,7 @@ func oxGetPublicKeyRing(client *xmpp.Client, iqc chan xmpp.IQ, recipient string)
}
}
}
}
pubKeyRing , err := oxRecvPublicKeys ( client , iqc , recipient , pubKeyRingID )
pubKeyRing , err := oxRecvPublicKeys ( client , iqc , recipient , pubKeyRingID )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to get public keyring: %w" , err )
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to get public keyring: %w" , err )
}
}
pubKeySaveXML := etree . NewDocument ( )
pubKeySaveXML := etree . NewDocument ( )
@ -652,31 +677,31 @@ func oxGetPublicKeyRing(client *xmpp.Client, iqc chan xmpp.IQ, recipient string)
date . SetText ( newestKey . Format ( time . RFC3339 ) )
date . SetText ( newestKey . Format ( time . RFC3339 ) )
for _ , key := range pubKeyRing . GetKeys ( ) {
for _ , key := range pubKeyRing . GetKeys ( ) {
keySerialized , err := key . Serialize ( )
keySerialized , err := key . Serialize ( )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to serialize key: %w" , err )
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to serialize key: %w" , err )
}
}
saveKey := pubKeySaveXML . CreateElement ( "pubkey" )
saveKey := pubKeySaveXML . CreateElement ( "pubkey" )
saveKey . SetText ( base64 . StdEncoding . EncodeToString ( keySerialized ) )
saveKey . SetText ( base64 . StdEncoding . EncodeToString ( keySerialized ) )
}
}
err = pubKeySaveXML . WriteToFile ( pubKeyRingLocation )
err = pubKeySaveXML . WriteToFile ( pubKeyRingLocation )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to create xml for saving public key: %w" , err )
return nil , fmt . Errorf ( "oxGetPublicKeyRing: failed to create xml for saving public key: %w" , err )
}
}
return pubKeyRing , nil
return pubKeyRing , nil
}
}
func oxEncrypt ( client * xmpp . Client , oxPrivKey * crypto . Key , recipient string , keyRing crypto . KeyRing , message string , subject string ) ( string , error ) {
func oxEncrypt ( client * xmpp . Client , oxPrivKey * crypto . Key , recipient string , keyRing * crypto . KeyRing , message string ) ( string , error ) {
if message == "" {
if message == "" {
return "" , nil
return "" , nil
}
}
privKeyRing , err := crypto . NewKeyRing ( oxPrivKey )
privKeyRing , err := crypto . NewKeyRing ( oxPrivKey )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return strError , fmt . Errorf ( "oxEncrypt: failed to create private keyring: %w" , err )
return strError , fmt . Errorf ( "oxEncrypt: failed to create private keyring: %w" , err )
}
}
ownJid := strings . Split ( client . JID ( ) , "/" ) [ 0 ]
ownJid := strings . Split ( client . JID ( ) , "/" ) [ 0 ]
if recipient != ownJid {
if recipient != ownJid {
opk , err := oxPrivKey . GetPublicKey ( )
opk , err := oxPrivKey . GetPublicKey ( )
if err == nil {
if err ors. Unwrap ( err ) == nil {
ownKey , _ := crypto . NewKey ( opk )
ownKey , _ := crypto . NewKey ( opk )
_ = keyRing . AddKey ( ownKey )
_ = keyRing . AddKey ( ownKey )
}
}
@ -692,20 +717,16 @@ func oxEncrypt(client *xmpp.Client, oxPrivKey *crypto.Key, recipient string, key
oxCryptMessageScRpad := oxCryptMessageSc . CreateElement ( "rpad" )
oxCryptMessageScRpad := oxCryptMessageSc . CreateElement ( "rpad" )
oxCryptMessageScRpad . CreateText ( getRpad ( len ( message ) ) )
oxCryptMessageScRpad . CreateText ( getRpad ( len ( message ) ) )
oxCryptMessageScPayload := oxCryptMessageSc . CreateElement ( "payload" )
oxCryptMessageScPayload := oxCryptMessageSc . CreateElement ( "payload" )
if subject != "" {
oxCryptMessageScPayloadSub := oxCryptMessageScPayload . CreateElement ( "subject" )
oxCryptMessageScPayloadSub . CreateText ( subject )
}
oxCryptMessageScPayloadBody := oxCryptMessageScPayload . CreateElement ( "body" )
oxCryptMessageScPayloadBody := oxCryptMessageScPayload . CreateElement ( "body" )
oxCryptMessageScPayloadBody . CreateAttr ( "xmlns" , nsJabberClient )
oxCryptMessageScPayloadBody . CreateAttr ( "xmlns" , nsJabberClient )
oxCryptMessageScPayloadBody . CreateText ( message )
oxCryptMessageScPayloadBody . CreateText ( message )
ocm , err := oxCryptMessage . WriteToString ( )
ocm , err := oxCryptMessage . WriteToString ( )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return strError , fmt . Errorf ( "oxEncrypt: failed to create xml for ox crypt message: %w" , err )
return strError , fmt . Errorf ( "oxEncrypt: failed to create xml for ox crypt message: %w" , err )
}
}
plainMessage := crypto . NewPlainMessage ( [ ] byte ( ocm ) )
plainMessage := crypto . NewPlainMessage ( [ ] byte ( ocm ) )
pgpMessage , err := keyRing . Encrypt ( plainMessage , privKeyRing )
pgpMessage , err := keyRing . Encrypt ( plainMessage , privKeyRing )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return strError , fmt . Errorf ( "oxEncrypt: failed to create pgp message: %w" , err )
return strError , fmt . Errorf ( "oxEncrypt: failed to create pgp message: %w" , err )
}
}
om := etree . NewDocument ( )
om := etree . NewDocument ( )
@ -724,7 +745,7 @@ func oxEncrypt(client *xmpp.Client, oxPrivKey *crypto.Key, recipient string, key
omMessageBody := omMessage . CreateElement ( "body" )
omMessageBody := omMessage . CreateElement ( "body" )
omMessageBody . CreateText ( oxAltBody )
omMessageBody . CreateText ( oxAltBody )
oms , err := om . WriteToString ( )
oms , err := om . WriteToString ( )
if err != nil {
if err ors. Unwrap ( err ) != nil {
return strError , fmt . Errorf ( "oxEncrypt: failed to create xml for ox message: %w" , err )
return strError , fmt . Errorf ( "oxEncrypt: failed to create xml for ox message: %w" , err )
}
}