For Educational Purposes only, this guide will allow you to build the cryptomator desktop app from source, and grant you a valid license.
Requirements
- Java JDK 24
- Maven
- git
Modding the source
- 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
- 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
- Apply patches
git apply ./LicenseChecker.java.patch
git apply ./LicenseHolder.java.patch
Building the application
- Download Java JDK 24 from Eclipse Temurin for Linux
- Extract the Java JDK
tar -xf ./OpenJDK24U-jdk_x64_linux_hotspot_24.0.1_9.tar.gz
- Set the
JAVA_HOME
to the exported path (or wherever you extracted)
export JAVA_HOME="$PWD/jdk-24.0.1+9/"
- Ensure
maven
is installed (GUIDE) - 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 yourJAVA_HOME
to be - Ensure the
Java version
is24.x.x
- Navigate to the appimage build folder
# within the cloned cryptomator repository
cd ./dist/linux/appimage
- 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