JMP

XMPPTwitterReddit
Featured Image

Newsletter: JMP at SeaGL, Cheogram now on Amazon

denver@ozg.ca

Hi everyone!

Welcome to the latest edition of your pseudo-monthly JMP update!

In case it’s been a while since you checked out JMP, here’s a refresher: JMP lets you send and receive text and picture messages (and calls) through a real phone number right from your computer, tablet, phone, or anything else that has a Jabber client. Among other things, JMP has these features: Your phone number on every device; Multiple phone numbers, one app; Free as in Freedom; Share one number with multiple people.

JMP at SeaGL

The Seattle GNU/Linux Conference (SeaGL) is happening next week and JMP will be there! We’re going to have a booth with some of our employees, and will have JMP eSIM Adapters and USB card readers for purchase (if you prefer to save on shipping, or like to pay cash or otherwise), along with stickers and good conversations. :) The exhibition area is open all day on Friday and Saturday, November 8 and 9, so be sure to stop by and say hi if you happen to be in the area. We look forward to seeing you!

Cheogram Android in Amazon Appstore

We have just added Cheogram Android to the Amazon Appstore! And we also added Cheogram Android to Aptoide earlier this month. While F-Droid remains our preferred official source, we understand many people prefer to use stores that they’re used to, or that come with their device. We also realize that many people have been waiting for Cheogram Android to return to the Play Store, and we wanted to provide this other option to pay for Cheogram Android while Google works out the approval process issues on their end to get us back in there. We know a lot of you use and recommend app store purchases to support us, so let your friends know about this new Amazon Appstore option for Cheogram Android if they’re interested!

New features in Cheogram Android

As usual, we’ve added a bunch of new features to Cheogram Android over the past month or so. Be sure to update to the latest version (2.17.2-1) to check them out! (Note that Amazon doesn’t have this version quite yet, but it should be there shortly.) Here are the notable changes since our last newsletter: privacy-respecting link previews (generated by sender), more familiar reactions, filtering of conversation list by account, nicer autocomplete for mentions and emoji, and fixes for Android 15, among many others.

To learn what’s happening with JMP between newsletters, here are some ways you can find out:

Featured Image

Newsletter: eSIM Adapter Launch!

singpolyma@singpolyma.net

Hi everyone!

Welcome to the latest edition of your pseudo-monthly JMP update!

In case it’s been a while since you checked out JMP, here’s a refresher: JMP lets you send and receive text and picture messages (and calls) through a real phone number right from your computer, tablet, phone, or anything else that has a Jabber client.  Among other things, JMP has these features: Your phone number on every device; Multiple phone numbers, one app; Free as in Freedom; Share one number with multiple people.

eSIM Adapter

We’ve talked before about the eSIM Adapter, but today we’re excited to announce that we have a good amount of production stock, and you can order the eSIM adapter right now. Existing JMP customers who want to pay with their account balance can also order by contacting support. Have a look at the product launch on Product Hunt as well.

JMP’s eSIM Adapter is a device that acts exactly like a SIM card and will work in any device that accepts a SIM card (phone, tablet, hotspot, USB modem), but the credentials it offers come from eSIMs provided by you. With the adapter, you can use eSIMs from any provider in any device, regardless of whether the device or OS support eSIM. It also means you can move all your eSIMs between devices easily and conveniently. It’s the best of both worlds: the convenience of downloading eSIMs along with the flexibility of moving them between devices and using them on any device.

For JMP Data Plan Physical SIM Owners

Our data plan has always had the choice for a physical SIM. For people who just want the data plan and no other eSIMs this works fine, and we will continue to sell these legacy cards until we run out of stock. However some of you might be wondering if you need to buy an eSIM Adapter now in order to get some of these benefits. The answer might be no! If you order just the USB reader, you can use the app to flash new eSIMs and switch profiles on your existing physical SIM! This isn’t quite as convenient as the full eSIM Adapter, you will need to pop out the SIM and put it into the USB reader even to switch profiles, but it does work for those who have one already.

