每张现金卡都有一个 4 位的识别码(PIN)。现金卡交易能否实现,取决于卡号与 PIN 是否匹配。这种匹配由 HSM(硬件安全模块)进行检查。该模块接收三个参数:卡号 $x$、PIN $p$ 以及一个转换数组 $a$(包含 16 个 0 到 9 之间的数字,索引从 0 到 15)。HSM 的处理方式如下:
- 对现金卡号 $x$ 进行加密,得到一个十六进制数 $y$;
- 保留 $y$ 的前四位十六进制数字,舍弃其余部分;
- 将保留的十六进制数字转换为十进制系统(即数字 $h$ 转换为 $a[h]$,其中 $h=\texttt{A}$ 对应 10,$h=\texttt{B}$ 对应 11,$h=\texttt{C}$ 对应 12,$h=\texttt{D}$ 对应 13,$h=\texttt{E}$ 对应 14,$h=\texttt{F}$ 对应 15);
- 得到的 4 位十进制数必须与提供的 PIN 完全一致。
标准转换数组为 $a=(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5)$。例如,假设卡号为 $x = \texttt{4556 2385 7753 2239}$,加密后得到的十六进制数为 $y = \texttt{3F7C 2201 00CA 8AB3}$。为了获得 4 位 PIN,我们取前四位十六进制数字 (3F7C),并使用标准转换数组进行编码。结果得到的 PIN 为 $p=\texttt{3572}$。不幸的是,不诚实的银行员工或黑客可能会获取 HSM 的访问权限,并通过操纵转换数组来尝试猜测 PIN。
任务
编写一个程序,通过向 HSM 发送查询来尝试猜测 PIN。最多可以进行 30 次查询。
交互
你的程序应仅通过 HSM 提供的函数(Pascal 中的 hsm.pas,C/C++ 中的 hsm.h)与“外部世界”进行通信。这意味着它不能打开任何文件或使用标准输入/输出。
程序启动后,每次都需要猜测一个与 HSM 中已知卡号相匹配的 PIN(使用标准转换数组)。HSM 提供以下函数:sprawdz(波兰语意为“检查”)和 wynik(波兰语意为“结果”)。它们在 Pascal 中的声明如下:
function sprawdz (pin:array of Longint, a:array of Longint):Boolean;
procedure wynik (pin:array of Longint);
在 C/C++ 中的声明如下:
int sprawdz (int pin[], int a[]);
void wynik (int pin[]);
函数 sprawdz 的参数为:待调查的 PIN(以 4 个元素的数字数组形式)和转换数组(包含 16 个元素)。其返回值为布尔值,用于确定在给定转换数组的情况下,提供的 PIN 是否与卡号匹配。你的程序最多应调用 sprawdz 函数 30 次,并调用 wynik 函数恰好一次。调用 wynik 过程将终止程序。其参数应为在标准转换数组下与卡号匹配的 PIN。
为了测试你的解决方案,你应该编写自己的 hsm。然而,它不是解决方案的一部分,不应与程序一起提交。
样例
输入格式 1
(无)
输出格式 1
sprawdz ((1,1,1,1), (0,0,1,1,0,1,0,1,0,0,0,0,1,1,0,1)) = true sprawdz ((1,1,0,0), (0,0,0,1,0,1,0,0,0,0,0,0,0,1,0,1)) = true sprawdz ((1,1,0,0), (0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0)) = false sprawdz ((1,0,0,0), (0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0)) = true sprawdz ((0,0,1,0), (0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0)) = false sprawdz ((0,0,0,1), (0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0)) = true wynik ((3,5,7,2))
说明
程序与 HSM 之间可能的交互如下。