Protecting QML Source Code from Plagiarism

The goal is to come up with a way to protect your QML code from plagiarism. This is a problem, since the QML path has been designed and implemented, it seems inexplicably insecure in this regard. The only types of QML that are somewhat protected are those that are fully implemented in C ++.

  • Qt resource files do not support any degree of protection.
  • even if you are compressing a resource file, extracting data from it is still pretty trivial for anyone with moderate experience
  • QML files stored in the file system practically exist for acceptance
  • the same applies to any remote QML files, in addition to adding an Internet connection dependency, it’s easy to sniff network access and receive QML files through their URLs.
  • QML does not seem to provide any public API to allow users enough control over the QML type to protect their code.

All in all, it seems that Qt intentionally refuses to protect QML code, one obvious candidate reason is to get people to buy an insanely expressive commercial license that has a QML compiler.

Thus, there is no stock method to protect QML sources, the only solution that comes to my mind right now is to control how QML types are resolved. There are several ways to register types in QML:

  • register in the executable application
  • register in the plugin
  • registered through the QML module

However, I need to manually QQuickImageProvider QML types, just as you can create a custom QQuickImageProvider that enters a URL string and displays an image, I need a QML mechanism to request a string with a type in my regular component provider, which displays the readiness component for creating an object .

It would be easy if some kind of custom instance creation mechanism was used, but I need those types that can be used in regular QML sources. Ideally, this should be the first mechanism used to resolve the type before looking for available import paths or even internal registered types.

Alternatively, it would also be useful if there was a way to fully define a QML module completely in C ++ without any external QML files without a qmldir file, etc.

As a last resort, and ideally I do not agree, I would also agree to register QML types (not C ++) for the runtime, this can also be useful, but I would prefer to have full control over the resolution process.

The QML plugin does not do the trick, since it registers C ++ types, and I want to register QML types, i.e. QQmlComponent , created from string sources and referencing each other.

+5
source share
3 answers

Ideal solution: pre-assemble it

Quick Compiler Qt is an add-on for Qt Quick applications that allows you to compile QML source code into a final binary. As stated in the description , this will help prevent plagiarism, as well as increase the launch time of your application and provide other benefits.

It was a closed source, but you can get an alternative open source version at https://github.com/qmlc/qmlc or you can wait until Qt 5.8 where it becomes opensource .

It is so close that you can protect your QML source code even if it is not yet fully optimized.

+1
source

After some digging, I found two directions that could be pursued:

  • using a custom QQmlAbstractUrlInterceptor for the QML engine, which allows QML types and returns QUrl , in the case of "protected" types, the interceptor can add a custom scheme in advance. Using a custom QNetworkAccessManager to intercept this URL causes a default implementation for unprotected types, and for protected types it decrypts the data and returns it to QNetworkReply .

  • another, simpler but less flexible solution includes only the second part of the previous solution, and the qmlRegisterType(const QUrl &url, ...) function qmlRegisterType(const QUrl &url, ...) is like QML types, avoiding the use of an interceptor.

I will post updates when I research these two. Please note that this is not 100% safe, since the response of the network with the decrypted code itself will at least temporarily remain in RAM, therefore, given sufficient competence, it will still be possible to obtain the code, however this is not as trivial as accepting it directly from a binary application. A possible direction would be to call a custom QNetworkReply , which does not contain decrypted data, but overloads the QIODevice part to act as an accessor to encrypted data that decrypts it along the way when reading it.

0
source

Option A) use the qtquick compiler

Option B) use encrypted resources:

  • compile resources into a separate file: rcc -binary your_resource.qrc -o extresources.rcc

  • encrypt extresources.rcc for extresources.rcc.cr (e.g. with gnupg)

  • create a new resource file APP.rcc, only with extresources.rcc.cr

  • at startup, load ": /extresources.rcc.cr" and decrypt them into the buffer (you need a cryptographic library such as Libgcrypt ... hide the private key for decompilers and debuggers, etc.)

  • Q_CLEANUP_RESOURCE (APP); (optional, clear APP.rcc to save memory)

  • Resource :: registerResource ((unsigned char *) myBuffer.constData ()))

// now you have decrypted resources available ... for example

engine.load (QUrl ("QRC: /main.qml"))

The actual implementation is not trivial, but it works very well ...

0
source

Source: https://habr.com/ru/post/1240707/


All Articles