Cheogram Android

Cheogram Android 2.15.3-3 and 2.15.3-4 have been released. These releases contain some improvements to the embedded “widget” system, funded by NLnet. You can now select from a large list of widgets right in the app. More improvements to this system are coming soon, and if you’re a web-tech developer who is interested in extending people’s chat clients, check out the docs!

Email Gateway

We sponsor the development of an email gateway, Cheogram SMTP, which is also getting better thanks to NLnet. The gateway now supports file attachments on emails, and will soon support sharing widgets with Delta Chat users as well!

To learn what’s happening with JMP between newsletters, here are some ways you can find out:

Thanks for reading and have a wonderful rest of your week!

Featured Image

Newsletter: Calls from SIP; Potential New SIM Plan

singpolyma@singpolyma.net

Hi everyone!

Welcome to the latest edition of your pseudo-monthly JMP update!

In case it’s been a while since you checked out JMP, here’s a refresher: JMP lets you send and receive text and picture messages (and calls) through a real phone number right from your computer, tablet, phone, or anything else that has a Jabber client. Among other things, JMP has these features: Your phone number on every device; Multiple phone numbers, one app; Free as in Freedom; Share one number with multiple people.

Access to our new SMS routes is slowly rolling out, with some users having been moved over already. The process of moving people is a bit slower than we’d hoped, but it is coming along. Let support know if this is a priority for you.

The JMP Data Plan has for some time been providing an option for people who want a privacy-conscious mobile data option for small usage. We do receive feedback from time to time that people would like a similar plan built for heavy data users. We are contemplating adding an “unlimited” (100GB full speed, throttled after) plan to the lineup. If this is you, please reach out to us at support or in the chatroom to let us know of your interest. Pricing is still being worked out, but will likely be in the $80-90 per month range. We may also have an option to access JMP voice and SMS services over the SIM if there is interest.

We have quietly rolled out a feature to allow any JMP customer to receive incoming voice calls from only SIP. While Cheogram SIP has allowed calls to your Jabber network app for some time, calls routed to sip:+yournumber@jmp.chat now ring according to your JMP account settings, including going to your JMP voicemail if not answered. This can be useful in conjunction with services that support forwarding to SIP, or from any sip-broker compatible service dial *10869 followed by a JMP number. This includes calling from any phone number in the world using the SIP Broker access numbers.

Cheogram Android 2.15.3-2 was released this month, with bug fixes and new features including:

  • Animated custom emoji
  • Rich replies, including small image preview and jump-to-parent
  • Hide reply quote if it’s just the exact previous message
  • Allow storing all media in cache on a per-chat basis
  • Optional rich text mode
  • Option to auto-download any size on unmetered networks
  • Use custom tabs for opening links
  • Menu to delete files from media browser
  • Bold timestamp on attention messages
  • Start a message with @mods to ping active moderators in a channel
  • Fix password change
  • Fix unbanning users in channel

Come out and see us at FOSSY 2024! JMP will have a booth and several of us will be giving talks as well.

To learn what’s happening with JMP between newsletters, here are some ways you can find out:

Thanks for reading and have a wonderful rest of your week!

Featured Image

Newsletter: SMS Routes, RCS, and more!

singpolyma@singpolyma.net

Hi everyone!

Welcome to the latest edition of your pseudo-monthly JMP update!

In case it’s been a while since you checked out JMP, here’s a refresher: JMP lets you send and receive text and picture messages (and calls) through a real phone number right from your computer, tablet, phone, or anything else that has a Jabber client.  Among other things, JMP has these features: Your phone number on every device; Multiple phone numbers, one app; Free as in Freedom; Share one number with multiple people.

SMS Censorship, New Routes

We have written before about the increasing levels of censorship across the SMS network. When we published that article, we had no idea just how bad things were about to get. Our main SMS route decided at the beginning of April to begin censoring all messages both ways containing many common profanities. There was quite some back and forth about this, but in the end this carrier has declared that the SMS network is not meant for person-to-person communication and they don’t believe in allowing any profanity to cross their network.

