godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.93k stars 21.15k forks source link

Protecting game resources in exported apk #39115

Closed dariuspranskus closed 4 years ago

dariuspranskus commented 4 years ago

Hello

This is not a bug as such, this was raised and discussed some time ago #19790 but I would like to raise this question again.

I completely understand, that there is no way to securely export encrypted/compressed assets and script files to apk which couldn't be hacked or broken in.

But I still believe that the files should not be exported to apk in plain text or the whole folder structure is visible. For me this is one of the biggest issues at the moment.

I started my game with unity, and was overwhelmed how it is heavy not for development but how it is running, every task takes ages. Then I played with the Game Maker, and it was OK, except that it demanded so much resources. And then I came across Godot, and it was almost perfect, light, fast and full of features. Until I discovered this issue

I do not want to port my game third time to some other platform.

So I would like to ask, please, how would it be possible to pack and encrypt my assets/code/scenes in apk into single/few files, so it is not visible just by unzipping.

I have recently became patreon and would also be willing to contribute to the codebase. I am a developer with many years of experience in various languages, unfortunately not in C++, but I understand the syntax, and would figure it out somehow, if someone can lead me into right direction. I would really want to develop such feature in Godot.

Thanks Regards, Darius

Calinou commented 4 years ago

Please don't ask support questions here, as this issue tracker is meant to be used for bug reports only. Use one of the other community channels instead.

You could also open a proposal on the Godot proposals repository, although writing a good proposal will be easier if you have prior experience with obfuscation/encryption systems.

Also, I would consider this to be mostly a duplicate of https://github.com/godotengine/godot/issues/24716 (since all game data is located in the PCK file which is in the APK).

Edit: The part about PCK is not actually correct, see https://github.com/godotengine/godot/issues/39115#issuecomment-635286804.

akien-mga commented 4 years ago

Also see #38308 (which aims at solving #24716).

dariuspranskus commented 4 years ago

This solves the issue only partially. All the file directory structure is visible in APK. Some of the files are still in plain text

Calinou commented 4 years ago

@dariuspranskus There should only be a handful of manifest files outside the PCK file. All your game scripts and artwork are inside the PCK.

Edit: This is not actually correct, see https://github.com/godotengine/godot/issues/39115#issuecomment-635286804.

dariuspranskus commented 4 years ago

Please don't ask support questions here, as this issue tracker is meant to be used for bug reports only. Use one of the other community channels instead.

You could also open a proposal on the Godot proposals repository, although writing a good proposal will be easier if you have prior experience with obfuscation/encryption systems.

Also, I would consider this to be mostly a duplicate of #24716 (since all game data is located in the PCK file which is in the APK).

I asked 3 or 4 questions on discord, did not receive the answer for most of them. Also I was recommended to ask on github.

Calinou commented 4 years ago

Also I was recommended to ask on github.

Well, I guess they were wrong :slightly_smiling_face:

In general, large GitHub issue trackers don't make for good support platforms, as bug reports will become intertwined with support requests (and sometimes feature requests) over time.

dariuspranskus commented 4 years ago

@dariuspranskus There should only be a handful of manifest files outside the PCK file. All your game scripts and artwork are inside the PCK.

When I export my game into Android APK I am getting all asset files (be it with script encryption or not) put individually into the assets folder. Folders are visible and some files are in plain text. Scripts are either encrypted or compiled.

image

What I am not getting here. Thanks

Calinou commented 4 years ago

@dariuspranskus Did you export the project using the "old" method or the "new" method? Maybe the final structure differs depending on the method used. Still, I was pretty sure only a PCK file was included in the APK.

cc @m4gr3d

dariuspranskus commented 4 years ago

@danielkulas Did you export the project using the "old" method or the "new" method? Maybe the final structure differs depending on the method used. Still, I was pretty sure only a PCK file was included in the APK.

cc @m4gr3d

I used the old method. Will try the new one. Thanks

dariuspranskus commented 4 years ago

@Calinou Same with the "new-way" - individual folders and files in assets folder in APK.

I also found the following discussion about the legal liability to protect loyalty-free assets https://godotforums.org/discussion/22122/there-should-be-options-for-protecting-game-resources-even-if-they-are-third-party#latest.

Zireael07 commented 4 years ago

@dariuspranskus There were issues with the export changes not 'sticking' - did you clear the export folder on PC/uninstall the app completely before retesting? Just making sure you're not seeing the old export...

dariuspranskus commented 4 years ago

@dariuspranskus There were issues with the export changes not 'sticking' - did you clear the export folder on PC/uninstall the app completely before retesting? Just making sure you're not seeing the old export...

@Zireael07 : Using v.3.2.2beta2, emptied the export folder, used the custom build, still no PCK file in the APK, individual folders and indicidual assets and compiled/encrypted scripts in the asset folder inside the APK

dariuspranskus commented 4 years ago

I searched for a PCK string in the Godot source platform sub-folder. As you can see there is no android platform there. It seems that the feature is not available. But it is essential in my opinion

image

akien-mga commented 4 years ago

You can unzip the .apk to see what the contents are.

akien-mga commented 4 years ago

