Ox: (Hopefully) support multiple pubkeys in result.

See https://xmpp.org/extensions/xep-0373.html#discover-pubkey
code-cleanup
Martin Dosch 2 years ago
parent d25294add7
commit 19dee4b8fd

@ -60,7 +60,7 @@ type OxPublicKey struct {
Item struct {
Text string `xml:",chardata"`
ID string `xml:"id,attr"`
Pubkey struct {
Pubkey []struct {
Text string `xml:",chardata"`
Xmlns string `xml:"xmlns,attr"`
Data string `xml:"data"`

@ -71,8 +71,8 @@ func readMessage(messageFilePath string) (string, error) {
func main() {
type recipientsType struct {
Jid string
OxKey *crypto.Key
Jid string
OxKeyRing *crypto.KeyRing
}
var (
@ -262,7 +262,7 @@ func main() {
var re recipientsType
re.Jid = r
if *flagOx {
re.OxKey, err = oxGetPublicKey(client, r)
re.OxKeyRing, err = oxGetPublicKeyRing(client, r)
if err != nil {
fmt.Println("Couldn't receive key for:", r)
}
@ -507,9 +507,9 @@ func main() {
scanner.Scan()
message = scanner.Text()
for _, recipient := range recipients {
if *flagOx && recipient.OxKey != nil {
if *flagOx && recipient.OxKeyRing != nil {
oxMessage, err := oxEncrypt(client, oxPrivKey,
recipient.Jid, recipient.OxKey, message)
recipient.Jid, recipient.OxKeyRing, message)
if err != nil {
fmt.Println("Ox: couldn't encrypt to",
recipient.Jid)
@ -537,9 +537,9 @@ func main() {
_, err = client.Send(xmpp.Chat{Remote: recipient.Jid,
Type: "chat", Ooburl: message, Text: message})
} else {
if *flagOx && recipient.OxKey != nil {
if *flagOx && recipient.OxKeyRing != nil {
oxMessage, err := oxEncrypt(client, oxPrivKey,
recipient.Jid, recipient.OxKey, message)
recipient.Jid, recipient.OxKeyRing, message)
if err != nil {
fmt.Println("Ox: couldn't encrypt to", recipient.Jid)
continue

124
ox.go

@ -45,7 +45,7 @@ func oxImportPrivKey(jid string, privKeyLocation string, client *xmpp.Client) er
return err
}
fingerprint := strings.ToUpper(pubKey.GetFingerprint())
_, err = oxRecvPublicKey(client, jid, fingerprint)
_, err = oxRecvPublicKeys(client, jid, fingerprint)
if err != nil {
return errors.New("Key not found in pubsub: " + fingerprint)
}
@ -267,10 +267,11 @@ func oxGenPrivKey(jid string, client *xmpp.Client, passphrase string) error {
return errors.New("Error while publishing public key.")
}
ownPubKeyFromPubsub, err := oxRecvPublicKey(client, jid, fingerprint)
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.")
@ -317,8 +318,8 @@ func oxGenPrivKey(jid string, client *xmpp.Client, passphrase string) error {
return nil
}
func oxRecvPublicKey(client *xmpp.Client, recipient string,
fingerprint string) (*crypto.Key, error) {
func oxRecvPublicKeys(client *xmpp.Client, recipient string,
fingerprint string) (*crypto.KeyRing, error) {
var oxPublicKeyRequest IQPubsubRequest
var oxPublicKeyXML OxPublicKey
oxPublicKeyRequest.Xmlns = nsPubsub
@ -340,24 +341,37 @@ func oxRecvPublicKey(client *xmpp.Client, recipient string,
if err != nil {
return nil, err
}
decodedPubKey, err := base64.StdEncoding.DecodeString(oxPublicKeyXML.Items.Item.Pubkey.Data)
keyring, err := crypto.NewKeyRing(nil)
if err != nil {
return nil, err
}
key, err := crypto.NewKey(decodedPubKey)
if err != nil {
return nil, err
}
if key.IsExpired() {
return nil, errors.New("Key is expired: " + fingerprint)
for _, r := range oxPublicKeyXML.Items.Item.Pubkey {
decodedPubKey, err := base64.StdEncoding.DecodeString(r.Data)
if err != nil {
return nil, err
}
key, err := crypto.NewKey(decodedPubKey)
if err != nil {
return nil, err
}
if key.IsExpired() {
return nil, errors.New("Key is expired: " + fingerprint)
}
err = keyring.AddKey(key)
if err != nil {
return nil, err
}
}
return key, nil
return keyring, nil
}
func oxGetPublicKey(client *xmpp.Client, recipient string) (*crypto.Key, error) {
func oxGetPublicKeyRing(client *xmpp.Client, recipient string) (*crypto.KeyRing, error) {
var oxPublicKeyListRequest IQPubsubRequest
var oxPublicKeyListXML OxPublicKeysList
publicKeyRing, err := crypto.NewKeyRing(nil)
if err != nil {
return nil, err
}
oxPublicKeyListRequest.Xmlns = nsPubsub
oxPublicKeyListRequest.Items.Node = nsOxPubKeys
@ -379,8 +393,8 @@ func oxGetPublicKey(client *xmpp.Client, recipient string) (*crypto.Key, error)
return nil, err
}
fingerprint := "none"
newestKey, err := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
pubKeyRingId := "none"
newestKey, err := time.Parse(time.RFC3339, "1900-01-01T00:00:00Z")
if err != nil {
return nil, err
}
@ -391,55 +405,83 @@ func oxGetPublicKey(client *xmpp.Client, recipient string) (*crypto.Key, error)
}
if keyDate.After(newestKey) {
newestKey = keyDate
fingerprint = r.V4Fingerprint
pubKeyRingId = r.V4Fingerprint
}
}
if fingerprint == "none" {
if pubKeyRingId == "none" {
return nil, errors.New("server didn't provide public key fingerprints for " + recipient)
}
pubKeyLocation, err := oxGetPubKeyLoc(fingerprint)
pubKeyRingLocation, err := oxGetPubKeyLoc(pubKeyRingId)
if err != nil {
return nil, err
}
pubKeyFile, err := readFile(pubKeyLocation)
doc := etree.NewDocument()
err = doc.ReadFromFile(pubKeyRingLocation)
if err == nil {
decodedPubKey, err := base64.StdEncoding.DecodeString(pubKeyFile.String())
date := doc.SelectElement("date")
if date != nil {
savedKeysDate, err := time.Parse(time.RFC3339, date.Text())
if err != nil {
return nil, err
}
if !savedKeysDate.Before(newestKey) {
pubKeys := doc.SelectElements("pubkey")
if pubKeys == nil {
return nil, errors.New("Couldn't read public keys from cache.")
}
for _, r := range pubKeys {
keyByte, err := base64.StdEncoding.DecodeString(r.Text())
if err != nil {
return nil, err
}
key, err := crypto.NewKey(keyByte)
if err != nil {
return nil, err
}
if !key.IsExpired() {
err = publicKeyRing.AddKey(key)
if err != nil {
return nil, err
}
}
}
if publicKeyRing.CanEncrypt() {
return publicKeyRing, nil
}
}
}
}
pubKeyRing, err := oxRecvPublicKeys(client, recipient, pubKeyRingId)
if err != nil {
return nil, err
}
doc2 := etree.NewDocument()
date := doc2.CreateElement("date")
date.SetText(newestKey.Format(time.RFC3339))
for _, key := range pubKeyRing.GetKeys() {
keySerialized, err := key.Serialize()
if err != nil {
return nil, err
}
key, err := crypto.NewKey(decodedPubKey)
if err != nil {
return nil, err
}
if !key.IsExpired() {
return key, nil
}
saveKey := doc2.CreateElement("pubkey")
saveKey.SetText(base64.StdEncoding.EncodeToString(keySerialized))
}
key, err := oxRecvPublicKey(client, recipient, fingerprint)
if err != nil {
return nil, errors.New("Couldn't fetch public key.")
}
keySerialized, err := key.Serialize()
err = doc2.WriteToFile(pubKeyRingLocation)
if err != nil {
return nil, err
}
err = oxStoreKey(pubKeyLocation,
base64.StdEncoding.EncodeToString(keySerialized))
if err != nil {
log.Println(err)
}
return key, nil
return pubKeyRing, nil
}
func oxEncrypt(client *xmpp.Client, oxPrivKey *crypto.Key, recipient string,
recipientKey *crypto.Key, message string) (string, error) {
keyRing *crypto.KeyRing, message string) (string, error) {
var oxCryptMessage OxCryptElement
var oxMessage OxMessageElement
keyRing, err := crypto.NewKeyRing(recipientKey)
if err != nil {
return "error", err
}
privKeyRing, err := crypto.NewKeyRing(oxPrivKey)
if err != nil {
return "error", err

Loading…
Cancel
Save