This obviously caused us to dramatically step up the priority of integration with other SMS routes, work which is now nearing completion. We expect very soon to be offering long-term customers with new options which will not only dramatically reduce the censorship issue, but also in some cases remove the max-10 group text limit, dramatically improve acceptance by online services, and more.

RCS

We often receive requests asking when JMP will add support for RCS, to complement our existing SMS and MMS offerings. We are happy to announce that we have RCS access in internal testing now. The currently-possible access is better suited to business use than personal use, though a mix of both is certainly possible. We are assured that better access is coming later in the year, and will keep you all posted on how that progresses. For now if you are interested in testing this, especially if you are a business user, please do let us know and we’ll let you know when we are ready to start some testing.

One thing to note is that “RCS” means different things to different people. The main RCS features we currently have access to are typing notifications, displayed/read notifications, and higher-quality media transmission.

Cheogram Android

Cheogram Android 2.15.3-1 was released this month, with bug fixes and new features including:

  • Major visual refresh, including optional Material You
  • Better audio routing for calls
  • More customizable custom colour theme
  • Conversation read-status sync with other supporting apps
  • Don’t compress animated images
  • Do not default to the network country when there is no SIM (for phone number format)
  • Delayed-send messages
  • Message loading performance improvements

New GeoApp Experiment

We love OpenStreetMap, but some of us have found existing geocoder/search options lacking when it comes to searching by business name, street address, etc. As an experimental way to temporarily bridge that gap, we have produced a prototype Android app (source code) that searches Google Maps and allows you to open search results in any mapping app you have installed. If people like this, we may also extend it with a server-side component that hides all PII, including IP addresses, from Google, for a small monthly fee. For now, the prototype is free to test and will install as “Maps+” in your launcher until we come up with a better name (suggestions welcome!).

To learn what’s happening with JMP between newsletters, here are some ways you can find out:

Thanks for reading and have a wonderful rest of your week!

Featured Image

Newsletter: eSIM Adapter (and Google Play Fun)

singpolyma@singpolyma.net

Hi everyone!

Welcome to the latest edition of your pseudo-monthly JMP update!

In case it’s been a while since you checked out JMP, here’s a refresher: JMP lets you send and receive text and picture messages (and calls) through a real phone number right from your computer, tablet, phone, or anything else that has a Jabber client.  Among other things, JMP has these features: Your phone number on every device; Multiple phone numbers, one app; Free as in Freedom; Share one number with multiple people.

eSIM Adapter

This month we’re pleased to announce the existence of the JMP eSIM Adapter. This is a device that acts exactly like a SIM card and will work in any device that accepts a SIM card (phone, tablet, hotspot, Rocket Stick), but the credentials it offers come from eSIMs provided by the user. With the adapter, you can use eSIMs from any provider in any device, regardless of whether the device or OS support eSIM. It also means you can move all your eSIMs between devices easily and conveniently. It’s the best of both worlds: the convenience of downloading eSIMs along with the flexibility of moving them between devices and using them on any device.

So how are eSIMs downloaded and written to the device in order to use them? The easiest and most convenient way will be the official Android app, which will of course be freedomware and available in F-droid soon. The app is developed by PeterCxy of OpenEUICC fame. If you have an OS that bundles OpenEUICC, it will also work for writing eSIMs to the adapter. The app is not required to use the adapter, and swapping the adapter into another device will work fine. What if you want to switch eSIMs without putting the card back into an Android device? No problem; as long as your other device supports the standard SIM Toolkit menus, you will be able to switch eSIMs on the fly.

What if you don’t have an Android device at all? No problem, there are a few other options for writing eSIMs to the adapter. You can get a PC/SC reader device (about $20 on Amazon for example) and then use a tool such as lpac to download and write eSIMs to the adapter from your PC. Some other cell modems may also be supported by lpac directly. Finally, there is work in progress on an optional tool that will be able to use a server (optionally self-hosted) to facilitate downloading eSIMs with just the SIM Toolkit menus.

