保护QML源代码免受抄袭

时间:2016-01-15 15:42:58

标签: c++ qt qml qtquick2 type-resolution

目标是提出一种保护您的QML代码免受抄袭的方法。这是一个问题,因为在这方面,QML的设计和实施方式似乎莫名其妙地不受保护。唯一受到保护的QML类型是完全用C ++实现的类型。

  • Qt资源文件不支持任何程度的保护
  • 即使您压缩资源文件,从中提取数据对于经验适中的人来说仍然相当微不足道
  • 存储在文件系统上的QML文件几乎可以用于
  • 同样适用于任何远程QML文件,除了添加对互联网连接的依赖外,还可以轻松嗅探网络访问并通过其网址获取QML文件
  • QML似乎没有提供任何公共API以允许用户对QML类型解析进行足够的控制以保护其代码

总而言之,它几乎看起来Qt故意吝啬QML代码保护,一个明显的候选理由是迫使人们购买具有QML编译器的疯狂表达的商业许可证。

因此缺乏保护QML源的任何库存方法,目前我想到的唯一解决方案是控制如何解决QML类型。有几种方法可以将类型注册到QML:

  • 在应用程序可执行文件中注册
  • 在插件中注册
  • 通过QML模块注册

但是,我需要的是手动解析QML类型,就像你可以创建一个输入URL字符串并输出图像的自定义QQuickImageProvider一样,我需要QML引擎来请求类型为的字符串我的自定义组件提供程序,它输出一个ready for object instantiation组件。

如果使用任何自定义实例化机制,这将很容易,但我需要这些类型在常规QML源中可用。理想情况下,在查看可用的导入路径或甚至是内部注册的类型之前,这应该是用于解析类型的第一种机制。

或者,如果有一种方法可以完全用C ++定义QML模块,没有任何外部QML文件,没有qmldir文件等等,那将同样有用。

作为最后的手段,并且从理想情况下来说,我还倾向于向运行时注册QML(而不是C ++)类型,这也可能有用,但我更愿意完全控制解析过程。

QML插件没有这个技巧,因为它注册了C ++类型,我想注册QML类型,即从字符串源创建的QQmlComponent并相互引用。

4 个答案:

答案 0 :(得分:3)

(理想)解决方案:预编译

Qt Quick Compiler是Qt Quick应用程序的开发附件,允许您将QML源代码编译为最终二进制文件。 As it's description says,它有助于防止抄袭,它还可以增强您的应用程序启动时间并提供其他好处。

这就像保护您的QML源代码一样接近,即使它还没有完全优化

更新

从Qt 5.11开始,解决方案已经到位并且变得更快。

更新(2)

Seems the QML compiler is already opensource from 5.11我无法讲述工具,但Lars Knoll在博客文章中解释了这一点。

答案 1 :(得分:1)

选项A)使用qtquick编译器

选项B)使用加密资源:

  1. 将资源编译为单独的文件: rcc -binary your_resource.qrc -o extresources.rcc

  2. 将extresources.rcc加密为extresources.rcc.cr(例如使用gnupg)

  3. 创建一个新资源文件APP.rcc,仅使用extresources.rcc.cr文件

  4. 启动时,加载":/ extresources.rcc.cr"并将它们解密到缓冲区(你需要一个像Libgcrypt这样的加密库...隐藏反编译器和调试器的私钥等)

  5. Q_CLEANUP_RESOURCE(APP); (可选,清除APP.rcc以节省内存)

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

  7. //现在,你有可用的解密资源......例如

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

    真正的实施并非无足轻重,但效果非常好......

答案 2 :(得分:1)

实际上,您可以在C ++中注册QML类型。函数QUrl具有重叠形式,该形式接受qmlRegisterType(QUrl("qrc:/YourQMLModule.qml"), "YourModule", 1, 0, "YourQMLModule"); 表示qrc中的qml文件:

 BUREAU DES DOCKS ET TRANSPORTS         POSTE M.G.           CN 

看起来就像您注册了普通的C ++类。 Qt的官方资料中经常使用它,尽管文档中没有。

答案 3 :(得分:0)

经过一番挖掘后,我找到了两个可能值得追求的方向:

  • 使用自定义QQmlAbstractUrlInterceptor作为QML引擎,解析QML类型并重新调整QUrl,在" protected"类型,拦截器可以添加自定义方案。使用自定义QNetworkAccessManager拦截该URL,调用未受保护类型的默认实现,对于受保护类型,对数据进行解密并将其返回QNetworkReply

  • 另一个更简单但不太灵活的解决方案只涉及前一个解决方案的第二部分,并且qmlRegisterType(const QUrl &url, ...)函数要公开为QML类型,避免使用拦截器。

我会在调查这两个时发布更新。请注意,这也不是100%安全,因为使用解密代码本身的网络回复将至少暂时保留在RAM中,因此如果有足够的能力,仍然可以获得代码,但是它并不像访问代码那样微不足道它直接来自应用程序二进制文件更进一步的可能方向是使用不包含解密数据的自定义QNetworkReply,但重载QIODevice部分以充当解密的加密数据的访问者它在阅读时一路走来。