[New Free Plugin] OpenPGP Utilities

From the hallowed bit forges deep in the mines of Genstate comes our latest open source release: OpenPGP Utilities. This plugin provides both server-side actions, and a client-side element wrapping the OpenPGPJS NodeJS library.

The client-side actions are contained in a non-rendering element, and use an implicit Promise chaining mechanism through Bubble events. This design pattern allowed us to offer a one-to-one mapping of the OpenPGP API to Bubble element actions. Additionally, all the element actions run truly asynchronous. The server-side actions explicitly chains the Promises in the actions, with the downside that the server-side processing consumes more server resources.

Just Added Encryption and decryption of raw bytes is now supported on both the client-side and server-side. For client-side this is mediated by user file prompts and the new read file action. On the server-side the raw bytes have to be coerced to and from Base 64. Explicit signing and verification is now done with much more convenient detached signatures.

This plugin supports OpenPGP RSA 4096:

  • Key pair generation.
  • Single public key encryption.
  • Single private key decryption.
  • Single private key detached signing.
  • Single public key detached signature verification.

Review the code and demonstration pages:

Check back here frequently as we are working on instructional videos covering this new plugin.


Hey! Seems cool. Is this used mostly for encrypting stuff?

Yup, it supports OpenPGP RSA 4096:

  • Key pair generation.
  • Public key encryption.
  • Private key decryption.
  • Private key signing.
  • Public key signature verification.

Our particular use case was secondary credentials on text files transferred by sFTP.

1 Like

We have added more functionality. See the main post above.

1 Like

How do I get data returned from the readKey method as it is not included in the server side workflows

Ah yes. To get the plugin off the ground I structured the Server-Side functionality around the much more directly imperative “encrypt, decrypt, etc…”. I did this because I wanted to chain the promises of OpenPGP.js together, and Bubble only produces primitive data types. The client-side function works more directly with the promises and is also more secure because there is no recording of input to the server logs.

uh-oh! My use case requires me to encrypt with the data returned from readKey passed in as the encryptionKey. So is it impossible to do this or is there any other way? I’ll appreciate your help

Do you have access to the OpenPGP formatted armoured public key text?

---- Begin Block Public Key -----


I just wrote that plugin a couple months ago and haven’t had time to record documentation videos. The essence of the server-side action is that it expects the formated public key block as a Bubble Long String.

In theory the text of the public key and the symmetrically encrypted private key should be safe to share, provided the symmetric key is strong. As well it is very important to note that ALL inputs to server-side actions are recorded in the server logs. So anything you are encrypting on the server-side should be safe for your Bubble admin to read.

Yes I fetch openpgp formatted armoured txt from an api and then pass it to readKey I think it’s supposed to return a decodedPubKeywhich I can then pass in as encryptionKey when running the encryptfunction. The problem i’m having is that I don’t know how to access the returned key from the readKey function. I hope this makes sense. Forgive my typos if any

Perfect. The encrypt action expects the armored public key. ReadKey is called implicitly inside the action. As soon as I’m back at my desk I’ll post a PDF diagram I put together illustrating how the promises are chained. In the plugin itself I used Bubble’s action documentation to record this explanation. Unfortunately Bubble does not propagate that documentation to the plugin user. Too bad because that would be very helpful.

I’ll add the PDF to a GitHub page tomorrow.

Ok it’s starting to make sense now. If I understand correctly, I’ll call the ReadKey, createMessage and EncryptMessageaction on the client side and then run encrypt on the server side passing in PGP element states as parameters.

This has been really helpful and yes the pdf diagram will make a lot of sense. Thank you

You can do this client side as well:

  1. Retrieve the armored public key from the api (HTTPS Fetch or XMLHTTPSRequest?).
  2. Call the Public Key Read action.
  3. This will raise the Public Key Read (past tense), event.
  4. In that event call the Create Message action, with the text you want to encrypt, or call Read File if you want to encrypt a whole file
  5. This will raise the Message Created or File Selected events respectively
  6. In the appropriate event call the Encrypt Message action
  7. This will raise the Message Encrypted event. In the case of a file this will also prompt the user to save the file. In the case of text it will populate the Message state with the encrypted message.

I’ve explicitly laid out the plugin using promise chaining as a security measure. This prevents intermediate data from being exposed in the Bubble workflow itself. One would need direct access to the JavaScript’s memory to read the intermediate values of things like encrypted private keys.

Side note, I need to do something smarter with the file than just prompting the user to save it. At the very least I need to pass the local blob URL through a state so that it can be uploaded.

Everything seems fine until the last step which for some reason doesn’t announce the Message encrypted event

I’ll take a look at the plugin.

Hi Aaron, I noticed that public keys generated with your plugin actually works but the armored key I got from the API doesn’t even though I included the ‘------ BEGIN PGP PUBLIC KEY BLOCK-----’ and ‘-----END PGP PUBLIC KEY BLOCK-----’. I’m not exactly sure if my public key’s rsaBits is 4096 or not as it was not specified in the API documentation but I suspect it might be the problem. Is there any way I could confirm the actual RSA standard?

Oh shoot that is tough. I basically just Bubble wrapped a Node.js library that was built to expect 100% conformant PGP formatting. I’m not sure what to recommend if a third part is producing output that is a bit more “loosely” formatted. I do realize there is a lot of variation out their in the wild.