Example from https://gitlab.com/QbieShay/bring-out-your-dead:

        ./AndroidManifest.xml
        ./resources.arsc
        ./kotlin
        ./kotlin/math
        ./kotlin/math/UMathKt.kotlin_metadata
        ./kotlin/math/MathHKt.kotlin_metadata
        ./kotlin/time
        ./kotlin/time/DurationUnit.kotlin_metadata
        ./kotlin/time/ClockKt.kotlin_metadata
        ./kotlin/time/MeasureTimeKt.kotlin_metadata
        ./kotlin/time/Duration.kotlin_metadata
        ./kotlin/time/MonoClock.kotlin_metadata
        ./kotlin/time/Clock.kotlin_metadata
        ./kotlin/time/TestClock.kotlin_metadata
        ./kotlin/time/AdjustedClockMark.kotlin_metadata
        ./kotlin/time/TimedValue.kotlin_metadata
        ./kotlin/time/AbstractDoubleClock.kotlin_metadata
        ./kotlin/time/DurationUnitKt.kotlin_metadata
        ./kotlin/time/AbstractLongClock.kotlin_metadata
        ./kotlin/time/ClockMark.kotlin_metadata
        ./kotlin/time/ExperimentalTime.kotlin_metadata
        ./kotlin/time/DurationKt.kotlin_metadata
        ./kotlin/annotation
        ./kotlin/annotation/annotation.kotlin_builtins
        ./kotlin/ranges
        ./kotlin/ranges/RangesKt.kotlin_metadata
        ./kotlin/ranges/ClosedDoubleRange.kotlin_metadata
        ./kotlin/ranges/ClosedFloatingPointRange.kotlin_metadata
        ./kotlin/ranges/ULongProgression.kotlin_metadata
        ./kotlin/ranges/ULongRange.kotlin_metadata
        ./kotlin/ranges/UIntProgression.kotlin_metadata
        ./kotlin/ranges/ranges.kotlin_builtins
        ./kotlin/ranges/UIntProgressionIterator.kotlin_metadata
        ./kotlin/ranges/UIntRange.kotlin_metadata
        ./kotlin/ranges/ComparableRange.kotlin_metadata
        ./kotlin/ranges/ULongProgressionIterator.kotlin_metadata
        ./kotlin/SuccessOrFailureKt.kotlin_metadata
        ./kotlin/ResultKt.kotlin_metadata
        ./kotlin/StandardKt.kotlin_metadata
        ./kotlin/NoSuchElementException.kotlin_metadata
        ./kotlin/SuspendKt.kotlin_metadata
        ./kotlin/native
        ./kotlin/native/concurrent
        ./kotlin/native/concurrent/ThreadLocal.kotlin_metadata
        ./kotlin/native/concurrent/SharedImmutable.kotlin_metadata
        ./kotlin/UShort.kotlin_metadata
        ./kotlin/OptionalExpectation.kotlin_metadata
        ./kotlin/IllegalStateException.kotlin_metadata
        ./kotlin/InitializedLazyImpl.kotlin_metadata
        ./kotlin/UseExperimental.kotlin_metadata
        ./kotlin/UByteArrayKt.kotlin_metadata
        ./kotlin/UIntArrayKt.kotlin_metadata
        ./kotlin/IllegalArgumentException.kotlin_metadata
        ./kotlin/ConcurrentModificationException.kotlin_metadata
        ./kotlin/LazyKt.kotlin_metadata
        ./kotlin/io
        ./kotlin/io/IoHKt.kotlin_metadata
        ./kotlin/io/Serializable.kotlin_metadata
        ./kotlin/TuplesKt.kotlin_metadata
        ./kotlin/properties
        ./kotlin/properties/ReadOnlyProperty.kotlin_metadata
        ./kotlin/properties/ReadWriteProperty.kotlin_metadata
        ./kotlin/properties/Delegates.kotlin_metadata
        ./kotlin/properties/ObservableProperty.kotlin_metadata
        ./kotlin/properties/NotNullVar.kotlin_metadata
        ./kotlin/UIntKt.kotlin_metadata
        ./kotlin/UninitializedPropertyAccessException.kotlin_metadata
        ./kotlin/experimental
        ./kotlin/experimental/ExperimentalTypeInference.kotlin_metadata
        ./kotlin/experimental/BitwiseOperationsKt.kotlin_metadata
        ./kotlin/ClassCastException.kotlin_metadata
        ./kotlin/NumbersKt.kotlin_metadata
        ./kotlin/ExperimentalUnsignedTypes.kotlin_metadata
        ./kotlin/Result.kotlin_metadata
        ./kotlin/KotlinVersion.kotlin_metadata
        ./kotlin/Pair.kotlin_metadata
        ./kotlin/UIntArray.kotlin_metadata
        ./kotlin/UNumbersKt.kotlin_metadata
        ./kotlin/Triple.kotlin_metadata
        ./kotlin/UByteKt.kotlin_metadata
        ./kotlin/Experimental.kotlin_metadata
        ./kotlin/ULongKt.kotlin_metadata
        ./kotlin/Comparator.kotlin_metadata
        ./kotlin/ULongArray.kotlin_metadata
        ./kotlin/KotlinHKt.kotlin_metadata
        ./kotlin/Error.kotlin_metadata
        ./kotlin/UnsafeLazyImpl.kotlin_metadata
        ./kotlin/UInt.kotlin_metadata
        ./kotlin/collections
        ./kotlin/collections/IndexingIterator.kotlin_metadata
        ./kotlin/collections/HashMap.kotlin_metadata
        ./kotlin/collections/ReversedViewsKt.kotlin_metadata
        ./kotlin/collections/MapAccessorsKt.kotlin_metadata
        ./kotlin/collections/ArrayList.kotlin_metadata
        ./kotlin/collections/UIntIterator.kotlin_metadata
        ./kotlin/collections/SlidingWindowKt.kotlin_metadata
        ./kotlin/collections/RingBuffer.kotlin_metadata
        ./kotlin/collections/ArrayAsCollection.kotlin_metadata
        ./kotlin/collections/ULongIterator.kotlin_metadata
        ./kotlin/collections/SetsKt.kotlin_metadata
        ./kotlin/collections/MutableMapWithDefault.kotlin_metadata
        ./kotlin/collections/AbstractMap.kotlin_metadata
        ./kotlin/collections/LinkedHashSet.kotlin_metadata
        ./kotlin/collections/AbstractSet.kotlin_metadata
        ./kotlin/collections/UArraySortingKt.kotlin_metadata
        ./kotlin/collections/IndexedValue.kotlin_metadata
        ./kotlin/collections/CollectionsHKt.kotlin_metadata
        ./kotlin/collections/AbstractMutableMap.kotlin_metadata
        ./kotlin/collections/MapWithDefaultKt.kotlin_metadata
        ./kotlin/collections/AbstractMutableList.kotlin_metadata
        ./kotlin/collections/UByteIterator.kotlin_metadata
        ./kotlin/collections/MovingSubList.kotlin_metadata
        ./kotlin/collections/IteratorsKt.kotlin_metadata
        ./kotlin/collections/collections.kotlin_builtins
        ./kotlin/collections/AbstractMutableCollection.kotlin_metadata
        ./kotlin/collections/ReversedList.kotlin_metadata
        ./kotlin/collections/AbstractList.kotlin_metadata
        ./kotlin/collections/EmptySet.kotlin_metadata
        ./kotlin/collections/MapWithDefaultImpl.kotlin_metadata
        ./kotlin/collections/AbstractMutableSet.kotlin_metadata
        ./kotlin/collections/State.kotlin_metadata
        ./kotlin/collections/AbstractIterator.kotlin_metadata
        ./kotlin/collections/CollectionsKt.kotlin_metadata
        ./kotlin/collections/Grouping.kotlin_metadata
        ./kotlin/collections/GroupingKt.kotlin_metadata
        ./kotlin/collections/ArraysKt.kotlin_metadata
        ./kotlin/collections/UShortIterator.kotlin_metadata
        ./kotlin/collections/MutableCollectionsKt.kotlin_metadata
        ./kotlin/collections/AbstractCollection.kotlin_metadata
        ./kotlin/collections/EmptyIterator.kotlin_metadata
        ./kotlin/collections/ReversedListReadOnly.kotlin_metadata
        ./kotlin/collections/HashSet.kotlin_metadata
        ./kotlin/collections/MutableMapWithDefaultImpl.kotlin_metadata
        ./kotlin/collections/RandomAccess.kotlin_metadata
        ./kotlin/collections/MapWithDefault.kotlin_metadata
        ./kotlin/collections/EmptyMap.kotlin_metadata
        ./kotlin/collections/IterablesKt.kotlin_metadata
        ./kotlin/collections/MapsKt.kotlin_metadata
        ./kotlin/collections/LinkedHashMap.kotlin_metadata
        ./kotlin/collections/IndexingIterable.kotlin_metadata
        ./kotlin/collections/EmptyList.kotlin_metadata
        ./kotlin/jvm
        ./kotlin/jvm/Strictfp.kotlin_metadata
        ./kotlin/jvm/Transient.kotlin_metadata
        ./kotlin/jvm/Synchronized.kotlin_metadata
        ./kotlin/jvm/JvmName.kotlin_metadata
        ./kotlin/jvm/JvmStatic.kotlin_metadata
        ./kotlin/jvm/JvmOverloads.kotlin_metadata
        ./kotlin/jvm/JvmWildcard.kotlin_metadata
        ./kotlin/jvm/JvmSynthetic.kotlin_metadata
        ./kotlin/jvm/JvmPackageName.kotlin_metadata
        ./kotlin/jvm/JvmField.kotlin_metadata
        ./kotlin/jvm/JvmSuppressWildcards.kotlin_metadata
        ./kotlin/jvm/JvmMultifileClass.kotlin_metadata
        ./kotlin/jvm/Volatile.kotlin_metadata
        ./kotlin/UnsignedUtilsKt.kotlin_metadata
        ./kotlin/UShortKt.kotlin_metadata
        ./kotlin/text
        ./kotlin/text/Regex.kotlin_metadata
        ./kotlin/text/StringBuilderKt.kotlin_metadata
        ./kotlin/text/StringsKt.kotlin_metadata
        ./kotlin/text/DelimitedRangesSequence.kotlin_metadata
        ./kotlin/text/Appendable.kotlin_metadata
        ./kotlin/text/MatchGroupCollection.kotlin_metadata
        ./kotlin/text/MatchGroup.kotlin_metadata
        ./kotlin/text/UStringsKt.kotlin_metadata
        ./kotlin/text/RegexOption.kotlin_metadata
        ./kotlin/text/StringBuilder.kotlin_metadata
        ./kotlin/text/TextHKt.kotlin_metadata
        ./kotlin/text/IndentKt.kotlin_metadata
        ./kotlin/text/CharKt.kotlin_metadata
        ./kotlin/text/MatchResult.kotlin_metadata
        ./kotlin/text/RegexExtensionsKt.kotlin_metadata
        ./kotlin/text/CharacterCodingException.kotlin_metadata
        ./kotlin/text/Typography.kotlin_metadata
        ./kotlin/text/StringNumberConversionsKt.kotlin_metadata
        ./kotlin/text/MatchNamedGroupCollection.kotlin_metadata
        ./kotlin/random
        ./kotlin/random/RandomKt.kotlin_metadata
        ./kotlin/random/XorWowRandom.kotlin_metadata
        ./kotlin/random/URandomKt.kotlin_metadata
        ./kotlin/random/Random.kotlin_metadata
        ./kotlin/ULongArrayKt.kotlin_metadata
        ./kotlin/comparisons
        ./kotlin/comparisons/ReversedComparator.kotlin_metadata
        ./kotlin/comparisons/ReverseOrderComparator.kotlin_metadata
        ./kotlin/comparisons/ComparisonsKt.kotlin_metadata
        ./kotlin/comparisons/NaturalOrderComparator.kotlin_metadata
        ./kotlin/internal
        ./kotlin/internal/UProgressionUtilKt.kotlin_metadata
        ./kotlin/internal/DynamicExtension.kotlin_metadata
        ./kotlin/internal/LowPriorityInOverloadResolution.kotlin_metadata
        ./kotlin/internal/NoInfer.kotlin_metadata
        ./kotlin/internal/AccessibleLateinitPropertyLiteral.kotlin_metadata
        ./kotlin/internal/ContractsDsl.kotlin_metadata
        ./kotlin/internal/RequireKotlinVersionKind.kotlin_metadata
        ./kotlin/internal/InlineOnly.kotlin_metadata
        ./kotlin/internal/internal.kotlin_builtins
        ./kotlin/internal/HidesMembers.kotlin_metadata
        ./kotlin/internal/RequireKotlin.kotlin_metadata
        ./kotlin/internal/Exact.kotlin_metadata
        ./kotlin/internal/OnlyInputTypes.kotlin_metadata
        ./kotlin/IndexOutOfBoundsException.kotlin_metadata
        ./kotlin/ArithmeticException.kotlin_metadata
        ./kotlin/PreconditionsKt.kotlin_metadata
        ./kotlin/NoWhenBranchMatchedException.kotlin_metadata
        ./kotlin/NotImplementedError.kotlin_metadata
        ./kotlin/UByteArray.kotlin_metadata
        ./kotlin/BuilderInference.kotlin_metadata
        ./kotlin/UShortArrayKt.kotlin_metadata
        ./kotlin/Exception.kotlin_metadata
        ./kotlin/Lazy.kotlin_metadata
        ./kotlin/NullPointerException.kotlin_metadata
        ./kotlin/AssertionError.kotlin_metadata
        ./kotlin/UNINITIALIZED_VALUE.kotlin_metadata
        ./kotlin/reflect
        ./kotlin/reflect/KMutableProperty.kotlin_metadata
        ./kotlin/reflect/KProperty1.kotlin_metadata
        ./kotlin/reflect/KMutableProperty0.kotlin_metadata
        ./kotlin/reflect/KProperty.kotlin_metadata
        ./kotlin/reflect/reflect.kotlin_builtins
        ./kotlin/reflect/TypeOfKt.kotlin_metadata
        ./kotlin/reflect/KProperty0.kotlin_metadata
        ./kotlin/reflect/KMutableProperty2.kotlin_metadata
        ./kotlin/reflect/KCallable.kotlin_metadata
        ./kotlin/reflect/KClass.kotlin_metadata
        ./kotlin/reflect/KMutableProperty1.kotlin_metadata
        ./kotlin/reflect/KProperty2.kotlin_metadata
        ./kotlin/coroutines
        ./kotlin/coroutines/RestrictsSuspension.kotlin_metadata
        ./kotlin/coroutines/AbstractCoroutineContextElement.kotlin_metadata
        ./kotlin/coroutines/Continuation.kotlin_metadata
        ./kotlin/coroutines/experimental
        ./kotlin/coroutines/experimental/SequenceBuilderKt.kotlin_metadata
        ./kotlin/coroutines/experimental/RestrictsSuspension.kotlin_metadata
        ./kotlin/coroutines/experimental/AbstractCoroutineContextElement.kotlin_metadata
        ./kotlin/coroutines/experimental/Continuation.kotlin_metadata
        ./kotlin/coroutines/experimental/EmptyCoroutineContext.kotlin_metadata
        ./kotlin/coroutines/experimental/CombinedContext.kotlin_metadata
        ./kotlin/coroutines/experimental/CoroutineContext.kotlin_metadata
        ./kotlin/coroutines/experimental/intrinsics
        ./kotlin/coroutines/experimental/intrinsics/IntrinsicsKt.kotlin_metadata
        ./kotlin/coroutines/experimental/intrinsics/CoroutinesIntrinsicsExperimentalHKt.kotlin_metadata
        ./kotlin/coroutines/experimental/CoroutinesLibraryKt.kotlin_metadata
        ./kotlin/coroutines/experimental/SequenceBuilder.kotlin_metadata
        ./kotlin/coroutines/experimental/SequenceBuilderIterator.kotlin_metadata
        ./kotlin/coroutines/experimental/ContinuationInterceptor.kotlin_metadata
        ./kotlin/coroutines/experimental/SafeContinuation.kotlin_metadata
        ./kotlin/coroutines/EmptyCoroutineContext.kotlin_metadata
        ./kotlin/coroutines/CombinedContext.kotlin_metadata
        ./kotlin/coroutines/ContinuationKt.kotlin_metadata
        ./kotlin/coroutines/CoroutineContext.kotlin_metadata
        ./kotlin/coroutines/intrinsics
        ./kotlin/coroutines/intrinsics/CoroutineSingletons.kotlin_metadata
        ./kotlin/coroutines/intrinsics/IntrinsicsKt.kotlin_metadata
        ./kotlin/coroutines/intrinsics/CoroutinesIntrinsicsHKt.kotlin_metadata
        ./kotlin/coroutines/ContinuationInterceptor.kotlin_metadata
        ./kotlin/coroutines/SafeContinuation.kotlin_metadata
        ./kotlin/coroutines/coroutines.kotlin_builtins
        ./kotlin/ExperimentalMultiplatform.kotlin_metadata
        ./kotlin/ULong.kotlin_metadata
        ./kotlin/contracts
        ./kotlin/contracts/Returns.kotlin_metadata
        ./kotlin/contracts/ExperimentalContracts.kotlin_metadata
        ./kotlin/contracts/InvocationKind.kotlin_metadata
        ./kotlin/contracts/CallsInPlace.kotlin_metadata
        ./kotlin/contracts/ReturnsNotNull.kotlin_metadata
        ./kotlin/contracts/ContractBuilderKt.kotlin_metadata
        ./kotlin/contracts/SimpleEffect.kotlin_metadata
        ./kotlin/contracts/ConditionalEffect.kotlin_metadata
        ./kotlin/contracts/ContractBuilder.kotlin_metadata
        ./kotlin/contracts/Effect.kotlin_metadata
        ./kotlin/js
        ./kotlin/js/JsName.kotlin_metadata
        ./kotlin/LazyThreadSafetyMode.kotlin_metadata
        ./kotlin/RuntimeException.kotlin_metadata
        ./kotlin/kotlin.kotlin_builtins
        ./kotlin/LateinitKt.kotlin_metadata
        ./kotlin/UShortArray.kotlin_metadata
        ./kotlin/sequences
        ./kotlin/sequences/SubSequence.kotlin_metadata
        ./kotlin/sequences/TakeSequence.kotlin_metadata
        ./kotlin/sequences/SequenceBuilderKt.kotlin_metadata
        ./kotlin/sequences/MergingSequence.kotlin_metadata
        ./kotlin/sequences/TakeWhileSequence.kotlin_metadata
        ./kotlin/sequences/DistinctIterator.kotlin_metadata
        ./kotlin/sequences/TransformingSequence.kotlin_metadata
        ./kotlin/sequences/EmptySequence.kotlin_metadata
        ./kotlin/sequences/GeneratorSequence.kotlin_metadata
        ./kotlin/sequences/TransformingIndexedSequence.kotlin_metadata
        ./kotlin/sequences/DropWhileSequence.kotlin_metadata
        ./kotlin/sequences/IndexingSequence.kotlin_metadata
        ./kotlin/sequences/DistinctSequence.kotlin_metadata
        ./kotlin/sequences/FlatteningSequence.kotlin_metadata
        ./kotlin/sequences/SequenceBuilderIterator.kotlin_metadata
        ./kotlin/sequences/SequenceScope.kotlin_metadata
        ./kotlin/sequences/FilteringSequence.kotlin_metadata
        ./kotlin/sequences/Sequence.kotlin_metadata
        ./kotlin/sequences/DropSequence.kotlin_metadata
        ./kotlin/sequences/SequencesKt.kotlin_metadata
        ./kotlin/sequences/ConstrainedOnceSequence.kotlin_metadata
        ./kotlin/sequences/DropTakeSequence.kotlin_metadata
        ./kotlin/ExperimentalStdlibApi.kotlin_metadata
        ./kotlin/NumberFormatException.kotlin_metadata
        ./kotlin/UnsupportedOperationException.kotlin_metadata
        ./kotlin/HashCodeKt.kotlin_metadata
        ./kotlin/WasExperimental.kotlin_metadata
        ./kotlin/UByte.kotlin_metadata
        ./res
        ./res/mipmap-xhdpi-v4
        ./res/mipmap-xhdpi-v4/icon_foreground.png
        ./res/mipmap-xhdpi-v4/icon.png
        ./res/mipmap-xhdpi-v4/icon_background.png
        ./res/mipmap-anydpi-v26
        ./res/mipmap-anydpi-v26/icon.xml
        ./res/layout
        ./res/layout/notification_template_part_chronometer.xml
        ./res/layout/notification_template_media_custom.xml
        ./res/layout/notification_action.xml
        ./res/layout/notification_template_media.xml
        ./res/layout/notification_template_lines_media.xml
        ./res/layout/status_bar_ongoing_event_progress_bar.xml
        ./res/layout/notification_template_icon_group.xml
        ./res/layout/notification_template_big_media_narrow.xml
        ./res/layout/downloading_expansion.xml
        ./res/layout/notification_template_big_media.xml
        ./res/layout/notification_action_tombstone.xml
        ./res/layout/notification_template_big_media_narrow_custom.xml
        ./res/layout/notification_template_big_media_custom.xml
        ./res/layout/notification_template_part_time.xml
        ./res/layout/notification_media_action.xml
        ./res/layout/notification_media_cancel_action.xml
        ./res/drawable
        ./res/drawable/notification_tile_bg.xml
        ./res/drawable/notification_icon_background.xml
        ./res/drawable/notification_bg_low.xml
        ./res/drawable/notification_bg.xml
        ./res/drawable-mdpi-v4
        ./res/drawable-mdpi-v4/notification_bg_low_normal.9.png
        ./res/drawable-mdpi-v4/notification_bg_normal.9.png
        ./res/drawable-mdpi-v4/notification_bg_normal_pressed.9.png
        ./res/drawable-mdpi-v4/notify_panel_notification_icon_bg.png
        ./res/drawable-mdpi-v4/notification_bg_low_pressed.9.png
        ./res/layout-v16
        ./res/layout-v16/notification_template_custom_big.xml
        ./res/mipmap-xxhdpi-v4
        ./res/mipmap-xxhdpi-v4/icon_foreground.png
        ./res/mipmap-xxhdpi-v4/icon.png
        ./res/mipmap-xxhdpi-v4/icon_background.png
        ./res/mipmap-xxxhdpi-v4
        ./res/mipmap-xxxhdpi-v4/icon_foreground.png
        ./res/mipmap-xxxhdpi-v4/icon.png
        ./res/mipmap-xxxhdpi-v4/icon_background.png
        ./res/layout-v21
        ./res/layout-v21/notification_action.xml
        ./res/layout-v21/notification_template_custom_big.xml
        ./res/layout-v21/notification_template_icon_group.xml
        ./res/layout-v21/notification_action_tombstone.xml
        ./res/mipmap-hdpi-v4
        ./res/mipmap-hdpi-v4/icon_foreground.png
        ./res/mipmap-hdpi-v4/icon.png
        ./res/mipmap-hdpi-v4/icon_background.png
        ./res/drawable-v21
        ./res/drawable-v21/notification_action_background.xml
        ./res/mipmap
        ./res/mipmap/icon_foreground.png
        ./res/mipmap/icon.png
        ./res/mipmap/icon_background.png
        ./res/drawable-hdpi-v4
        ./res/drawable-hdpi-v4/notification_bg_low_normal.9.png
        ./res/drawable-hdpi-v4/notification_bg_normal.9.png
        ./res/drawable-hdpi-v4/notification_bg_normal_pressed.9.png
        ./res/drawable-hdpi-v4/notify_panel_notification_icon_bg.png
        ./res/drawable-hdpi-v4/notification_bg_low_pressed.9.png
        ./res/mipmap-mdpi-v4
        ./res/mipmap-mdpi-v4/icon_foreground.png
        ./res/mipmap-mdpi-v4/icon.png
        ./res/mipmap-mdpi-v4/icon_background.png
        ./res/drawable-xhdpi-v4
        ./res/drawable-xhdpi-v4/notification_bg_low_normal.9.png
        ./res/drawable-xhdpi-v4/notification_bg_normal.9.png
        ./res/drawable-xhdpi-v4/notification_bg_normal_pressed.9.png
        ./res/drawable-xhdpi-v4/notify_panel_notification_icon_bg.png
        ./res/drawable-xhdpi-v4/notification_bg_low_pressed.9.png
        ./classes.dex
        ./META-INF
        ./META-INF/MANIFEST.MF
        ./META-INF/ANDROIDD.RSA
        ./META-INF/ANDROIDD.SF
        ./lib
        ./lib/arm64-v8a
        ./lib/arm64-v8a/libgodot_android.so
        ./lib/arm64-v8a/libc++_shared.so
        ./lib/armeabi-v7a
        ./lib/armeabi-v7a/libgodot_android.so
        ./lib/armeabi-v7a/libc++_shared.so
        ./assets
        ./assets/project.binary
        ./assets/_cl_
        ./assets/icon.png.import
        ./assets/scripts
        ./assets/scripts/Dead.gdc
        ./assets/scripts/collector.gdc
        ./assets/scripts/Level.gd.remap
        ./assets/scripts/dump.gdc
        ./assets/scripts/collector.gd.remap
        ./assets/scripts/Window.gd.remap
        ./assets/scripts/global.gdc
        ./assets/scripts/global.gd.remap
        ./assets/scripts/cart.gdc
        ./assets/scripts/Window.gdc
        ./assets/scripts/cart.gd.remap
        ./assets/scripts/Dead.gd.remap
        ./assets/scripts/Level.gdc
        ./assets/scripts/dump.gd.remap
        ./assets/.import
        ./assets/.import/house-window-bg.png-74fc7d4cc4b6ea74b2b4b4abbc256f2c.stex
        ./assets/.import/house-window-top.png-b447a08db369aee34be8995e2bb5344b.stex
        ./assets/.import/churchbell.wav-e54174026516443fd546530a48df5b3d.sample
        ./assets/.import/dump.png-565eb851d6833be7ecfcdc2d21b21386.stex
        ./assets/.import/house-ground-floor.png-29527bade4e73106d2548a7ee71d8030.stex
        ./assets/.import/bringout.wav-f4c8f08ce60ffb308bf8f12213c87e0d.sample
        ./assets/.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex
        ./assets/.import/star.png-db40ec76fb3fd808480ce0481255e27b.stex
        ./assets/.import/triangle-dude-spritesheet.png-a7a33e15689a0a26a594c760755b4db4.stex
        ./assets/.import/bg.png-23a59c2e9cba2223a50fa3fe41b70b25.stex
        ./assets/.import/bringout2.wav-fb663ac2e386cdf4bb8119ee45f0a145.sample
        ./assets/.import/gaslamp_funworks.ogg-ef6ece76ae0b6538a5d2eab31c14866d.oggstr
        ./assets/.import/house-roof.png-59cde44fe40ce7a395f5b89fb2cf1115.stex
        ./assets/.import/wheel.png-842e45fbc3d7e57d167cfb4b1fa152b4.stex
        ./assets/.import/alpha-2x2.png-fd2c8b3a568534be2c0beaf4c88f6b84.stex
        ./assets/.import/road.png-72005ad96a94b3869b023c4f4a0b0b7d.stex
        ./assets/.import/filling.png-d01074696edf202528a79348df6e0010.stex
        ./assets/.import/cart.png-5acbb80ef3e75e7c02b4d1a258771f47.stex
        ./assets/.import/house-middle-floors.png-e9e41c2761e192668d99b5f795e6f59f.stex
        ./assets/.import/ded.png-9b16a5eaac971d13ca7e3ee24a9928fb.stex
        ./assets/scenes
        ./assets/scenes/Level.tscn
        ./assets/scenes/Window.tscn
        ./assets/scenes/Background.tscn
        ./assets/scenes/collector.tscn
        ./assets/scenes/Dead.tscn
        ./assets/scenes/House.tscn
        ./assets/scenes/cart.tscn
        ./assets/scenes/House.gdc
        ./assets/scenes/dump.tscn
        ./assets/scenes/Ground.tscn
        ./assets/scenes/HouseTall.tscn
        ./assets/scenes/House.gd.remap
        ./assets/assets
        ./assets/assets/bg.png.import
        ./assets/assets/gaslamp_funworks.ogg.import
        ./assets/assets/house-roof.png.import
        ./assets/assets/bringout.wav.import
        ./assets/assets/cart
        ./assets/assets/cart/filling.png.import
        ./assets/assets/cart/cart.png.import
        ./assets/assets/cart/wheel.png.import
        ./assets/assets/house-window-top.png.import
        ./assets/assets/bringout2.wav.import
        ./assets/assets/house-middle-floors.png.import
        ./assets/assets/triangle-dude
        ./assets/assets/triangle-dude/triangle-dude-spritesheet.png.import
        ./assets/assets/triangle-dude/stick.tres
        ./assets/assets/triangle-dude/bot-arm.tres
        ./assets/assets/triangle-dude/effect.tres
        ./assets/assets/triangle-dude/triangle.tres
        ./assets/assets/triangle-dude/cape-up.tres
        ./assets/assets/triangle-dude/face.tres
        ./assets/assets/triangle-dude/cape.tres
        ./assets/assets/triangle-dude/up-arm.tres
        ./assets/assets/churchbell.wav.import
        ./assets/assets/alpha-2x2.png.import
        ./assets/assets/road.png.import
        ./assets/assets/star.png.import
        ./assets/assets/dump.png
        ./assets/assets/ded
        ./assets/assets/ded/head.tres
        ./assets/assets/ded/shirt.tres
        ./assets/assets/ded/arm-bot.tres
        ./assets/assets/ded/ded.png.import
        ./assets/assets/ded/arm-up.tres
        ./assets/assets/ded/leg.tres
        ./assets/assets/house-window-bg.png.import
        ./assets/assets/FiraSans-Regular.ttf
        ./assets/assets/dump.png.import
        ./assets/assets/house-ground-floor.png.import

