• Pl chevron_right

    JMP: Privacy and Threat Modelling / PlanetJabber · 7 days ago - 15:01 · 3 minutes

One often hears people ask if a product or service is “good for privacy” or if some practice they intend to incorporate is “good enough” for their privacy needs.  The problem with most such questions is that they often lack the necessary context, called a threat model, in order to even begin to understand how to answer them.  Understanding your own threat model (and making any implicit model you carry more explicit to yourself) is one of the most important steps you can take to improve your privacy.

What is a Threat Model?

A threat model is a list of possible vulnerabilities, often with attached priorities.  In the context of personal privacy, this includes anyone who you might not want to learn private infomation about you, what private information you most want that party to remain ignorant of, and why.  For example, someone may not want their ISP to learn that they are communicating on LGTBQ+ forums, because their ISP is their school and their school might tell their parents, whom they are not yet ready to tell.  In this example they might say “I don’t want the school to learn” but because of the reasons it may actually be more important to say “I don’t want my parents to learn.”  So the ISP, the school, and the parents all represent potential vulnerabilities, with the parents as the most important.

Why is a Threat Model Important?

You cannot protect your privacy unless you know what your are protecting and what you are defending against .  Otherwise you may take extra steps to secure something not worth protecting, omit something you were unaware needed protected, or even protect something at the detriment of something you would have cared more about.  Privacy is not a slider from zero to infinity, you cannot be simply “more” or “less” private in some general abstract way.

For example, someone may be a part of a group of insurgents in a small country.  They wish the contents of their communication to be kept a secret from the current government if any one of them is found out, so they choose to use an end-to-end encrypted messaging app.  They have prevented their mobile carrier and government from logging their messages!  They also secure their devices with biometrics so they cannot be stolen.  However, due to the unpopularity of this app in their country, when asked the carrier can immediately identify the current location of anyone using it.  When any of these people are brought in for questioning, the investigator forces the biometric (face or fingerprint) onto the device from the person in custody, unlocks it, gets access to all the decrypted messages, and let’s just say the insurgency is over.

So did the insurgents make “un-private” choices?  No!  For other people with different vulnerabilities, their choices may have been ideal.  But when their identity and current location is more at risk than the content of their messages, sending messages less-encrypted over a more-popular app or protocol (which could have all contents logged for all users, but very likely does not), and deleting them regularly from the local device in case they are caught, would have been more effective.

Privacy LARPing

“Privacy LARPing” is what happens when someone wants to be “more private” because it is cool and not because they have any well-reasoned need for privacy.  Believe it or not, this kind of use case also has a threat model.  The model may be more built on what kinds of vulnerabilities are currently trendy to defend against, but it exists nonetheless.  Putting thought and explicit description into your threat model can be a great way to seem even more “with it” so it’s highly recommended.  You may even identify real threats of concern (there certainly are some for everyone) and move beyong the LARP and into addressing your real needs.

How to Build a Threat Model

This is really an introspection activity.  Ask yourself what kind of entities are most concerning to you.  Estranged friends or lovers?  The other people at the airport or coffee shop?  Local police?  Local SUV owners?  Federal agencies?  Data brokers?  The list of people who may want to know more about you than you want them to is endless, so revisit your model from time to time.  Try to add to it and refine it.  This kind of work is never “done” because the scope is so vast.  Do talk to others and educate yourself about what the set of possible threats is, but do not take each new threat you learn about with the same weight.  Try to understand whether mitigations or new techniques are able to acheieve what you need, rather than blindly applying every “defense” without regard for context.

  • wifi_tethering open_in_new

    This post is public /b/2022-privacy-threat-modelling

  • Pl chevron_right

    Paul Schaub: Using Pushdown Automata to verify Packet Sequences / PlanetJabber · Wednesday, 14 September - 21:46 · 10 minutes

As a software developer, most of my work day is spent working practically by coding and hacking away. Recently though I stumbled across an interesting problem which required another, more theoretical approach;

An OpenPGP message contains of a sequence of packets. There are signatures, encrypted data packets and their accompanying encrypted session keys, compressed data and literal data, the latter being the packet that in the end contains the plaintext body of the message.

Those packets can be sequential, e.g. a one-pass-signature followed by a literal data packet and then a signature, or nested, where for example an encrypted data packet contains a compressed data packet, in turn containing a literal data packet. A typical OpenPGP message can be visualized as follows:

A typical encrypted, signed OpenPGP message

This particular message consists of a sequence of Public-Key Encrypted Session Keys (PKESKs), followed by a Symmetrically Encrypted Integrity-Protected Data packet (SEIPD), and Modification Detection Code packet (MDC). Decrypting the SEIPD using the session key obtained from any of the PKESKs by providing an OpenPGP secret key yields a new data stream consisting of a OnePassSignature (OPS) followed by a Compressed Data packet and a Signature. Decompressing the Compressed Data packet yields a Literal Data packet which in turn contains the plaintext of the message.

I am pretty confident that PGPainless can currently handle all possible combinations of packets just fine. Basically it simply reads the next packet, processes it in however way the packet needs to be processed and then reads the next packet. That makes it very powerful, but there is a catch! Not possible combinations are valid!

The RFC contains a section describing the syntax of OpenPGP messages using a set of expressions which form a context-free grammar:

11.3.  OpenPGP Messages

An OpenPGP message is a packet or sequence of packets that corresponds to the following grammatical rules (comma  represents sequential composition, and vertical bar separates alternatives):

   OpenPGP Message :- Encrypted Message | Signed Message |
                      Compressed Message | Literal Message.

   Compressed Message :- Compressed Data Packet.

   Literal Message :- Literal Data Packet.

   ESK :- Public-Key Encrypted Session Key Packet |
          Symmetric-Key Encrypted Session Key Packet.

   ESK Sequence :- ESK | ESK Sequence, ESK.

   Encrypted Data :- Symmetrically Encrypted Data Packet |
         Symmetrically Encrypted Integrity Protected Data Packet

   Encrypted Message :- Encrypted Data | ESK Sequence, Encrypted Data.

   One-Pass Signed Message :- One-Pass Signature Packet,
               OpenPGP Message, Corresponding Signature Packet.

   Signed Message :- Signature Packet, OpenPGP Message |
               One-Pass Signed Message.

In addition, decrypting a Symmetrically Encrypted Data packet or a Symmetrically Encrypted Integrity Protected Data packet as well as decompressing a Compressed Data packet must yield a valid OpenPGP Message.

Using this grammar, we can construct OpenPGP messages by starting with the term “OpenPGP Message” and iteratively replacing parts of it according to the rules until only final “Packet” terms are left.

Let’s create the message from the diagram above to illustrate the process:

OpenPGP Message
-> Encrypted Message
-> ESK Sequence, Encrypted Data
-> ESK, ESK Sequence, Encrypted Data
-> ESK, ESK, Encrypted Data
-> SKESK, ESK, Encrypted Data
-> SKESK, SKESK, Encrypted Data
-> SKESK, SKESK, SEIPD(Signed Message)
-> SKESK, SKESK, SEIPD(One-Pass Signed Message)
-> SKESK, SKESK, SEIPD(OPS, OpenPGP Message, Sig)
-> SKESK, SKESK, SEIPD(OPS, Compressed Message, Sig)
-> SKESK, SKESK, SEIPD(OPS, Compressed Packet(OpenPGP Message), Sig)
-> SKESK, SKESK, SEIPD(OPS, Compressed Packet(Literal Message), Sig)
-> SKESK, SKESK, SEIPD(OPS, Compressed Packet(Literal Packet("Hello, World!")), Sig)

Here, cursive text marks the term that gets replaced in the next step. Bold text marks final OpenPGP packets which are not being replaced any further. Text inside of braces symbolizes nested data, which is the content of the packet before the braces. Some packet terms were abbreviated to make the text fit into individual lines.

Now, applying the rules in the “forwards direction” as we just did is rather simple and if no non-final terms are left, we end up with a valid OpenPGP message. There are infinitely many solutions for “valid” OpenPGP messages. A brief selection:

Literal Packet("Hello, World")
OPS, Literal Packet("Hey!"), Sig
OPS, OPS, Literal Packet("Hoh!"), Sig, Sig
SEIPD(Literal Packet("Wow"))
Sig, Compressed Packet(Literal Packet("Yay"))

On the other hand, some examples for invalid OpenPGP packet streams:

Literal Packet(_), Literal Packet(_)
OPS, Compressed Packet(<empty>), Sig
Literal Packet(_), Sig
OPS, Literal Packet(_)
SKESK, SEIPD(Literal Packet(_)), Literal Packet(_)

