跳至内容
Blog

格拉茨编码挑战赛:获胜者是

· 由 grommunio
格拉茨编码挑战赛:获胜者是

在格拉茨 Linux 日上,grommunio 主办了一场备受赞誉的编码挑战赛。在 23 名参赛者中,有 9 人取得了成功。通过抽签选出的大奖得主已在 grommunio 办事处领取了奖品。

编码挑战 - 获胜者](/img/posts/26-05-15_Coding-Challenge_winner.wep)

来自 grommunio 的 Fabian Ortner 为幸运儿 Andreas 送上了价值近 700 欧元的全新索尼 PlayStation 5。

听起来其实很简单,不是吗?

对于这项任务,您需要在 \src\main.cpp 文件中编写 C/C++ 代码,以解决本自述文件末尾的 “编码挑战”。使用的是带有 gcc/g++ 15.2 的 MinGW64,它会自动设置在本地目录中,可以使用以下命令 ”

对许多非技术人员来说听起来难以理解的东西,对程序员来说似乎并不困难—至少乍一看是这样。原则上,grommunio 提出的四项任务肯定是可以解决的,于是 23 名 Linux 专家在四月的一个星期六在格拉茨接受了挑战。

时间压力下的编程

许多参赛者都在努力争取在规定时间内使用自己编写的代码找到正确的解决方案。事实证明,最初预计的 20 分钟过于乐观;即使在最后分配的 40 分钟内,也只有 9 名参赛者能够找到正确的解决方案。

因此,格拉茨的两台特别准备的 Windows 机器在周六几乎一直被占用着,用于挑战本身的时间超过了 7 个小时。

编码挑战赛设置

grommunio 的员工在电脑上创建了新的用户账户,将 VSCode 设置为编辑器,并通过 Windows cmd 脚本自动执行各种命令,以加快编译和提交过程。

编码挑战 - 代码](/img/posts/26-05-15_Coding-Challenge_code.webp)

使用 grommunio 提供的工具成功完成挑战的参赛者。

“我们建立了一个小型 HTTP 端点,结合挑战赛计算机上的 shell 脚本,可以根据每位参赛者的电子邮件地址为其生成个性化输入,然后就他们尝试解决问题的情况提供反馈,” grommunio 的 Fabian Ortner(上图)解释说。 *“然后,一个自述文件对编程任务需要完成的工作提供了更详细的说明,因此,我们创建了一个相当简单的自动化流程,使参与尽可能简单。

但 “尽可能简单 “的说法并没有持续多久。在挑战赛中,参赛者必须通过编写一个小的转换脚本来修复出现故障的邮件服务器。在 README 中,要解决的四项任务中的第一项任务是:

*“每一行似乎都包含 8 个字符的整数倍,因此让我们尝试将这些字符解释为单个字节。例如

*0100010001010001001010 0x44 0x51 0x4A 0100010001000001001100 => 0x44 0x50 0x4C 010000100101000101001100 0x42 0x51 0x4C *

*我们知道,旧的邮件服务器在导出邮件后使用了一种非常简单的加密方法: *

  • 取每一行文本,即**每个字节****
  • *对于每一行,用密钥 (grommunio\ )逐个字符进行XOR 加密
  • *如果一行比密钥长,只需再次使用密钥,从第一个字符开始。

更多的要求和任务接踵而至,着实让他们头大。只有少数参与者能够提出正确的解决方案。

不过,即使是那些没有成功的人也有值得期待的事情:最后,所有参与者将通过随机抽奖决定谁将获得承诺的 PlayStation。获胜者 Andreas 被邀请到维也纳 DC 大厦 30 层的 grommunio 总部领取。

解决办法是什么?我们不会在这里公布,但您可以在本帖下方找到包含完整问题说明的 README 文件。如果没有 grommunio 为格拉茨 Linux 日搭建的服务器,那就需要一点想象力了…

了解有关 grommunio 在格拉茨 Linux 日上的更多信息,请参阅此[文章]。


编码挑战说明

本挑战要求您在 .\src\main.cpp 内编写一些 C/C++ 代码,以解决本自述末尾的挑战。它使用 MinGW64 和 gcc/g++ 15.2,gcc/g++ 15.2 会自动设置在本地目录中,可以使用以下命令。

其中包含的脚本有四个***重要的命令:

1.注册您的电子邮件地址并启动 20 分钟计时器:

.\glt.cmd start.

2.只需构建您的代码:

.\glt.cmd build.

3.编译并运行代码,将输出结果打印到终端:

.\glt.cmd build_and_run.

4.编译、运行并提交解决方案:

.\glt.cmd submit.

用于构建解决方案的命令默认未启用任何优化:

g++.exe -static -O0 -g -std=c++17 src\main.cpp -o build/app.exe.

挑战

要开始挑战,user.txt文件中输入您的电子邮件地址,然后使用 start 命令获取您的输入。我们仅在您中奖时使用它与您联系。您只需更改代码中的 result 变量,然后运行提交命令检查是否正确。

哇邮件迁移过程中发生了什么?在新邮件服务器的设置过程中,您的一封 E-Mail 不知何故损坏了。它似乎只包含分成几行的二进制符号(您的输入)。每行似乎有 8 个符号的整数倍,因此我们试着将它们解释为单个字节。例如

0100010001010001001010 0x44 0x51 0x4A 0100010001000001001100 => 0x44 0x50 0x4C 010000100101000101001100 0x42 0x51 0x4C

我们知道,旧的邮件服务器在导出电子邮件后使用了非常简单的加密方法:

  • 将每行文本,即每个字节
  • 将每一行与按字符顺序排列的 grommunio 密钥进行 XOR 运算
  • 如果一行比密钥长,只需从第一个字符开始重复使用密钥。

0x44 ^ g = 0x23 0x51 ^ r = 0x23 0x4A ^ o = 0x25 0x44 ^ g = 0x23 0x50 ^ r = 0x22 0x4C ^ o = 0x23 0x42 ^ g = 0x25 0x51 ^ r = 0x23 0x4C ^ o = 0x23

这看起来已经比较有希望了,但仍有许多乱码…

早期的旧邮件服务器已经出现过单个字符值偏移的问题,偏移量取决于两个方面:

  • 电子邮件地址的水平校验和
  • 字符在一行中的索引及其所在的行号

当时,服务器通过简单地将电子邮件地址的所有字节值相加来计算水平校验和。

max.mustermann@grommunio.com => (m=109) + (a=97) + (x=120) + … = 2888

然后,每个字符的正偏移量都是通过将校验和与该字符在行中的位置相乘计算得出的。因此,为了纠正这一错误,我们必须从每个字节中减去偏移值。此外,这些偏移值在每一行后左移一个字符。

0x23 - (2888 % 1) = ’#’ 0x23 - (2888 % 2) = ’#’ 0x25 - (2888 % 3) = ’#’ 0x23 - (2888 % 2) = ’#’ 0x22 - (2888 % 3) = ’ ’ 0x25 - (2888 % 1) = ’#’ 0x23 - (2888 % 3) = ’#’ 0x23 - (2888 % 1) = ’#’ 0x25 - (2888 % 2) = ’#’

现在,这看起来是一条正确的信息!但是,为了确保算法的正确性,我们需要计算偏移值乘以每个关键字的字符值的元素乘积,并对信息中的每个 ”#“字符求和。(\n\r`应舍弃)

(g=103)\*0 + (r=114)\*0 + (o=111)\*2
  • (g=103)*0 + (o=111)*0
  • (g=103)*2 + (r=114)*0 + (o=111)*0 = 428

你需要把这个元素相乘之和写入结果变量来完成编码挑战!

祝你好运!