There is a very limited supply of these devices available for testing now, so if you’re interested, or just have questions, swing by the chatroom (below) and let us know. We expect full retail roll-out to happen in Q2.

Cheogram Android

Cheogram Android saw a major new release this month, 2.13.4-1 includes a visual refresh, many fixes, and some features including:

  • Allow locally muting channel participants
  • Allow setting subject on messages and threads
  • Display list of recent threads in channel details
  • Support full channel configuration form for owners
  • Register with channel when joining, deregister when leaving (where supported)
  • Expert setting to choose voice message codec

Is My Contact List Uploaded?

Cheogram Android has always included optional features for integrating with your local Android contacts (if you give permission). If you add a Jabber ID to an Android contact, their name and image are displayed in the app. Additionally, if you use a PSTN gateway (such as cheogram.com, which JMP acts as a plugin for) all your contacts with phone numbers are displayed in the app, making it easy to message or call them via the gateway. This is all done locally and no information is uploaded anywhere as part of this feature.

Unfortunately, Google does not believe us. From speaking with developers of similar apps, it seems Google no longer believe anyone who has access to the device contacts is not uploading them somewhere. So, starting with this release, Cheogram Android from the Play Store says when asking for contact permission that contacts are uploaded. Not because they are, but because Google requires that we say so. The app’s privacy policy also says contacts are uploaded; again, only because Google requires that it say this without regard for whether it is true.

Can any of your contacts be exposed to your server? Of course. If you choose to send a message or make a call, part of the message or call’s metadata will transit your server, so the server could become aware of that one contact. Similarly, if you view the contact’s details, the server may be asked whether it knows anything about this contact. And finally, if you tap the “Add Contact” button in the app to save this contact to your server-side list, that one contact is saved server-side. Unfortunately, spelling out all these different cases did not appease Google, who insisted we must say that we “upload the contact list to the server” in exactly those words. So, those words now appear.

Thanks for Reading

The team is growing! This month we welcome SavagePeanut to the team to help out with development.

To learn what’s happening with JMP between newsletters, here are some ways you can find out:

Thanks for reading and have a wonderful rest of your week!

Featured Image

Newsletter: Holidays

singpolyma@singpolyma.net

Hi everyone!

Welcome to the latest edition of your pseudo-monthly JMP update!

In case it’s been a while since you checked out JMP, here’s a refresher: JMP lets you send and receive text and picture messages (and calls) through a real phone number right from your computer, tablet, phone, or anything else that has a Jabber client. Among other things, JMP has these features: Your phone number on every device; Multiple phone numbers, one app; Free as in Freedom; Share one number with multiple people.

Automatic refill for users of the data plan was rolled out to everyone this fall. This has been going well and we fully expect to enable new SIM and eSIM orders for all JMP customers (with no waitlist) in January, after the holidays.

Speaking of holidays, MBOA staff, including JMP support staff, will be taking an end of year break just like we always do. Expect support response times to be longer than usual from December 18 until January 2.

This fall also saw the silent launch of new inventory features for JMP. Historically, JMP has never held inventory of phone numbers, buying them directly from our carrier partners when a customer places an order. Unfortunately, this leaves us at the mercy of which regions our partners choose to keep in stock, and this year saw several occasions where there was no stock at all for all of Canada. So we now have a limited amount of local inventory to improve coverage of important regions, and may eventually be adding a function for “premium numbers” for very rare area codes or similar which cost more to stock.

We have also been working in partnership with Snikket on a cross-platform SDK which we hope will make it easier for developers to build applications that integrate with the Jabber network without needing to be protocol or standards experts. Watch the chatroom and the Snikket blog for more information and demos.