Give it a try, I can guarantee you, you cannot create these messages using the OpenPGP grammar when starting with the term OpenPGP Message .

So now the problem becomes: How can we check, whether a given OpenPGP packet stream forms a valid OpenPGP message according to the grammar? Surely just trying to reverse engineer the message structure manually by brute force would be a daunting task… Luckily, theoretical computer science has a solution for us: Pushdown Automata !

Note: The following description of a PDA is kept brief and simplistic. I may well have made imprecise simplifications on the formal definition. If you want to learn more, but care about correctness, or if you are reading this post in preparation for an exam, you really should check out the Wikipedia page linked above instead.

Me, perhaps not totally accurate on the internet

A Pushdown Automaton (PDA) consists of a set of states with transition rules between those states, as well as a stack. It further has an initial state, as well as a set of accepting states. Each time the automaton reads an input symbol from a word (in our case a packet from a packet stream), it pops the top most item from the stack and then checks, if there is a transition from its current state using the given input and stack item to another state. If there is, it transitions into that state, possibly pushing a new item onto the stack, according to the transition rule. If all input symbols have been read, the word (packet stream) is valid if and only if current state is an accepting state, the stack of the automaton is empty and there are no more input symbols left. If the current state is not accepting or if the stack of the automaton is not empty, the word is invalid.

Formally defined, a transition rule is a tuple (state, input-symbol, stack-symbol, state, stack-symbol), where the first state is the origin, the first stack-symbol is what needs to be popped from the stack, the second state is the destination and the second stack-symbol what we push back onto the stack.

There is a special symbol ‘ε’ which means “nothing”. If the input symbol is ε, it means we can apply the rule without reading any input. If a stack symbol is nothing it means we can apply the rule without popping or pushing the stack.

I translated the OpenPGP grammar into a PDA. There is an initial state “start”, a single accepting state “Valid” and a set of transition rules which I annotated with arrows in the following diagram. Let’s take a closer look.

Pushdown Automaton implementing the OpenPGP Message grammar

Let’s say we want to validate an OpenPGP message of the format OPS , Literal Packet (_), Sig .

We start with the “start” state to the left. As you can see, the only rule we can apply now is labelled ε,ε/m# , which means we do not read any input and do not pop the stack, but we push ‘#’ and ‘m’ onto the stack. After we applied the rule, we are in the state labelled “OpenPGP Message” and the top of our stack contains the symbol ‘m’.

To advance from here, we can peek at our stack and at the input to check our options. Since our message begins with a One-Pass-Signature (OPS), the only rule we can now apply is OPS,m/o , which requires that the top stack symbol is ‘m’. We read “OPS”, pop ‘m’ from the stack, push ‘o’ onto it and transition into the state “One-Pass-Signed Message”. From here there is only one rule ε,ε/m , which means we simply push ‘m’ onto the stack without popping an item and without reading input. That leaves us back in the state “OpenPGP Message”. Our stack now contains (top to bottom) ‘mo#’.

Now we read the next input symbol “Literal Packet” and apply the rule Literal Packet,m/ε , which means we pop ‘m’ from the stack and transition into state “Literal Message”. The stack now contains ‘o#’.

Next, we read “Sig” from the input, pop ‘o’ from the stack without pushing back an item, transitioning to state “Corresponding Signature”.

Last but not least, we apply rule ε,#/ε , do not read from the input, but pop the top symbol ‘#’ from the stack, transitioning to state “Valid”.

In the end, our stack is empty, we read all of the input data and ended up in an accepting state; The packet sequence “OPS, Literal Packet, Sig” forms a valid OpenPGP message.

Would we start over, but with an invalid input like “Literal Packet, Sig”, the play would go like this:

First, we transition from “start” to “OpenPGP Message” by pushing ‘#’ and ‘m’ to the stack. Then we apply rule Literal Packet,m/ε , read “Literal Packet” from the input, pop ‘m’ from the stack without pushing anything back onto it. This brings us into state “Literal Message” with ‘#’ being our new stack symbol. From here, we only have two rules that we could apply: Sig,o/ε would require us to read “Sig” from the input and have ‘o’ on the top of our stack. Both of these requirements we cannot fulfill. The other option ε,#/ε requires us to pop ‘#’ from the stack without reading input. It even brings us into a state called “Valid”! Okay, let’s do that then!

