Show specific message if desktop supporter cert entered as license key

This commit is contained in:
Julian Raufelder 2022-02-24 15:43:11 +01:00
parent 71dc76b157
commit e1a5ff7007
No known key found for this signature in database
GPG Key ID: 17EE71F6634E381D
4 changed files with 38 additions and 20 deletions

View File

@ -0,0 +1,9 @@
package org.cryptomator.domain.exception.license;
public class DesktopSupporterCertificateException extends LicenseNotValidException {
public DesktopSupporterCertificateException(final String license) {
super(license);
}
}

View File

@ -4,6 +4,7 @@ import com.google.common.io.BaseEncoding;
import org.cryptomator.domain.exception.BackendException;
import org.cryptomator.domain.exception.FatalBackendException;
import org.cryptomator.domain.exception.license.DesktopSupporterCertificateException;
import org.cryptomator.domain.exception.license.LicenseNotValidException;
import org.cryptomator.domain.exception.license.NoLicenseAvailableException;
import org.cryptomator.domain.repository.UpdateCheckRepository;
@ -20,10 +21,19 @@ import java.security.spec.X509EncodedKeySpec;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.SignatureException;
@UseCase
public class DoLicenseCheck {
private static final String ANDROID_PUB_KEY = "MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBcnb81CfNeL3qBVFMx/yRfm1Y1yib" + //
"ajIJkV1s82AQt+mOl4+Kub64wq1OCgBVwWUlKwqgnyF39nmkoXEjakRPFngBzg2J" + //
"zo4UR0B7OYmn0uGf3K+zQfxKnNMxGVPtlzE8j9Nqz/dm2YvYLLVwvTSDQX/GaxoP" + //
"/EH84Hupw2wuU7qAaFU=";
private static final String DESKTOP_SUPPORTER_CERTIFICATE_PUB_KEY = "MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQB7NfnqiZbg2KTmoflmZ71PbXru7oW" + //
"fmnV2yv3eDjlDfGruBrqz9TtXBZV/eYWt31xu1osIqaT12lKBvZ511aaAkIBeOEV" + //
"gwcBIlJr6kUw7NKzeJt7r2rrsOyQoOG2nWc/Of/NBqA3mIZRHk5Aq1YupFdD26QE" + //
"r0DzRyj4ixPIt38CQB8=";
private final UpdateCheckRepository updateCheckRepository;
private String license;
@ -34,17 +44,13 @@ public class DoLicenseCheck {
public LicenseCheck execute() throws BackendException {
license = useLicenseOrRetrieveFromDb(license);
try {
final Claims claims = Jwts //
.parserBuilder() //
.setSigningKey(getPublicKey()) //
.build() //
.parseClaimsJws(license) //
.getBody();
final Claims claims = Jwts.parserBuilder().setSigningKey(getPublicKey(ANDROID_PUB_KEY)).build().parseClaimsJws(license).getBody();
return claims::getSubject;
} catch (JwtException | FatalBackendException e) {
if (e instanceof SignatureException && isDesktopSupporterCertificate(license)) {
throw new DesktopSupporterCertificateException(license);
}
throw new LicenseNotValidException(license);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
throw new FatalBackendException(e);
@ -56,28 +62,29 @@ public class DoLicenseCheck {
updateCheckRepository.setLicense(license);
} else {
license = updateCheckRepository.getLicense();
if (license == null) {
throw new NoLicenseAvailableException();
}
}
return license;
}
private ECPublicKey getPublicKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
final byte[] publicKey = BaseEncoding //
.base64() //
.decode("MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBcnb81CfNeL3qBVFMx/yRfm1Y1yib" + //
"ajIJkV1s82AQt+mOl4+Kub64wq1OCgBVwWUlKwqgnyF39nmkoXEjakRPFngBzg2J" + //
"zo4UR0B7OYmn0uGf3K+zQfxKnNMxGVPtlzE8j9Nqz/dm2YvYLLVwvTSDQX/GaxoP" + //
"/EH84Hupw2wuU7qAaFU=");
Key key = KeyFactory.getInstance("EC").generatePublic(new X509EncodedKeySpec(publicKey));
private ECPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
final X509EncodedKeySpec keySpec = new X509EncodedKeySpec(BaseEncoding.base64().decode(publicKey));
Key key = KeyFactory.getInstance("EC").generatePublic(keySpec);
if (key instanceof ECPublicKey) {
return (ECPublicKey) key;
} else {
throw new FatalBackendException("Key not an EC public key.");
}
}
private boolean isDesktopSupporterCertificate(String license) {
try {
Jwts.parserBuilder().setSigningKey(getPublicKey(DESKTOP_SUPPORTER_CERTIFICATE_PUB_KEY)).build().parseClaimsJws(license);
return true;
} catch (JwtException | NoSuchAlgorithmException | InvalidKeySpecException e) {
return false;
}
}
}

View File

@ -13,6 +13,7 @@ import org.cryptomator.domain.exception.NoSuchCloudFileException
import org.cryptomator.domain.exception.UnableToDecryptWebdavPasswordException
import org.cryptomator.domain.exception.VaultAlreadyExistException
import org.cryptomator.domain.exception.authentication.AuthenticationException
import org.cryptomator.domain.exception.license.DesktopSupporterCertificateException
import org.cryptomator.domain.exception.license.LicenseNotValidException
import org.cryptomator.domain.exception.license.NoLicenseAvailableException
import org.cryptomator.domain.exception.update.GeneralUpdateErrorException
@ -25,7 +26,6 @@ import org.cryptomator.domain.exception.vaultconfig.VaultVersionMismatchExceptio
import org.cryptomator.presentation.R
import org.cryptomator.presentation.ui.activity.view.View
import org.cryptomator.presentation.util.ResourceHelper
import java.util.ArrayList
import java.util.Collections
import javax.inject.Inject
import timber.log.Timber
@ -48,6 +48,7 @@ class ExceptionHandlers @Inject constructor(private val context: Context, defaul
staticHandler(NoSuchCloudFileException::class.java, R.string.error_no_such_file)
staticHandler(IllegalFileNameException::class.java, R.string.error_export_illegal_file_name)
staticHandler(UnableToDecryptWebdavPasswordException::class.java, R.string.error_failed_to_decrypt_webdav_password)
staticHandler(DesktopSupporterCertificateException::class.java, R.string.dialog_enter_license_not_valid_content_desktop_supporter_certificate)
staticHandler(LicenseNotValidException::class.java, R.string.dialog_enter_license_not_valid_content)
staticHandler(NoLicenseAvailableException::class.java, R.string.dialog_enter_license_no_content)
staticHandler(HashMismatchUpdateCheckException::class.java, R.string.error_hash_mismatch_update)

View File

@ -447,6 +447,7 @@
<string name="dialog_enter_license_title">Provide a valid license</string>
<string name="dialog_enter_license_content">We detected that you installed Cryptomator without using Google Play Store. Provide a valid license, which can be purchased on <a href="https://cryptomator.org/android/">https://cryptomator.org/android/</a></string>
<string name="dialog_enter_license_not_valid_content">The provided license isn\'t valid. Make sure you entered it correctly.</string>
<string name="dialog_enter_license_not_valid_content_desktop_supporter_certificate">The provided key is a desktop supporter certificate. Please enter a valid license.</string>
<string name="dialog_enter_license_no_content">No license provided. Please enter a valid license.</string>
<string name="dialog_enter_license_ok_button" translatable="false">@string/dialog_unable_to_share_positive_button</string>
<string name="dialog_enter_license_decline_button">Exit</string>