There have also been several releases of the Cheogram Android app (latest is 2.13.0-1) with new features including:

  • Improved call connection stability
  • Verify DNSSEC and DANE and show status in UI
  • Show command UI on channels when there are commands to show
  • Show thread selector when starting a mention
  • Circle around thread selector
  • Several Android 14 specific fixes, including for dialler integration
  • Opening WebXDC from home screen even from a very old message

To learn what’s happening with JMP between newsletters, here are some ways you can find out:

Thanks for reading and have a wonderful rest of your week!

Featured Image

Newsletter: Summer in Review

singpolyma@singpolyma.net

Hi everyone!

Welcome to the latest edition of your pseudo-monthly JMP update!

In case it’s been a while since you checked out JMP, here’s a refresher: JMP lets you send and receive text and picture messages (and calls) through a real phone number right from your computer, tablet, phone, or anything else that has a Jabber client.  Among other things, JMP has these features: Your phone number on every device; Multiple phone numbers, one app; Free as in Freedom; Share one number with multiple people.

Since our launch at the beginning of the summer, we’ve kept busy.  We saw some of you at the first FOSSY, which took place in July.  For those of you who missed it, the videos are out now.

Automatic refill for users of the data plan is in testing now.  That should be fully automated a bit later this month and will pave the way for the end of the waiting list, at least for existing JMP customers.

This summer also saw the addition of two new team members: welcome to Gnafu the Great who will be helping out with support, and Amolith, who will be helping out on the technical side.

There have also been several releases of the Cheogram Android app (latest is 2.12.8-2) with new features including:

  • Support for animated avatars
  • Show “hats” in the list of channel participants
  • An option to show related channels from the channel details area
  • Emoji and sticker autocomplete by typing ‘:’ (allows sending custom emoji)
  • Tweaks to thread UI, including no more auto-follow by default in channels
  • Optionally allow notifications for replies to your messages in channels
  • Allow selecting text and quoting the selection
  • Allow requesting voice when you are muted in a channel
  • Send link previews
  • Support for SVG images, avatars, etc.
  • Long press send button for media options
  • WebXDC importFiles and sendToChat support, allowing, for example, import and export of calendars from the calendar app
  • Fix Command UI in tablet mode
  • Manage permissions for channel participants with a dialog instead of a submenu
  • Ask if you want to moderate all recent messages by a user when banning them from a channel
  • Show a long streak of moderated messages as just one indicator

To learn what’s happening with JMP between newsletters, here are some ways you can find out:

Thanks for reading and have a wonderful rest of your week!

Featured Image

Newsletter: Jabber ID Discovery, New Referral Codes

singpolyma@singpolyma.net

Hi everyone!

Welcome to the latest edition of your pseudo-monthly JMP update!

In case it’s been a while since you checked out JMP, here’s a refresher: JMP lets you send and receive text and picture messages (and calls) through a real phone number right from your computer, tablet, phone, or anything else that has a Jabber client.  Among other things, JMP has these features: Your phone number on every device; Multiple phone numbers, one app; Free as in Freedom; Share one number with multiple people.

It has been a while since we got a newsletter out, and lots has been happening as we race towards our launch.

For those who have experienced the issue with Google Voice participants not showing up properly in our MMS group texting stack, we have a new stack in testing right now.  Let support know if you want to try it out, it has been working well so far for those already using it.

If you check your account settings for the “refer a friend” option you will now see two kinds of referral code.  The list of one-time use codes remains the same as always: a free month for your friend, and a free month’s worth of credit for you if they start paying.  The new code up in the top is multi-use and you can post and share it as much as you like.  It provides credit equivalent to an additional month to anyone who uses it on sign up after their initial $15 deposit as normal, and then a free month’s worth of credit for you after that payment fully clears.

We mentioned before that much of the team will be present at FOSSY, and we can now reveal why: there will be a conference track dedicated to XMPP, which we are helping to facilitate!  Call for proposals ends May 14th. Sign up and come out this summer!