So far we have read “Literal Packet” from the packet stream. Would the data stream end here, we would have a valid OpenPGP message. Unfortunately, there is still some input left. However, there are no valid rules which allow us to transition any further with input “Sig”. Therefore, the input “Literal Packet, Sig” is not a valid OpenPGP message.

You can try any of the invalid messages listed above and you will see that you will always end up in a situation where you either have not fully read all the input symbols, your stack is not empty, or you end up in a non-accepting state.

You might notice some transitions are drawn using dashed lines. Those illustrate transitions for validating the content of nested packets. For example the Compressed Packet MUST contain another valid OpenPGP message. Depending on how you implement the PDA in software, you can either replace the input stream and use the nested transitions which require you to jump back from a nested “Valid” to the state where the nested transition originated from, or use child PDAs as described below.

The packet sequence Compressed Packet ( Literal Packet (_)) for example would be resolved like follows:

From “start” we transition to “OpenPGP Message” by pushing ‘#’ and ‘m’ on the stack. The we read “Compressed Packet from input, pop ‘m’ from the stack and transition to state “Compressed Message”. Since the “Literal Packet” is part of the Compressed Packet”s contents, we now create a new child PDA with input stream “Literal Packet”. After initializing this PDA by pushing ‘#’ and ‘m’ to the stack, we then transition from “OpenPGP Message” to “Literal Message” by reading “Literal Packet” and popping ‘m’, after which we transition to “Valid” by popping ‘#’. Now this PDA is ended up in a valid state, so our parent PDA can transition from “Compressed Message” by reading nothing from the input (remember, the “Compressed Packet” was the only packet in this PDAs stream), popping ‘#’, leaving us with an empty stack and empty input in the valid state.

In PGPainless’ code I am planning to implement OpenPGP message validation by using InputStreams with individual PDAs. If a packet contains nested data (such as the Compressed or Encrypted Packet), a new InputStream will be opened on the decompressed/decrypted data. This new InputStream will in turn have a its own PDA to ensure that the content of the packet forms a valid OpenPGP message on its own. The parent stream on the other hand must check, whether the PDA of it’s child stream ended up in a valid state before accepting its own packet stream.

Initial tests already show promising results, so stay tuned for another blog post where I might go into more details on the implementation 🙂

I really enjoyed this journey into the realm of theoretical computer science. It was a welcome change to my normal day-to-day programming.

Happy Hacking!

  • wifi_tethering open_in_new

    This post is public /2022/09/14/using-pushdown-automata-to-verify-packet-sequences/

  • Pl chevron_right

    Monal IM: Monal IM – project moved / PlanetJabber · Saturday, 10 September - 15:24 · 1 minute

We recently started to migrate the App from Anu Pokharel ‘s Apple account to Thilo Molitor ‘s Apple account.

As part of this transition we also deployed some new push servers to not let an old retired developer pay for the infrastructure needed for Monal.

Coming along with this transition from the old developer team to the new one is our new clean website at . From now on, this blog will not be used for Monal anymore.

Many thanks to all users, contributors and followers so far.

Special thanks goes to Anu. Without him and his passion, Monal would not have been possible. He developed and maintained Monal for more than 10 years, always ensuring compatibility with the latest iOS releases.

When I (Thilo) gradually took over development, I was able to build upon an app with a decent codebase rather than writing my own app from scratch. That made it possible to improve Monal further while already being used by thousands of people. I can not stress enough how thankful I was and still am for all the work Anu put into the development of Monal.
Thank you, Anu, for your wonderful work towards a modern XMPP client for iOS and macOS!

Thilo, Friedrich, Anu

  • wifi_tethering open_in_new

    This post is public /blog/monal-im-project-moved/

  • Pl chevron_right

    Kaidan: Encrypted Audio and Video Calls / PlanetJabber · Saturday, 3 September - 10:00 · 1 minute

OMEMO logo

Kaidan will receive a grant by NLnet for adding encrypted audio and video calls.

The calls will be end-to-end encrypted and authenticated via OMEMO . Furthermore, Kaidan will support small group calls. We strive for interoperability between Kaidan and other XMPP apps supporting calls. In order to achieve that, we will implement a large number of XEPs (XMPP Extension Protocols). They make it possible to have a modern call experience.

