From 428bb86de2c64e8f8ce8127eac95faa2529ce0df Mon Sep 17 00:00:00 2001 From: Martin Dosch Date: Mon, 18 Apr 2022 11:16:41 +0200 Subject: [PATCH] Ox: Add private key import. --- README.md | 4 ++- main.go | 19 ++++++++++-- man/go-sendxmpp.1 | 6 +++- man/go-sendxmpp.1.html | 9 ++++-- man/go-sendxmpp.1.ronn | 9 ++++-- ox.go | 66 +++++++++++++++++++++++++++++++++++------- 6 files changed, 95 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 19d77df..b43a66d 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ If no configuration file is present or if the values should be overridden it is the account details via command line options: ```plain -Usage: go-sendxmpp [-cdilnt] [-f value] [--help] [--http-upload value] [-j value] [-m value] [--muc-password value] [--ox] [--ox-genprivkey] [--ox-passphrase value] [-p value] [--raw] [-r value] [--timeout value] [--tls-version value] [-u value] [--version] [parameters ...] +Usage: go-sendxmpp [-cdilnt] [-f value] [--help] [--http-upload value] [-j value] [-m value] [--muc-password value] [--ox] [--ox-genprivkey] [--ox-import-privkey value] [--ox-passphrase value] [-p value] [--raw] [-r value] [--timeout value] [--tls-version value] [-u value] [--version] [parameters ...] -c, --chatroom Send message to a chatroom. -d, --debug Show debugging info. -f, --file=value Set configuration file. (Default: @@ -105,6 +105,8 @@ Usage: go-sendxmpp [-cdilnt] [-f value] [--help] [--http-upload value] [-j value --ox-genprivkey Generate a public OpenPGP key for the given JID and publish the corresponding public key. + --ox-import-privkey=value + Import an existing private OpenPGP key. --ox-passphrase=value Passphrase for locking and unlocking the private OpenPGP key. diff --git a/main.go b/main.go index d3d8a21..34964f3 100644 --- a/main.go +++ b/main.go @@ -111,6 +111,8 @@ func main() { "Generate a public OpenPGP key for the given JID and publish the corresponding public key.") flagOxPassphrase := getopt.StringLong("ox-passphrase", 0, "", "Passphrase for locking and unlocking the private OpenPGP key.") + flagOxImportPrivKey := getopt.StringLong("ox-import-privkey", 0, "", + "Import an existing private OpenPGP key.") // Parse command line flags. getopt.Parse() @@ -145,8 +147,8 @@ func main() { // For listening or sending raw XML it's not required to specify a recipient except // when sending raw messages to MUCs (go-sendxmpp will join the MUC automatically). recipientsList := getopt.Args() - if (len(recipientsList) == 0 && !*flagRaw && !*flagListen && !*flagOxGenPrivKey) || - (len(recipientsList) == 0 && *flagChatroom) { + if (len(recipientsList) == 0 && !*flagRaw && !*flagListen && !*flagOxGenPrivKey && + *flagOxImportPrivKey == "") || (len(recipientsList) == 0 && *flagChatroom) { log.Fatal("No recipient specified.") } @@ -287,6 +289,19 @@ func main() { os.Exit(0) } + if *flagOxImportPrivKey != "" { + validatedOwnJid, err := MarshalJID(user) + if err != nil { + log.Fatal(err) + } + err = oxImportPrivKey(validatedOwnJid, *flagOxImportPrivKey, + client) + if err != nil { + log.Fatal(err) + } + os.Exit(0) + } + if *flagOx { validatedOwnJid, err := MarshalJID(user) if err != nil { diff --git a/man/go-sendxmpp.1 b/man/go-sendxmpp.1 index 2a5f937..4d0b265 100644 --- a/man/go-sendxmpp.1 +++ b/man/go-sendxmpp.1 @@ -38,7 +38,11 @@ You can either pipe a programs output to \fBgo\-sendxmpp\fR, write in your termi .br There is also no check whether the recipients key is trusted as there is no local keyring used\. Go\-sendxmpp just uses the most recent key that is provided via pubsub and checks that it is not expired\. .P -\fB\-\-ox\-genprivkey\fR: Generate a public OpenPGP key for the given JID and publish the corresponding public key\. Go\-sendxmpp will save the key in \fB$XDG_DATA_HOME/go\-sendxmpp/oxprivkeys\fR or \fB$HOME/\.local/share/go\-sendxmpp/oxprivkeys\fR\. To protect the key you might want to set a passphrase using \fB\-\-ox\-passphrase\fR while generating the key\. +\fB\-\-ox\-genprivkey\fR: Generate a public OpenPGP key for the given JID and publish the corresponding public key\. Go\-sendxmpp will save the key in \fB$XDG_DATA_HOME/go\-sendxmpp/oxprivkeys\fR or \fB$HOME/\.local/share/go\-sendxmpp/oxprivkeys\fR\. To protect the key a passphrase might be set using \fB\-\-ox\-passphrase\fR while generating the key\. +.br +If there is an existing private key for "OpenPGP for XMPP" created by another client (e\.g\. profanity) it might be imported using \fB\-\-ox\-import\-privkey\fR\. +.P +\fB\-\-ox\-import\-privkey\fR=[\fIvalue\fR]: Import an existing private OpenPGP key\. .P \fB\-\-ox\-passphrase\fR=[\fIvalue\fR]: Passphrase for locking and unlocking the private OpenPGP key\. .P diff --git a/man/go-sendxmpp.1.html b/man/go-sendxmpp.1.html index 04a391a..5fb35ca 100644 --- a/man/go-sendxmpp.1.html +++ b/man/go-sendxmpp.1.html @@ -137,8 +137,13 @@ file location is specified with -f or --file.

--ox-genprivkey: Generate a public OpenPGP key for the given JID and publish the corresponding public key. Go-sendxmpp will save the key in $XDG_DATA_HOME/go-sendxmpp/oxprivkeys or - $HOME/.local/share/go-sendxmpp/oxprivkeys. To protect the key you might want to set a - passphrase using --ox-passphrase while generating the key.

+ $HOME/.local/share/go-sendxmpp/oxprivkeys. To protect the key a passphrase might be set + using --ox-passphrase while generating the key.
+ If there is an existing private key for "OpenPGP for XMPP" created by another client (e.g. profanity) + it might be imported using --ox-import-privkey.

+ +

--ox-import-privkey=[value]: + Import an existing private OpenPGP key.

--ox-passphrase=[value]: Passphrase for locking and unlocking the private OpenPGP key.

diff --git a/man/go-sendxmpp.1.ronn b/man/go-sendxmpp.1.ronn index 3d6b14d..6b40073 100644 --- a/man/go-sendxmpp.1.ronn +++ b/man/go-sendxmpp.1.ronn @@ -62,8 +62,13 @@ file location is specified with `-f` or `--file`. `--ox-genprivkey`: Generate a public OpenPGP key for the given JID and publish the corresponding public key. Go-sendxmpp will save the key in `$XDG_DATA_HOME/go-sendxmpp/oxprivkeys` or - `$HOME/.local/share/go-sendxmpp/oxprivkeys`. To protect the key you might want to set a - passphrase using `--ox-passphrase` while generating the key. + `$HOME/.local/share/go-sendxmpp/oxprivkeys`. To protect the key a passphrase might be set + using `--ox-passphrase` while generating the key. + If there is an existing private key for "OpenPGP for XMPP" created by another client (e.g. profanity) + it might be imported using `--ox-import-privkey`. + + `--ox-import-privkey`=[]: + Import an existing private OpenPGP key. `--ox-passphrase`=[]: Passphrase for locking and unlocking the private OpenPGP key. diff --git a/ox.go b/ox.go index e3fbaad..52146fd 100644 --- a/ox.go +++ b/ox.go @@ -19,6 +19,52 @@ import ( "github.com/mattn/go-xmpp" // BSD-3-Clause ) +func oxImportPrivKey(jid string, privKeyLocation string, client *xmpp.Client) error { + xmppUri := "xmpp:" + jid + buffer, err := readFile(privKeyLocation) + if err != nil { + return err + } + key, err := crypto.NewKey(buffer.Bytes()) + if err != nil { + key, err = crypto.NewKeyFromArmored(buffer.String()) + if err != nil { + return err + } + } + entity := key.GetEntity() + if entity.Identities[xmppUri] == nil { + return errors.New("Key identity is not " + xmppUri) + } + pk, err := key.GetPublicKey() + if err != nil { + return err + } + pubKey, err := crypto.NewKey(pk) + if err != nil { + return err + } + fingerprint := strings.ToUpper(pubKey.GetFingerprint()) + _, err = oxRecvPublicKey(client, jid, fingerprint) + if err != nil { + return errors.New("Key not found in pubsub: " + fingerprint) + } + location, err := oxGetPrivKeyLoc(jid) + if err != nil { + return err + } + keySerialized, err := key.Serialize() + if err != nil { + return err + } + err = oxStorePrivKey(location, + base64.StdEncoding.EncodeToString(keySerialized)) + if err != nil { + log.Fatal(err) + } + return nil +} + func oxGetPrivKeyLoc(jid string) (string, error) { var err error var homeDir, dataDir string @@ -89,19 +135,15 @@ func oxGetPrivKey(jid string, passphrase string) (*crypto.Key, error) { return key, nil } -func oxStorePrivKey(jid string, privKey string) error { - dataFile, err := oxGetPrivKeyLoc(jid) - if err != nil { - log.Fatal(err) - } +func oxStorePrivKey(location string, privKey string) error { var file *os.File - if _, err := os.Stat(dataFile); os.IsNotExist(err) { - file, err = os.Create(dataFile) + if _, err := os.Stat(location); os.IsNotExist(err) { + file, err = os.Create(location) if err != nil { return err } } else { - file, err = os.OpenFile(dataFile, os.O_RDWR, 0600) + file, err = os.OpenFile(location, os.O_RDWR, 0600) if err != nil { return err } @@ -112,7 +154,7 @@ func oxStorePrivKey(jid string, privKey string) error { } else { _ = file.Chmod(os.FileMode(0200)) } - _, err = file.Write([]byte(privKey)) + _, err := file.Write([]byte(privKey)) if err != nil { return err } @@ -141,7 +183,11 @@ func oxGenPrivKey(jid string, client *xmpp.Client, passphrase string) error { if err != nil { return err } - err = oxStorePrivKey(jid, + location, err := oxGetPrivKeyLoc(jid) + if err != nil { + return err + } + err = oxStorePrivKey(location, base64.StdEncoding.EncodeToString(keySerialized)) if err != nil { log.Fatal(err)