Quicksy Logo For quite some time now, customers have been asked while registering if they would like to enable others who know their phone number to discover their Jabber ID, to enable upgrading to end-to-end encryption, video calls, etc.  The first version of this feature is now live, and users of at least Cheogram Android and Movim can check the contact details of anyone they exchange SMS with to see if a Jabber ID is listed.  We are happy to announce that we have also partnered with Quicksy to allow discovery of anyone registered for their app or directory as well.

Tapbacks Jabber-side reactions are now translated where possible into the tapback pseudo-syntax recognized by many Android and iMessage users so that your reactions will appear in a native way to those users.  In Cheogram Android you can swipe to reply to a message and enter a single emoji as the reply to send a reaction/tapback.

Cheogram Android There have been two Cheogram Android releases since our last newsletter, with a third coming out today.  You no longer need to add a contact to send a message or initiate a call.  The app has seen the addition of moderation features for channel administrators, as well as respecting these moderation actions on display.  For offensive media arriving from other sources, in avatars, or just not moderated quickly enough, users also have the ability to permanently block any media they see from their device.

Cheogram Android has seen some new sticker-related features including default sticker packs and the ability to import any sticker pack made for signal (browse signalstickers.com to find more sticker packs, just tap “add to signal” to add them to Cheogram Android).

There are also brand-new features today in 2.12.1-5, including a new onboarding flow that allows new users to register and pay for JMP before getting a Jabber ID, and then set up their very own Snikket instance all from within the app.  This flow also features some new introductory material about the Jabber network which we will continue to refine over time:

Welcome to Cheogram Android Screenshot How the Jabber network works Screenshot Welcome Screen Screenshot

Notifications about new messages now use the conversation style in Android.  This means that you can set seperate priority and sounds per-conversation at the OS level on new enough version of Android.  There is also an option in each conversation’s menu to add that conversation to your homescreen, something that has always been possible with the app but hopefully this makes it more discoverable for some.

For communities organizing in Jabber channels, sometimes it can be useful to notify everyone present about a message.  Cheogram Android now respects the attention element from members and higher in any channel or group chat.  To send a message with this priority attached, start the message body with @here (this will not be included in the actual message people see).

WebXDC Logo

This release also brings an experimental prototype supporting WebXDC.  This is an experimental specification to allow developers to ship mini-apps that work inside your chats.  Take any *.xdc file and send it to a contact or group chat where everyone uses Cheogram Android and you can play games, share notes, shopping lists, calendars, and more.  Please come by the channel to discuss the future of this technology on the Jabber network with us.

To learn what’s happening with JMP between newsletters, here are some ways you can find out:

Thanks for reading and have a wonderful rest of your week!

Featured Image

Verify Google Play App Purchase on Your Server

singpolyma@singpolyma.net

We are preparing for the first-ever Google Play Store launch of Cheogram Android as part of JMP coming out of beta later this year.  One of the things we wanted to “just work” for Google Play users is to be able to pay for the app and get their first month of JMP “bundled” into that purchase price, to smooth the common onboarding experience.  So how do the JMP servers know that the app communicating with them is running a version of the app bought from Google Play as opposed to our builds, F-Droid’s builds, or someone’s own builds?  And also ensure that this person hasn’t already got a bundled month before?  The documentation available on how to do this is surprisingly sparse, so let’s do this together.

Client Side

Google publishes an official Licensing Verification Library for communicating with Google Play from inside an Android app to determine if this install of the app can be associated with a Google Play purchase.  Most existing documentation focuses on using this library, however it does not expose anything in the callbacks other than “yes license verified” or “no, not verified”.  This can allow an app to check if it is a purchased copy itself, but is not so useful for communicating that proof onward to a server.  The library also contains some exciting snippets like:

// Base64 encoded -
// com.android.vending.licensing.ILicensingService
// Consider encoding this in another way in your
// code to imp rove security
Base64.decode(
    "Y29tLmFuZHJvaWQudmVuZGluZy5saWNlbnNpbmcuSUxpY2Vuc2luZ1NlcnZpY2U=")))