Calls have become more widespread over the past few years in free XMPP chat apps. Especially, grants by NLnet made that possible. The development speed and interoperability between different apps have increased. Such an intense development often results in improved specifications. But sometimes the development overtakes the standardization. In that case, the standardization needs to catch up what has already been implemented.

We have to handle that circumstance with group calls and invitations to calls at the moment. There are some adjustments that are not yet official. To make calls from Kaidan to other apps already supporting them, we have to base our work on those changes. If those unofficial adjustments are being modified later to become official, we will need to modify Kaidan as well. But we see the evolution of calls in XMPP as a huge progress and are ready for adaption!

Kaidan’s goal is to establish free and secure communication while being easy to use , thus lowering the entry barrier to XMPP for average users coming from other networks. NLnet and a couple of other organizations support us via the NGI Zero PET fund to achieve that. The money is provided by the European Commission. That is an example of how software can be developed according to the Public Money, Public Code initiative .

There are many other interesting projects currently funded by NLnet . We are glad that Kaidan is one of them!

  • wifi_tethering open_in_new

    This post is public /2022/09/03/audio-video-calls/

  • Pl chevron_right

    Paul Schaub: Creating a Web-of-Trust Implementation: Accessing Certificate Stores / PlanetJabber · Thursday, 1 September - 11:19 · 6 minutes

Currently, I am working on a Web-of-Trust implementation for the OpenPGP library PGPainless. This work is being funded by the awesome NLnet foundation through NGI Assure . Check them out! NGI Assure is made possible with financial support from the European Commission’s Next Generation Internet programme .

NGI Assure

In this post, I will outline some progress I made towards a full WoT implementation. The current milestone entails integrating certificate stores more closely with the core API.

On most systems, OpenPGP certificates (public keys) are typically stored and managed by GnuPGs internal key store. The downside of this approach is, that applications that want to make use of OpenPGP either need to depend on GnuPG, or are required to manage their very own exclusive certificate store. The latter approach, which e.g. Thunderbird is taking, leads to a situation where there are multiple certificate stores with different contents. Your GnuPG certificate store might contain Bobs certificate, while the Thunderbird store does not. This is confusing for users, as they now have to manage two places with OpenPGP certificates.

There is a proposal for a Shared PGP Certificate Directory nicknamed “pgp.cert.d” which aims to solve this issue by specifying a shared, maildir-like directory for OpenPGP certificates. This directory serves as a single source for all OpenPGP certificates a user might have to deal with. Being well-defined through the standards draft means different applications can access the certificate store without being locked into a single OpenPGP backend.

Since the Web-of-Trust also requires a certificate store of some kind to work on, I thought that pgp.cert.d might be the ideal candidate to implement. During the past months I reworked my existing implementation to allow for different storage backends and defined an abstraction layer for generalized certificate stores (not only pgp.cert.d). This abstraction layer was integrated with PGPainless to allow encryption and verification operations to request certificates from a store. Let me introduce the different components in more detail:

The library pgp-cert-d-java contains an implementation of the pgp.cert.d specification. It provides an API for applications to store and fetch certificates to and from the pgp.cert.d directory. The task of parsing the certificate material was delegated to the consumer application, so the library is independent from OpenPGP backends.

The library pgp-certificate-store defines an abstraction layer above pgp-cert-d-java . It contains interfaces for a general OpenPGP certificate store. Implementations of this interface could for example access GnuPGs certificate store, since the interface does not make assumptions about how the certificates are stored. Inside pgp-cert-d-java , there is an adapter class that adapts the PGPCertificateDirectory class to the PGPCertificateStore interface.

The pgpainless-cert-d module provides certificate parsing functionality using pgpainless-core . It further provides a factory class to instantiate PGPainless-backed instances of the PGPCertificateDirectory interface (both file-based, as well as in-memory directories).

Lastly, the pgpainless-cert-d-cli application is a command line tool to demonstrate the pgp.cert.d functionality. It can be used to manage the certificate directory by inserting and fetching certificates:

$ pgpainless-cert-d-cli help
Store and manage public OpenPGP certificates
Usage: certificate-store [-s=DIRECTORY] [COMMAND]

  -s, --store=DIRECTORY   Overwrite the default certificate directory path

  help    Display the help text for a subcommand
  export  Export all certificates in the store to Standard Output
  insert  Insert or update a certificate
  import  Import certificates into the store from Standard Input
  get     Retrieve certificates from the store
  setup   Setup a new certificate directory
  list    List all certificates in the directory
  find    Lookup primary certificate fingerprints by subkey ids or fingerprints
