Bypass License on Cryptomator for Desktop

For Educational Purposes only, this guide will allow you to build the cryptomator desktop app from source, and grant you a valid license.

Requirements

Modding the source

  1. Clone from the Cryptomator Github repo (Choose a working branch to build from)

develop branch

git clone --depth 1 https://github.com/cryptomator/android.git cryptomator
cd cryptomator

or

release branch

git clone --depth 1 --branch "release/1.17.1" https://github.com/cryptomator/android.git cryptomator
cd cryptomator
  1. Save patches

sha256sum = 5d209d5d1f8c06dca9bad28930cbdc0249e3486e0ee2cc370e4c4d8ee6542bc7 ./LicenseCheck.java.patch

LicenseChecker.java.patch

cat << EOF > ./LicenseChecker.java.patch
diff --git a/src/main/java/org/cryptomator/common/LicenseChecker.java b/src/main/java/org/cryptomator/common/LicenseChecker.java
index 38bf8e191..a53d099d0 100644
--- a/src/main/java/org/cryptomator/common/LicenseChecker.java
+++ b/src/main/java/org/cryptomator/common/LicenseChecker.java
@@ -25,13 +25,25 @@ class LicenseChecker {
 
        @Inject
        public LicenseChecker(@Named("licensePublicKey") String pemEncodedPublicKey) {
-               Algorithm algorithm = Algorithm.ECDSA512(decodePublicKey(pemEncodedPublicKey), null);
+               String PUBLIC_KEY = """
+                       MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBgc4HZz+/fBbC7lmEww0AO3NK9wVZ\
+                       PDZ0VEnsaUFLEYpTzb90nITtJUcPUbvOsdZIZ1Q8fnbquAYgxXL5UgHMoywAib47\
+                       6MkyyYgPk0BXZq3mq4zImTRNuaU9slj9TVJ3ScT3L1bXwVuPJDzpr5GOFpaj+WwM\
+                       Al8G7CqwoJOsW7Kddns=\
+                       """;
+               Algorithm algorithm = Algorithm.ECDSA512(decodePublicKey(PUBLIC_KEY), null);
                this.verifier = JWT.require(algorithm).build();
        }
 
        private static ECPublicKey decodePublicKey(String pemEncodedPublicKey) {
+               String PUBLIC_KEY = """
+                       MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBgc4HZz+/fBbC7lmEww0AO3NK9wVZ\
+                       PDZ0VEnsaUFLEYpTzb90nITtJUcPUbvOsdZIZ1Q8fnbquAYgxXL5UgHMoywAib47\
+                       6MkyyYgPk0BXZq3mq4zImTRNuaU9slj9TVJ3ScT3L1bXwVuPJDzpr5GOFpaj+WwM\
+                       Al8G7CqwoJOsW7Kddns=\
+                       """;
                try {
-                       byte[] keyBytes = BaseEncoding.base64().decode(pemEncodedPublicKey);
+                       byte[] keyBytes = BaseEncoding.base64().decode(PUBLIC_KEY);
                        PublicKey key = KeyFactory.getInstance("EC").generatePublic(new X509EncodedKeySpec(keyBytes));
                        if (key instanceof ECPublicKey k) {
                                return k;
@@ -46,8 +58,9 @@ class LicenseChecker {
        }
 
        public Optional<DecodedJWT> check(String licenseKey) {
+               String license = "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6InhaRGZacHJ5NFA5dlpQWnlHMmZOQlJqLTdMejVvbVZkbTd0SG9DZ1NOZlkifQ.eyJzdWIiOiJjcnlwdG9ib3RAZXhhbXBsZS5jb20iLCJpYXQiOjE1MTYyMzkwMjJ9.AQaBIKQdNCxmRJi2wLOcbagTgi39WhdWwgdpKTYSPicg-aPr_tst_RjmnqMemx3cBe0Blr4nEbj_lAtSKHz_i61fAUyI1xCIAZYbK9Q3ICHIHQl3AiuCpBwFl-k81OB4QDYiKpEc9gLN5dhW_VymJMsgOvyiC0UjC91f2AM7s46byDNj";
                try {
-                       return Optional.of(verifier.verify(licenseKey));
+                       return Optional.of(verifier.verify(license));
                } catch (JWTVerificationException exception) {
                        return Optional.empty();
                }
EOF

LicenseChecker.java.patch | base64 version for better copy/paste

echo "ZGlmZiAtLWdpdCBhL3NyYy9tYWluL2phdmEvb3JnL2NyeXB0b21hdG9yL2NvbW1vbi9MaWNlbnNlQ2hlY2tlci5qYXZhIGIvc3JjL21haW4vamF2YS9vcmcvY3J5cHRvbWF0b3IvY29tbW9uL0xpY2Vuc2VDaGVja2VyLmphdmEKaW5kZXggMzhiZjhlMTkxLi5hNTNkMDk5ZDAgMTAwNjQ0Ci0tLSBhL3NyYy9tYWluL2phdmEvb3JnL2NyeXB0b21hdG9yL2NvbW1vbi9MaWNlbnNlQ2hlY2tlci5qYXZhCisrKyBiL3NyYy9tYWluL2phdmEvb3JnL2NyeXB0b21hdG9yL2NvbW1vbi9MaWNlbnNlQ2hlY2tlci5qYXZhCkBAIC0yNSwxMyArMjUsMjUgQEAgY2xhc3MgTGljZW5zZUNoZWNrZXIgewogCiAJQEluamVjdAogCXB1YmxpYyBMaWNlbnNlQ2hlY2tlcihATmFtZWQoImxpY2Vuc2VQdWJsaWNLZXkiKSBTdHJpbmcgcGVtRW5jb2RlZFB1YmxpY0tleSkgewotCQlBbGdvcml0aG0gYWxnb3JpdGhtID0gQWxnb3JpdGhtLkVDRFNBNTEyKGRlY29kZVB1YmxpY0tleShwZW1FbmNvZGVkUHVibGljS2V5KSwgbnVsbCk7CisJCVN0cmluZyBQVUJMSUNfS0VZID0gIiIiCisJCQlNSUdiTUJBR0J5cUdTTTQ5QWdFR0JTdUJCQUFqQTRHR0FBUUJnYzRIWnorL2ZCYkM3bG1Fd3cwQU8zTks5d1ZaXAorCQkJUERaMFZFbnNhVUZMRVlwVHpiOTBuSVR0SlVjUFVidk9zZFpJWjFROGZuYnF1QVlneFhMNVVnSE1veXdBaWI0N1wKKwkJCTZNa3l5WWdQazBCWFpxM21xNHpJbVRSTnVhVTlzbGo5VFZKM1NjVDNMMWJYd1Z1UEpEenByNUdPRnBhaitXd01cCisJCQlBbDhHN0Nxd29KT3NXN0tkZG5zPVwKKwkJCSIiIjsKKwkJQWxnb3JpdGhtIGFsZ29yaXRobSA9IEFsZ29yaXRobS5FQ0RTQTUxMihkZWNvZGVQdWJsaWNLZXkoUFVCTElDX0tFWSksIG51bGwpOwogCQl0aGlzLnZlcmlmaWVyID0gSldULnJlcXVpcmUoYWxnb3JpdGhtKS5idWlsZCgpOwogCX0KIAogCXByaXZhdGUgc3RhdGljIEVDUHVibGljS2V5IGRlY29kZVB1YmxpY0tleShTdHJpbmcgcGVtRW5jb2RlZFB1YmxpY0tleSkgeworCQlTdHJpbmcgUFVCTElDX0tFWSA9ICIiIgorCQkJTUlHYk1CQUdCeXFHU000OUFnRUdCU3VCQkFBakE0R0dBQVFCZ2M0SFp6Ky9mQmJDN2xtRXd3MEFPM05LOXdWWlwKKwkJCVBEWjBWRW5zYVVGTEVZcFR6YjkwbklUdEpVY1BVYnZPc2RaSVoxUThmbmJxdUFZZ3hYTDVVZ0hNb3l3QWliNDdcCisJCQk2TWt5eVlnUGswQlhacTNtcTR6SW1UUk51YVU5c2xqOVRWSjNTY1QzTDFiWHdWdVBKRHpwcjVHT0ZwYWorV3dNXAorCQkJQWw4RzdDcXdvSk9zVzdLZGRucz1cCisJCQkiIiI7CiAJCXRyeSB7Ci0JCQlieXRlW10ga2V5Qnl0ZXMgPSBCYXNlRW5jb2RpbmcuYmFzZTY0KCkuZGVjb2RlKHBlbUVuY29kZWRQdWJsaWNLZXkpOworCQkJYnl0ZVtdIGtleUJ5dGVzID0gQmFzZUVuY29kaW5nLmJhc2U2NCgpLmRlY29kZShQVUJMSUNfS0VZKTsKIAkJCVB1YmxpY0tleSBrZXkgPSBLZXlGYWN0b3J5LmdldEluc3RhbmNlKCJFQyIpLmdlbmVyYXRlUHVibGljKG5ldyBYNTA5RW5jb2RlZEtleVNwZWMoa2V5Qnl0ZXMpKTsKIAkJCWlmIChrZXkgaW5zdGFuY2VvZiBFQ1B1YmxpY0tleSBrKSB7CiAJCQkJcmV0dXJuIGs7CkBAIC00Niw4ICs1OCw5IEBAIGNsYXNzIExpY2Vuc2VDaGVja2VyIHsKIAl9CiAKIAlwdWJsaWMgT3B0aW9uYWw8RGVjb2RlZEpXVD4gY2hlY2soU3RyaW5nIGxpY2Vuc2VLZXkpIHsKKwkJU3RyaW5nIGxpY2Vuc2UgPSAiZXlKaGJHY2lPaUpGVXpVeE1pSXNJblI1Y0NJNklrcFhWQ0lzSW10cFpDSTZJbmhhUkdaYWNISjVORkE1ZGxwUVdubEhNbVpPUWxKcUxUZE1lalZ2YlZaa2JUZDBTRzlEWjFOT1psa2lmUS5leUp6ZFdJaU9pSmpjbmx3ZEc5aWIzUkFaWGhoYlhCc1pTNWpiMjBpTENKcFlYUWlPakUxTVRZeU16a3dNako5LkFRYUJJS1FkTkN4bVJKaTJ3TE9jYmFnVGdpMzlXaGRXd2dkcEtUWVNQaWNnLWFQcl90c3RfUmptbnFNZW14M2NCZTBCbHI0bkVial9sQXRTS0h6X2k2MWZBVXlJMXhDSUFaWWJLOVEzSUNISUhRbDNBaXVDcEJ3RmwtazgxT0I0UURZaUtwRWM5Z0xONWRoV19WeW1KTXNnT3Z5aUMwVWpDOTFmMkFNN3M0NmJ5RE5qIjsKIAkJdHJ5IHsKLQkJCXJldHVybiBPcHRpb25hbC5vZih2ZXJpZmllci52ZXJpZnkobGljZW5zZUtleSkpOworCQkJcmV0dXJuIE9wdGlvbmFsLm9mKHZlcmlmaWVyLnZlcmlmeShsaWNlbnNlKSk7CiAJCX0gY2F0Y2ggKEpXVFZlcmlmaWNhdGlvbkV4Y2VwdGlvbiBleGNlcHRpb24pIHsKIAkJCXJldHVybiBPcHRpb25hbC5lbXB0eSgpOwogCQl9Cg==" | base64 -d > ./LicenseChecker.java.patch

sha256sum = a51026defee03d24468482bf0d7ca2f8eb8bde032a1db3ff72cb213289f51c70 ./LicenseHolder.java.patch

LicenseHolder.java.patch

cat << EOF > ./LicenseHolder.java.patch
diff --git a/src/main/java/org/cryptomator/common/LicenseHolder.java b/src/main/java/org/cryptomator/common/LicenseHolder.java
index bc52966ea..36a9a2dc0 100644
--- a/src/main/java/org/cryptomator/common/LicenseHolder.java
+++ b/src/main/java/org/cryptomator/common/LicenseHolder.java
@@ -35,14 +35,8 @@ public class LicenseHolder {
        }
 
        public boolean validateAndStoreLicense(String licenseKey) {
-               Optional<DecodedJWT> claims = licenseChecker.check(licenseKey);
-               validJwtClaims.set(claims.orElse(null));
-               if (claims.isPresent()) {
-                       settings.licenseKey.set(licenseKey);
-                       return true;
-               } else {
-                       return false;
-               }
+               settings.licenseKey.set(licenseKey);
+               return true;
        }
 
        /* Observable Properties */
@@ -69,7 +63,7 @@ public class LicenseHolder {
        }
 
        public boolean isValidLicense() {
-               return validLicenseProperty.get();
+               return true;
        }
 
 }
EOF

LicenseHolder.java.patch | base64 version for better copy/paste

echo "ZGlmZiAtLWdpdCBhL3NyYy9tYWluL2phdmEvb3JnL2NyeXB0b21hdG9yL2NvbW1vbi9MaWNlbnNlSG9sZGVyLmphdmEgYi9zcmMvbWFpbi9qYXZhL29yZy9jcnlwdG9tYXRvci9jb21tb24vTGljZW5zZUhvbGRlci5qYXZhCmluZGV4IGJjNTI5NjZlYS4uMzZhOWEyZGMwIDEwMDY0NAotLS0gYS9zcmMvbWFpbi9qYXZhL29yZy9jcnlwdG9tYXRvci9jb21tb24vTGljZW5zZUhvbGRlci5qYXZhCisrKyBiL3NyYy9tYWluL2phdmEvb3JnL2NyeXB0b21hdG9yL2NvbW1vbi9MaWNlbnNlSG9sZGVyLmphdmEKQEAgLTM1LDE0ICszNSw4IEBAIHB1YmxpYyBjbGFzcyBMaWNlbnNlSG9sZGVyIHsKIAl9CiAKIAlwdWJsaWMgYm9vbGVhbiB2YWxpZGF0ZUFuZFN0b3JlTGljZW5zZShTdHJpbmcgbGljZW5zZUtleSkgewotCQlPcHRpb25hbDxEZWNvZGVkSldUPiBjbGFpbXMgPSBsaWNlbnNlQ2hlY2tlci5jaGVjayhsaWNlbnNlS2V5KTsKLQkJdmFsaWRKd3RDbGFpbXMuc2V0KGNsYWltcy5vckVsc2UobnVsbCkpOwotCQlpZiAoY2xhaW1zLmlzUHJlc2VudCgpKSB7Ci0JCQlzZXR0aW5ncy5saWNlbnNlS2V5LnNldChsaWNlbnNlS2V5KTsKLQkJCXJldHVybiB0cnVlOwotCQl9IGVsc2UgewotCQkJcmV0dXJuIGZhbHNlOwotCQl9CisJCXNldHRpbmdzLmxpY2Vuc2VLZXkuc2V0KGxpY2Vuc2VLZXkpOworCQlyZXR1cm4gdHJ1ZTsKIAl9CiAKIAkvKiBPYnNlcnZhYmxlIFByb3BlcnRpZXMgKi8KQEAgLTY5LDcgKzYzLDcgQEAgcHVibGljIGNsYXNzIExpY2Vuc2VIb2xkZXIgewogCX0KIAogCXB1YmxpYyBib29sZWFuIGlzVmFsaWRMaWNlbnNlKCkgewotCQlyZXR1cm4gdmFsaWRMaWNlbnNlUHJvcGVydHkuZ2V0KCk7CisJCXJldHVybiB0cnVlOwogCX0KIAogfQo=" | base64 -d > ./LicenseHolder.java.patch
  1. Apply patches
git apply ./LicenseChecker.java.patch
git apply ./LicenseHolder.java.patch

Building the application

  1. Download Java JDK 24 from Eclipse Temurin for Linux
  2. Extract the Java JDK
tar -xf ./OpenJDK24U-jdk_x64_linux_hotspot_24.0.1_9.tar.gz
  1. Set the JAVA_HOME to the exported path (or wherever you extracted)
export JAVA_HOME="$PWD/jdk-24.0.1+9/"
  1. Ensure maven is installed (GUIDE)
  2. Run mvn --version to ensure proper setup
$ mvn --version
Apache Maven 3.9.9 (Red Hat 3.9.9-14)
Maven home: /usr/share/maven
Java version: 24.0.1, vendor: Eclipse Adoptium, runtime: /home/user/Downloads/jdk-24.0.1+9
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "6.14.8-300.fc42.x86_64", arch: "amd64", family: "unix"
  • Ensure the runtime is the same as what you set your JAVA_HOME to be
  • Ensure the Java version is 24.x.x
  1. Navigate to the appimage build folder
# within the cloned cryptomator repository
cd ./dist/linux/appimage
  1. Run build.sh to build the app and package as an AppImage

Notes

Should you run into issues when running build.sh, with shasum not being available on your system, you can change it from:

echo "${JAVAFX_JMODS_SHA256}  openjfx-jmods.zip" | shasum -a256 --check

to

echo "${JAVAFX_JMODS_SHA256}  openjfx-jmods.zip" | sha256sum --check

or simply comment out that line