Which implies that they expect developers to fork this code to use it.  Digging in to the code we find in LicenseValidator.java:

public void verify(PublicKey publicKey, int responseCode, String signedData, String signature)

Which looks like exactly what we need: the actual signed assertion from Google Play and the signature!  So we just need a small patch to pass those along to the callback as well as the response code currently being passed.  Then we can use the excellent jitpack to include the forked library in our app:

implementation 'com.github.singpolyma:play-licensing:1c637ea03c'

Then we write a small class in our app code to actually use it:

import android.content.Context;
import com.google.android.vending.licensing.*;
import java.util.function.BiConsumer;

public class CheogramLicenseChecker implements LicenseCheckerCallback {
    private final LicenseChecker mChecker;
    private final BiConsumer mCallback;

    public CheogramLicenseChecker(Context context, BiConsumer<String, String> callback) {
        mChecker = new LicenseChecker(  
            context,  
            new StrictPolicy(), // Want to get a signed item every time  
            context.getResources().getString(R.string.licensePublicKey)  
        );
        mCallback = callback;
    }

    public void checkLicense() {
        mChecker.checkAccess(this);
    }

    @Override
    public void dontAllow(int reason) {
        mCallback.accept(null, null);
    }

    @Override
    public void applicationError(int errorCode) {
        mCallback.accept(null, null);
    }

    @Override
    public void allow(int reason, ResponseData data, String signedData, String signature) {
        mCallback.accept(signedData, signature);
    }
}

Here we use the StrictPolicy from the License Verification Library because we want to get a fresh signed data every time, and if the device is offline the whole question is moot because we won’t be able to contact the server anyway.

This code assumes you put the Base64 encoded licensing public key from “Monetisation Setup” in Play Console into a resource R.string.licensePublicKey.

Then we need to communicate this to the server, which you can do whatever way makes sense for your protocol; with XMPP we can easily add custom elements to our existing requests so:

new com.cheogram.android.CheogramLicenseChecker(context, (signedData, signature) -> {
    if (signedData != null && signature != null) {
        c.addChild("license", "https://ns.cheogram.com/google-play").setContent(signedData);
        c.addChild("licenseSignature", "https://ns.cheogram.com/google-play").setContent(signature);
    }

    xmppConnectionService.sendIqPacket(getAccount(), packet, (a, iq) -> {
        session.updateWithResponse(iq);
    });
}).checkLicense();

Server Side

When trying to verify this on the server side we quickly run into some new issues.  What format is this public key in?  It just says “public key” and is Base64 but that’s about it.  What signature algorithm is used for the signed data?  What is the format of the data itself?  Back to the library code!

private static final String KEY_FACTORY_ALGORITHM = "RSA";
…
byte[] decodedKey = Base64.decode(encodedPublicKey);
…
new X509EncodedKeySpec(decodedKey)

So we can see it is an X509 related encoded, and indeed turns out to be Base64 encoded DER.  So we can run this:

echo "BASE64_STRING" | base64 -d | openssl rsa -pubin -inform der -in - -text

to get the raw properties we might need for any library (key size, modulus, and exponent).  Of course, if your library supports parsing DER directly you can also use that.

import java.security.Signature;
…
private static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
…
Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM);
sig.initVerify(publicKey);
sig.update(signedData.getBytes());

Combined with the java documentation we can thus say that the signature algoritm is PKCS#1 padded RSA with SHA1.

And finally:

String[] fields = TextUtils.split(mainData, Pattern.quote("|"));
data.responseCode = Integer.parseInt(fields[0]);
data.nonce = Integer.parseInt(fields[1]);
data.packageName = fields[2];
data.versionCode = fields[3];
// Application-specific user identifier.
data.userId = fields[4];
data.timestamp = Long.parseLong(fields[5]);

The format of the data, pipe-seperated text. The main field of interest for us is userId which is (as it says in a comment) “a user identifier unique to the <application, user> pair”. So in our server code:

import Control.Error (atZ)
import qualified Data.ByteString.Base64 as Base64
import qualified Data.Text as T
import Crypto.Hash.Algorithms (SHA1(SHA1))
import qualified Crypto.PubKey.RSA as RSA
import qualified Crypto.PubKey.RSA.PKCS15 as RSA
import qualified Data.XML.Types as XML

googlePlayUserId
    | googlePlayVerified = (T.split (=='|') googlePlayLicense) `atZ` 4
    | otherwise = Nothing
googlePlayVerified = fromMaybe False $ fmap (\pubKey ->
    RSA.verify (Just SHA1) pubKey (encodeUtf8 googlePlayLicense)
        (Base64.decodeLenient $ encodeUtf8 googlePlaySig)
    ) googlePlayPublicKey
googlePlayLicense = mconcat $ XML.elementText
    =<< XML.isNamed (s"{https://ns.cheogram.com/google-play}license")
    =<< XML.elementChildren payload
googlePlaySig = mconcat $ XML.elementText
    =<< XML.isNamed (s"{https://ns.cheogram.com/google-play}licenseSignature")
    =<< XML.elementChildren payload

We can then use the verified and extracted googlePlayUserId value to check if this user has got a bundled month before and, if not, to provide them with one during signup.

Featured Image

Cheogram Android: Stickers

singpolyma@sigpolyma.net

One feature people ask about from time to time is stickers.  Now, “stickers” isn’t really a feature, nor is it even universally agreed what it means, but we’ve been working on some improvements to Cheogram Android (and the Cheogram service) to make some sticker workflows better, released today in 2.12.1-3.  This post will mostly talk about those changes and the technical implications; if you just want to see a demo of some UI you may want to skip to the video demo.

Many Android users already have pretty good support for inserting stickers (or GIFs) into Cheogram Android via their keyboard.  However, as the app existed at the time, this would result in the sender re-uploading and the recipient re-downloading the sticker image every time, and fill up the sending server and receiving device with many copies of the same image.  The first step to mitigating this was to switch local media storage in the app to content-addressed, which in this case means that the file is named after the hash of its contents.  This prevents filling up the device when receiving the same image many times.

Now that we know the hashes of our stored media, we can use SIMS to transmit this hash when sending.  If the app sees an image that it already has, it can display it without downloading at all, saving not only space but bandwidth and time as well.  The Cheogram service also uses SIMS to transmit hashes of incoming MMS images for this purpose as well.

An existing Jabber client which uses the word “stickers” is Movim.  It wouldn’t make sense to add the word to our UI without supporting what they already have.  So we added support for XHTML-IM including Bits of Binary images.  This also relies on hash-based storage or caching, which by now we had.  This tech will also be useful in the future to extend beyond stickers into custom emoji.

Some stickers are animated, and users want to be able to send GIFs as well, so the app was updated to support inline playback of animated images (both GIF and WebP format).

Some users don’t have any sticker support in their keyboard or OS, so we want to provide some tools for these users as well.  We have added the option to download some default sticker packs (mostly curated from the default set from Movim for now) so that users start with some options.  We also built a small proxy to allow easily importing stickers intended for signal by clicking the regular “add to signal” links on eg signalstickers.com.  Any sticker selected from these will get sent without even uploading, saving time and space on the server, and then will be received by any user of the app who has the default packs installed with no need for downloading, with fallbacks for other clients and situations of course.

If a user receives a sticker that they’d like to save for easily sending out again later, they can long-press any image they receive and choose “Save as sticker” which will prompt them to choose or create a sticker pack to keep it in, then save it there.  Pointing a sticker sheet app or keyboard at this directory also allows re-using other sticker selection UIs with custom stickers saved in this way.

Taken together we hope these features produce real benefits for users of stickers, both with and without existing keyboard support, and also provide foundational work that we can build upon to provide custom emoji, thumbnails before downloading, URL previews, and other rich media features in the future.  If you’d like to see some of these features in action, check out this short video.

Creative Commons Attribution ShareAlike