Powered by picocli

Now let’s see how the certificate store can integrate with PGPainless:

Firstly, let’s set up a pgp.cert.d using pgpainless-cert-d-cli:

$ pgpainless-cert-d-cli setup

This command initializes the certificate directory in .local/share/pgp.cert.d/ and creates a trust-root key with the displayed fingerprint. This trust-root currently is not of use, but eventually we will use it as the root of trust in the Web-of-Trust.

Just for fun, let’s import our OpenPGP certificates from GnuPG into the pgp.cert.d:

$ gpg --export --armor | pgpainless-cert-d-cli import

The first part of the command exports all public keys from GnuPG, while the second part imports them into the pgp.cert.d directory.

We can now access those certificates like this:

$ pgpainless-cert-d-cli get -a 7F9116FEA90A5983936C7CFAA027DB2F3E1E118A
Version: PGPainless
Comment: 7F91 16FE A90A 5983 936C  7CFA A027 DB2F 3E1E 118A
Comment: Paul Schaub <>
Comment: 2 further identities


Would this certificate change over time, e.g. because someone signs it and sends me an updated copy, I could merge the new signatures into the store by simply inserting the updated certificate again:

pgpainless-cert-d-cli insert < update.asc

Now, I said earlier that the benefit of the pgp.cert.d draft was that applications could access the certificate store without the need to rely on a certain backend. Let me demonstrate this by showing how to access my certificate within a Java application without the need to use pgpainless-cert-d-cli .

First, let’s write a small piece of code which encrypts a message to my certificate:

// Setup the store
SubkeyLookupFactory lookupFactory = new DatabaseSubkeyLookupFactory();
PGPCertificateDirectory pgpCertD = PGPainlessCertD.fileBased(lookupFactory);
PGPCertificateStoreAdapter store = new PGPCertificateStoreAdapter(pgpCertD);

OpenPgpFingerprint myCert = OpenPgpFingerprint.parse("7F9116FEA90A5983936C7CFAA027DB2F3E1E118A");

ByteArrayInputStream plaintext = new ByteArrayInputStream("Hello, World! This message is encrypted using a cert from a store!".getBytes());
ByteArrayOutputStream ciphertextOut = new ByteArrayOutputStream();

// Encrypt
EncryptionStream encryptionStream = PGPainless.encryptAndOrSign()
      .addRecipient(adapter, myCert)));
Streams.pipeAll(plaintext, encryptionStream);


In this example, we first set up access to the shared certificate directory. For that we need a method to look up certificates by subkey-ids. In this case this is done through an SQLite database. Next, we instantiate a PGPCertificateDirectory object, which we then wrap in a PGPCertificateStoreAdapter to make it usable within PGPainless.

Next, we only need to know our certificates fingerprint in order to instruct PGPainless to encrypt a message to it. Lastly, we print out the encrypted message.

In the future, once the Web-of-Trust is implemented, it should be possible to pass in the recipients email address instead of the fingerprint. The WoT would then find trustworthy keys with that email address and select those for encryption. Right now though, the user still has to identify trustworthy keys of recipients themselves still.

Similarly, we can use a certificate store when verifying a signed message:

ByteArrayInputStream ciphertextIn = ...; // signed message
ByteArrayOutputStream plaintextOut = new ByteArrayOutputStream();