So yeah it doesn't use a PCK, the project files are exported to the assets folder.

Scripts are compiled by default (.gdc) and could likely be encrypted if configured. Scenes are in plain text.

m4gr3d commented 4 years ago

As @akien-mga mentioned, the project files are exported directly to the assets folder on Android.

However the engine supports reading project data from an exported .pck or .zip file in the assets folder (validated through testing), so we could get to the desired outcome through a few steps:

  1. Change the default Android export behavior so that a .pck or .zip file of the project is pushed to the assets folder instead of the project files.
    • This should be fairly simple as the plumbing is already there and just need to be hooked up properly.
    • @akien-mga @Calinou Is there a breakdown for the use-cases between exporting to .zip vs exporting to .pck file? Is pck a custom Godot format?
  2. Update the default loading behavior so that the engine also looks for the exported .pck or .zip file in the assets folder.
  3. Add the option (and logic) to encrypt the exported .pck or .zip file and decrypt it at runtime to access the data. I believe #38308 may be providing that capability.

@dariuspranskus Could you open a godot-proposals for the described process. Once the proposal is opened, could you take a stab at the first step.

One thing to make clear though is that this would make it harder for the game resources to be accessed, not impossible. Given the need to decrypt the data at runtime, the encryption key would need to be available to the apk and thus accessible to anyone with the ability to introspect an apk. In addition, since this project is open-source, anyone can see the logic used for encryption/decryption, and the location of the data (and/or keys) by looking at the engine source code. As long as this is clear and understood, then we should proceed!

