Creative Developer Tools – status update

I’ve been working hard on Creative Developer Tools (CRDT).

My current focus is to implement a unified packager/installer/license management for third party Adobe scripts/extensions/plug-ins.

PluginInstaller handles the whole developer-to-user chain: packaging, downloading, installing, removing, updating…

I’ve just finished adding support for CEP. PluginInstaller now handles plain ExtendScript as well as CEP extensions. Next up is UXP.

PluginInstaller is part of the growing suite of Creative Developer Tools.

Unified Packager/Installer

PluginInstaller handles both packaging (developer side) and installing (user side) of third party enhancements to the Adobe Creative Cloud apps.

I’ve just released a new version of the PluginInstaller which combines support for plain ExtendScript (.jsx) as well as CEP panels (.zxp).

My plan is to further extend PluginInstaller so the same packager/installer will also handle UXP/UXPScript and C++ plug-ins.

PluginInstaller uses a unified package format (.tpkg) which combines a number of features:

  • Code signing
  • Code encryption
  • Licensing and activation
  • JSON meta-information in the .tpkg file header
  • Support multiple types of solutions (.jsx, .zxp…)

PluginInstaller can be downloaded here:

CEP: no more ZXPSignCmd

I’ve managed to fully integrate all the steps needed for .zxp code signing into CRDT/PluginInstaller.

As we all know, Adobe’s .zxp code signing is both required and ineffective – i.e. it’s just security theater. Just an additional hurdle that developers have to jump.

When packaging a CEP extension using PluginInstaller, it will automatically create and manage the necessary self-signed signing certificates during the packaging operation.

Separate of the Adobe code signing setup, CRDT/PluginInstaller implements a more generic code signing mechanism. This mechanism can handle all kind of project types, including plain ExtendScript script projects.

When PluginInstaller manages a CEP extension, it transparently manages two distinct ‘layers’ of code signing: one as imposed by Adobe, the second layer is handled by CRDT.

PluginInstaller will build both a standard .zxp as well as a .tpkg file when packaging a CEP extension.

The .zxp file is a courtesy file which is not needed nor used by CRDT. It allows the developer to opt for using existing installer tools (e.g. Anastasiy’s Extension Manager) instead of PluginInstaller.

Such .zxp is not protected by CRDT code signing, but it can still have access to the protective CRDT code encryption features as long as the CRDT_ES runtime is included into the package.

The PluginInstaller also handles downloading of .tpkg and handles management of activation files for commercial solutions that need licensing/demo configurations.

CRDT Encryption

CRDT uses two levels of encryption, for two different purposes: an outer level (public/private key) handles code signing, and an inner level (AES-256) handles code protection.

Code signing is there to protect the user: they can verify that the code they are about to run was created by someone they can trust.

Code encryption is there to protect the developer: it blocks malicious users from inspecting and copying the crucial code magic that makes a software solution work.

.tpkg files

.tpkg files are self-identifying. They are structured so they have a human/computer readable JSON header which contains useful meta-info about their content.

This also allows the use of partial downloads: we can download the first 1024 bytes of any .tpkg file and figure out what they are without having to download the whole file.

CRDT Code Signing

When a developer registers a developer account in PluginManager, it will use OpenSSL to automatically generate a public/private key pair and publish the public key in online registry. PluginInstaller handles key generation automatically and there is no cost to creating these keys.

The private key is only stored on the developer’s workstation and used to encrypt anything that gets packaged by the developer.

A package will only work when it is decrypted with the matching public developer key as retrieved from the registry.

The approach was chosen to avoid forcing developers to deal with expensive code-signing certificates.

When a developer creates a .tpkg, the file is encrypted using the developer’s private key.

Then, when the user downloads and installs the .tpkg, the file is decrypted using the developer’s public key as retrieved from the registry.

That way the user can make sure they know who the .tpkg was created by.

Code encryption

When a .tpkg file contains .jsx files, they are encrypted using AES-256.

CRDT_ES comes with a binary runtime in a .dylib/.dll. This runtime is loaded into the ExtendScript engine inside the host app, and it handles on-the-fly decryption and execution. This works for plain .jsx as well as for .jsx embedded inside a CEP solution/.zxp.

CRDT currently does not transparently handle encryption of other file types than .jsx (e.g. .js).

Encryption of .js files (as opposed to .jsx files) would currently not be a strong deterrent for hackers because the decrypted .js code could be inspected by way of a debugger, simply by putting a breakpoint after the decryption call.

.jsx is different: CRDT can execute the encrypted code straight from the CRDT runtime, which is binary C++ code, without making the code easily inspectable in an ExtendScript debugger. By judiciously using closures, the code can be made inaccessible to would-be snoopers that know how to use the ExtendScript debugger.

For .js I cannot do that (yet). I do plan to change this later, but I need to do some research and find Adobe documentation: I need to be able to embed and call a binary runtime from the embedded Node.js or UXP engines. I am eagerly awaiting the ability to call C++ code from a UXP script.

For the time being, if you have .js code that needs to be protected from prying eyes, stash it in a .jsx and call it from .js through CSInterface, or else use the ‘standard’ approach of uglifying the code.


CRDT encryption/decryption is also tied into the tracking/licensing/activation mechanisms. It allows developers to add code to decide whether their plugin/script is active/not active/in demo/paid for mode…

Depending on the situation, their extension can stop working, or be limited in features – whatever they want.

Payment Handling

Currently I don’t have payment handling integrated yet; but I plan to build sample integrations for PayPal and Stripe.

Developers can then decide to either use my integrations or create their own.

For the time being, when using CRDT for licensing, users need to pay the developer via a standard invoicing mechanism, after which can be emailed an activation file generated in PluginInstaller by the developer.

This is a manual process, which should be manageable for small developers.

Eventually this will all be fully automated.

CRDT also has support for sub-licensing, and can handle floating licenses to support licensing a developer’s solutions to larger companies.