// Verify
DecryptionStream verificationStream = PGPainless.decryptAndOrVerify()
  .withOptions(new ConsumerOptions()
Streams.pipeAll(verificationStream, plaintextOut);

OpenPgpMetadata result = decryptionStream.getResult();
assertTrue(result.isVerified()); // signature is correct and valid

Here, PGPainless will process the signed message, identify the key that was used for signing and fetch its certificate from the certificate store.

Note, that if you implement verification like that, it is up to you to verify the trustworthiness of the certificate yourself.

In the future, this task will be done by a WoT library in the PGPainless ecosystem automatically though 🙂

The current state of the certificate store integration into PGPainless can be found on the storeIntegration branch.

  • wifi_tethering open_in_new

    This post is public /2022/09/01/creating-a-web-of-trust-implementation-accessing-certificate-stores/

  • Pl chevron_right

    Ignite Realtime Blog: Openfire ThreadDump plugin 1.1.0 released / PlanetJabber · Wednesday, 31 August - 14:22

Earlier today, we have released version 1.1.0 of the Openfire Thread Dump plugin. This plugin uses various evaluators to trigger the creation of a Java thread dump. These thread dumps provide valuable information that is typically used when analyzing issues within Openfire’s implementation.

In the new version of the plugin, two new evaluators have been added: one that looks at the usage pattern of Openfire’s TaskEngine, and another one that uses statistics from the database connection pool.

The updated plugin should become available for download in your Openfire admin console in the course of the next few hours. Alternatively, you can download the plugin directly, from the plugin’s archive page .

For other release announcements and news follow us on Twitter

1 post - 1 participant

Read full topic

  • Pl chevron_right

    Kaidan: Kaidan's End-to-End Encryption Trust Management / PlanetJabber · Wednesday, 31 August - 10:00 · 2 minutes

We worked several months on Kaidan’s upcoming end-to-end encryption and trust management. Once Kaidan 0.9 is released, it will provide the latest OMEMO Encryption . But it will also make trust decisions in the background for you if it’s possible. Some trust decisions have to be made manually but there are many others Kaidan automates without decreasing your security. That is done by automatically sharing trust decisions via already secured channels.

The feature Kaidan uses is called Automatic Trust Management (ATM) . Your device receives the encryption data to secure the conversation between you and your contact via the internet. That encryption data can be the data of an attacker. While you think that you communicate with your contact securely, the attacker can read, modify or drop everything you exchange.

You have to make sure that the encryption data you received are really those from your contact to detect and stop an attack. That is done by comparing the exchanged encryption data via a second secure channel. Kaidan provides QR codes for that. QR codes are especially helpful when you want a secure conversation with a contact you can meet in person. For that, you simply scan your contact’s QR code and vice versa.

First QR code scan

Second QR code scan

But what if your contact used a smartphone during the first QR code scan and now wants to chat with you via a notebook too? Usually, your contact would have to scan the notebook’s QR code with the smartphone and vice versa. Furthermore, you would have to scan the notebook’s QR code and vice versa. If you or your contact gets another device or even replaces an old one, QR codes have to be scanned again. That leads to multiple mutual scans, one for each pair of devices.

In the following example graph, there are four devices. B1, B2 and B3 could be your contact’s devices and A1 yours. The six gray edges are the mutual QR code scans that are needed to stop all possible attacks.

Needed trust decisions

With ATM, many QR code scans between you and your contact become unnecessary. The first meeting is used for the initial scan. The encryption data of all new devices is checked via the secure channel established by it. If your contact wants to chat via the notebook, your contact simply scans the notebook via the smartphone and vice versa. But all other scans are not needed anymore. The trust decisions are communicated between the devices that already have a secure channel.

In the example graph, ATM could work as follows:

  1. A1 scans B1’s QR code and vice versa.
  2. A1 scans A2’s QR code and vice versa.
  3. A2 scans A3’s QR code and vice versa.
  4. The remaining three edges are created automatically by ATM via the existing secure channels.

If you want to try out that new feature, stay tuned! Our next release will come soon.

  • wifi_tethering open_in_new

    This post is public /2022/08/31/e2ee-trust-management/

  • Pl chevron_right

    JMP: Signup with Cheogram Android / PlanetJabber · Tuesday, 30 August - 02:09 · 5 minutes

Welcome to ! If you are looking for a simple guide on how to sign up for JMP, then you have come to the right place! We will be keeping this guide up-to-date if there is ever a change in how to sign up.

We will first start with signing up from within your Jabber chat application on mobile, where you will never need to leave the client to get set up. I will be using the freedomware Android client Cheogram to do this signup. To start us off, we will need to create a Jabber ID (or “JID”). Upon first opening the app you will be presented with a welcome screen where you can choose to signup using the built-in flow for or, or you can choose your own custom server.

Main Startup Screen Jabber Server Selection Account User Creation

We will choose for the purposes of this guide, but you are definitely free to choose whatever service you like, or bring your own! On the first screen of the server signup it will ask you to enter a username; this can be anything you want as long as it isn’t already in use on the server. After tapping Next, it will ask you to create a password for this account; length does not seem to be limited so create one as long as you want. Do not forget it, or use a password manager to create/store the password! Tapping Next again will log you in and offer to set an avatar for your account, you can set one now or choose to do so at a later time, if at all. Once logged in to the new account, Cheogram will ask for permissions to your contacts, you can accept or deny them. Accepting will allow us to implement the integration, which we will explain at the end of this post.

Password Creation Profile Avatar Main Chat Captcha Contacts Permissions Dialog

Now the fun begins! First we will need to add the Cheogram bot as a contact before communicating with it. To do this tap the “chat” bubble icon in the lower right corner, it will change views as well as change to a “+” sign, tap it again, then tap “Add contact”. A dialog box will appear where you can type in a contact’s “Jabber ID”, here you will want to put and tap Add, it will provide a prompt saying that it “appears to be a domain”, so tap “add anyway” and then it will open the screen for the bot, most likely displaying the bot comands tab view.

Chat Icon Press Add Contact Dialog Bot Commands Tab View

From here you will get to see one of the features of the Cheogram app, the Command UI! When a chat first opens you will notice that a “tab” near the top will appear titled “Commands”; it is from within this tab that you can manage all the features and settings of your JMP account, but first we need to register an account, and you will notice there is only one command available right now, “register with backend”. You will want to tap this “register” command, and it will take you to the next step. Here you will choose the backend SGX you are wanting to use; this list includes the most popular community ones as well, but we need to select the JMP option. The next screen will ask you to enter a search term for selecting a number; this can be by area code, state/province, city&state/province, or lead with the tilde “~” character to indicate a vanity pattern. We have chosen areacode 902 which then shows us a list of numbers on the next screen; choose one and tap Next.

Backend Selection Number Search Box Number Selection List

On the following screen it will ask you how you wish to activate your account; you have four options: Credit Card, Invite Code, Bitcoin, and Mail or Interac e-Transfer, as well as what the base currency is that you want to use. For this tutorial we have chosen credit card and Canadian dollars. Tapping Next will give us a page rendered in-app where you can add a credit card to use for activation, and choose the amount of funds that will be auto-charged to your credit card when your balance drops below $5. If you clear this box before tapping save, it will disable the auto top-up feature on your account, tapping Next will finish the sign up process. You can now open the Commands tab again and check out the new commands available for your account; details on these commands will come in a seperate blog post.

Currency and Payment Option Invite Code Activation Screen

Now that you have activated your account you are able to call (who really does this anymore, seriously? ;) ), SMS or MMS with your contacts. To add a contact within Cheogram is quite easy with the contacts integration. Now that the bot has been added to your account contacts, your device’s contacts should already be visible when you tap on the “chat” icon to start a new chat, or you can do the following to add a contact to your Jabber server. First tap the chat icon again like you did earlier to add the bot, tap the “+”, then “add contact”. The first thing you should notice that is different this time with the dialog box that pops up is that it now has two selectable buttons: Jabber ID, and PSTN. The PSTN option makes adding telephone numbers for calling or sending SMS to very easy, just type out the phone number you wish to add to your contacts and then tap ADD. This will automatically format the phone number according to the locale detected on your device. If you need to add an international number, you will need to add the phone in the full international format to override the country code being automatically added. With the contact now added, you can either start typing out a message, or tap the “phone” icon that appears at the top to make an audio call to the contact. Images, videos and audio files can also be sent using a number from JMP.

Bot Commands PSTN Contact Dialog Conversation View

Another helpful feature of the Cheogram app is native dialer integration. This allows you to make phone calls straight from your dialer just like any other phone call. To enable this, tap on the 3-dot menu in the top right of the main Cheogram screen, and then tap on Manage Accounts. Here you should see a new option under your account(s) that says “Manage Phone Accounts”, tap on that title and it will take you to a system settings page where you can enable your Jabber ID to make and receive calls, tap the toggle next to the account you want to enable. Now go back to your Manage Accounts screen in Cheogram and then tap the “gear” icon and from this second system settings page, you can select which “calling account” is your default, or to require it to always ask what account you want to use. Do note that there is currently a known bug in Android where this setting will reset after every reboot of the device, there currenltly is no fix out and Google says it will be fixed in a later release version of Android.

Manage Accounts Screen System Dialing Accounts Default Dialling Accounts

  • wifi_tethering open_in_new

    This post is public /b/signup-with-cheogram-android