@akien-mga slightly unrelated, do we know if the apk expansion feature is being used at all and/or works? I noticed it writes a pack file with .obb extension, but the file is not packaged with the generated apk so it's not clear how the apk would ever access it.

Calinou commented 4 years ago

@m4gr3d PCK is a custom, Godot-specific format. Unlike ZIP, it's not compressed but it supports fast random seeking. You can use the PCKPacker class to create them programmatically.

m4gr3d commented 4 years ago

@m4gr3d PCK is a custom, Godot-specific format. Unlike ZIP, it's not compressed but it supports fast random seeking. You can use the PCKPacker class to create them programmatically.

Thanks! So we should probably use that as the default for export to the apk assets folder. Do you know if there are available tools to inspect the contents of .pck file outside of the Godot codebase? If not, then just implementing #1 and #2 may resolve @dariuspranskus's concern.

Calinou commented 4 years ago

@m4gr3d There are a few tools for that, such as https://github.com/hhyyrylainen/GodotPckTool. I don't consider this to be much of a problem, as you'll never find a way to have unencrypted data that's not easily extractible. (There are tools that can recognize data structures even in custom, undocumented formats.)

Also, the APK expansion feature appears to be broken: https://github.com/godotengine/godot/issues/28214

bruvzg commented 4 years ago

I noticed it writes a pack file with .obb extension, but the file is not packaged with the generated apk so it's not clear how the apk would ever access it.

This is correct behavior, APK size is limited to 100MB, AAB to 150MB (and it's not supported yet), OBBs are additional files if you need bigger size (2GB each), Play Store should download and place it to the correct location automatically.

bruvzg commented 4 years ago

Also, the APK expansion feature appears to be broken: #28214

As mentioned in this issue, OBBs do require "READ_EXTERNAL_STORAGE" permission (on some implementations of Android 6+ and all older versions), so it's probably not broken.

m4gr3d commented 4 years ago

@Calinou reading #28214, seems the issue may be user error. Also probably worth closing that bug since the user resolved the issue albeit through a different path.

@bruvzg Thanks for the clarification.

dariuspranskus commented 4 years ago

@m4gr3d Created godot proposals #946 #947 and #948. I am happy to take a stab on #946. Do you have any materials for me to read to get up and running with that faster? My background is not in C++ development, but I know C# and Javascript pretty well. Thanks

m4gr3d commented 4 years ago

@dariuspranskus Most of the logic you need to tie together for proposal #946 should be in the export.cpp source file.

I'd recommend taking a look at the Engine development section, and particularly the Introduction to Godot development and the IDE configuration section to get started.

Once you're set, I'd take a look at the Compiling section.

You'll probably have to validate your changes by compiling the editor, exporting an Android apk, and validate the apk's assets directory contains the generated .pck or .zip file.

Feel free to ask here or on irc if you have any questions.

dariuspranskus commented 4 years ago

@m4gr3d Thanks. will take a look.

rieniter commented 4 years ago

Scene files and all folder name are still in 100% original plain text when you exported to apk, this sucked, anyone know you using godot can clone your project easy than ever

dariuspranskus commented 4 years ago

@m4gr3d, @Calinou, @akien-mga Hello. Could someone please help me with the following:

I have the following development environment set up:

I am able to debug the core editor app - set breakpoints, stop at them, see variables, etc.

But I am struggling to debug the code in platform/android, can't set the breakpoints there, it looks like it is a separate module or something. How do I debug the export code?

Thanks

m4gr3d commented 4 years ago

@dariuspranskus Most of the code in platform/android is compiled and linked to the generated Android apk and not used by the editor, so you shouldn't need to modify it for #946. The platform/android/export/export.cpp which I've referenced above should be accessible via the debugger as it's part of the editor code.

dariuspranskus commented 4 years ago

@m4gr3 Thanks for the response. Not sure what might be a reason, but I am actually trying to set the breakpoint in platform/android/export/export.cpp, but when I run the code, the breakpoint becomes disabled: image if I set the breakpoint in editor/editor_export.cpp, then it works: image I also tried with the Qt Creator and got the same result. Please advice. Thank you

m4gr3d commented 4 years ago

@dariuspranskus just to confirm, you're generating the build using target=debug scons parameter instead of release or release_debug?

phil-hudson commented 1 year ago

@m4gr3d or anyone else - if you have any pointers about implementation, please let me know.

Looking to get this done as I need to encrypt the contents of my app for shipping the .aab to Play Console.

Thanks