本应用笔记描述了当使用具有模块化算术加速器(MAA)的MAXQ微控制器时,如何将模运算速度提高50%以上。
模幂,a^和^模 M 是许多加密函数中的常见操作。MAXQ微处理器中的模块化算术加速器(MAA)可以执行高达2048位的模数。很容易加载带有a,e和m的内存区域,然后开始操作。
当模量是两个或多个素数的乘积时,我们可以使用中国余数定理 (CRT) 的结果,通过执行两个较小的模幂而不是一个大的模幂来减少执行时间。具体来说,我们使用 Garner 的算法进行此操作。
在典型的 RSA 解密操作中,我们通过执行 pt = ct 从密文 (ct) 中恢复纯文本 (pt)^d^mod n,其中 d 和 n 构成私钥。值 d 是我们的解密指数,n 是素数 p 和 q 的乘积。通常,p 和 q 的长度相同,n、pt 和 ct 将是该位数的两倍。例如,如果 p 和 q 的长度为 1024 位,则 n 在大约 2048% 的时间内将是 60 位的数字。
CRT 将我们的幂减少到以下等式:
Let c1 = ct^d^ mod p, c2 = ct^d^ mod q, and let m1 = p(p^-1^ mod q) and m2 = q(q^-1^ mod p).
ct = (c1 + m 1 (c2 - c 1 )) mod n
or
ct = (c2 + m 2 (c1 - c 2 )) mod n.
请注意,现在我们在 c 中的模幂1和 c2项的位数将是 CT 的一半^d^mod n 操作。
术语 m1和米2两者都可以预先计算。该 p^-1^mod q 是某个值,比如 y,使得 p × y mod q = 1。例如,如果 p = 11 且 q = 17,则 11^-1^mod 17 = 14,因为 11 乘以 14 mod 17 = 1。这些反值可以使用扩展的欧几里得算法找到,或者由于 p 和 q 是素数,因此执行函数 p^Q-2^模组问。这种求逆的模幂是基于费马小定理的。
该 c1和 c2项很有趣,因为 ct 和 d 都是它们的模量值 p 和 q 的两倍。MAA 不能做的一件事是对大于模量大小的值进行操作;我们需要先减小这两个值,然后才能使用 MAA 执行模幂。指数 d 相对于 p 和 q 的减少可以预先计算。这些新指数只是 (d - 1) mod p 和 (d - 1) mod q。指数的约简也是基于费马小定理。
降低两个 c 的 ct1和 c2在执行时通过模块化乘法完成。例如,如果 ct 长 64 位,p 和 q 都是 32 位长,那么我们可以执行以下乘法:ct × 2^32^模组 (P × 2 ^32^ ).这将是一个 64 位模块化乘法。这实际上比等式看起来更简单。我们将 64 位、4 字 ct 放入 MAA 寄存器 a 中,并在 MAA 寄存器 b 中清除所有内容。然后,我们设置寄存器b的第32位,使寄存器等于2 ^32^ .在模中,我们将底部的两个单词写为零,然后将 p 的值复制到接下来的两个单词中。然后我们将 MAWS 设置为 64 并执行模块化乘法。我们正在寻找的减少值是结果的第 3 和第 4 字。
为了使其余的计算更容易,我们发现c之间的哪个项更大1和 c 2 ,然后选择我们从大数中减去较小以避免获得负数的等式。现在做一个模乘法,然后将其添加到 c 1 (如果我们乘以 m 1 ) 或 c 2 (如果我们乘以 m 2 ).
清单 1 显示了指向 MAA 中每个寄存器的无符号长字指针的初始化。给出了采用安全RISC架构的DeepCover安全微控制器(MAXQ1103)中MAA的硬编码地址。^®^
typedef unsigned long int ulong;
// long word pointers to MAA memories in the MAXQ1103
ulong *maa_aw = (ulong *) 0x8000;
ulong *maa_bw = (ulong *) 0x8100;
ulong *maa_resw = (ulong *) 0x8200;
ulong *maa_expw = (ulong *) 0x8400;
ulong *maa_modw = (ulong *) 0x8500;
清单 2 包含四个预先计算的常量:piqtp(读作 p 逆 q 乘以 p)、qiptq(读作 q 逆 p 乘以 q)、dphip(读作 p 的 d phi)和 dphiq(读作 q 的 d phi)。常量 diptp 和 piqtq 是 m1和米2上面的术语。常量 dphip 和 dphiq 是 c 的简化解密指数1和 c2上面的术语。两个载体 ptp 和 ptq 用于临时存储。其他变量 p、q、n、phi、e、d、pt 和 ct 描述了 RSA 所需的所有值。术语 phi 等于 (p - 1) × (q - 1)。
术语 nwords 是 n 中的单词数,即键的模数。在此实现中,假设 p 和 q 将具有正好 16 位× n字,并且 n 将恰好具有 32 位× n字。
这些向量中的单词从最低有效单词保存到最有效单词。它们从低字到高字加载到 MAA 寄存器中。需要明确的是,下面是一个 p × q = n 的示例,使用清单 2 中的常量和粗体的交替长字。
0xF22F213FE34B717B × 0xC9446776B381BFB9 = 0xBE67B781405A57697217C6CFBB2AC6E3
int nwords = 0x4;
ulong ptp[0x2];
ulong ptq[0x2];
// complete set of RSA constants
ulong p[0x2] = { 0xE34B717B, 0xF22F213F };
ulong q[0x2] = { 0xB381BFB9, 0xC9446776 };
ulong n[0x4] = { 0xBB2AC6E3, 0x7217C6CF, 0x405A5769, 0xBE67B781 };
ulong phi[0x4] = { 0x245D95B0, 0xB6A43E19, 0x405A5767, 0xBE67B781 };
// keys
ulong e[0x4] = { 0x00000005, 0x00000000, 0x00000000, 0x00000000 };
ulong d[0x4] = { 0xB6B1448D, 0xC55031AD, 0x337B791F, 0x9852F934 };
// sample plain text and corresponding cipher text
ulong pt[0x4] = { 0x90ABCDEF, 0x12345678, 0x90ABCDEF, 0x12345678 };
ulong ct[0x4] = { 0xDA3C591A, 0xC131AD9D, 0x40A51B30, 0x361958DF };
// the four pre-computed values used in crt computation.
ulong piqtp[0x4] = { 0x50995949, 0x4D355F7A, 0x907F8CC5, 0x1F0F60BF };
ulong qiptq[0x4] = { 0x6A916D9B, 0x24E26755, 0xAFDACAA4, 0x9F5856C1 };
ulong dphip[0x2] = { 0x5AEAFA31, 0x60DFA6E6 };
ulong dphiq[0x2] = { 0x6BB43FD5, 0x78C2A47A };
清单 3 具有 do_crt 函数,该函数使用 p 或 q 中的字数进行调用。例程从创建术语 c 开始1和 c2从上面并分别将这些值保存在 PTP 和 PTQ 中。然后我们确定 ptp 和 ptq 哪个更大,然后调用将执行模块化乘法和加法的例程。这会将 pt 留在maa_resw内存中。
void do_crt(int nwords)
{ // nwords is the number of 32 bit words in p or in q.
int i;
mod_reduction(ct, p, dphip, nwords, ptp);
mod_reduction(ct, q, dphiq, nwords, ptq);
for (i = nwords - 1; i >= 0; --i)
if (ptp[i] > ptq[i])
{
sum_mul_sub(2*nwords, ptp, ptq, qiptq, n);
break;
}
else
{
sum_mul_sub(2*nwords, ptq, ptp, piqtp, n);
break;
}
}
清单 4 包含初始化 MAA 的详细信息。在这里,我们清除MAA中的所有384个单词,初始化存储器选择寄存器MAMS,然后告诉MAA哪个是模数中最重要的位,MAWS。
void init_maa(int mod_size)
{
int i;
for (i = 0; i < 384; ++i)
maa_aw[i] = 0; // clear the entire MAA
MAMS = 0x6420; // memory select register
MAWS = mod_size; // position of the most significant bit of modulus.
}
清单 5 包含对 ptp = ct 形式的表达式进行模块化约简的详细信息^德菲普^莫德·此例程要做的第一件事是通过使用移位模数 p 进行模乘法,并让乘法成为移位值,将 ct 减小到其大小的一半。这些例程使用长单词的移动,而不是一次移动几个单词。(一个长字的距离移动就像移动32次。完成模乘法后,我们的简化答案在maa_resw寄存器中向左移动。
随着ct的减少,我们接下来进行模幂运算,以获得这个子程序应该得到的结果,ptp。
void mod_reduction(ulong *ct, ulong *p, ulong *dphip, int nwords, ulong *ptp)
{
int i;
// nwords as passed is the length of p. (rather than n)
// we are going to do a modmul, with a shifted p as the modulus
// init_maa is initializing MAWS with the correct modulus size.
init_maa(nwords*64);
// reducing ct mod p by doing the modmul ct * 2^(nwords*32) mod (p * (2^(nword*32))
// load a with ct
for (i = 0; i < 2*nwords; ++i)
maa_aw[i] = ct[i];
// load b with 2^(nwords*32) which is simply a bit set
maa_bw[nwords] = 1;
// load modulus with p*2^(nwords*32) which is simply a load shifted by nwords.
for (i = 0; i < nwords; ++i)
maa_modw[i + nwords] = p[i];
// this multiply gives us the reduction in ct and
// the answer in maa_resw shifted by nwords.
MACT = 0x05; // mod multiply and start
while (MACT & 1) // wait for the multiply to finish
;
// load registers to do ct^dphip mod p
// notice that we are coping the shifted result of maa_resw to maa_aw.
for (i = 0; i < nwords; ++i)
{
maa_aw[i] = maa_resw[nwords + i];
maa_bw[i] = 0;
maa_expw[i] = dphip[i];
maa_modw[i] = p[i];
}
maa_b[0] = 1; // the b reg is always 1 for modexp
MAWS = 32*nwords; // the most important step is setting MAWS to the correct size
MACT = 0x1; // mod exp and start
while (MACT & 1)
;
// copy our result to the ptp argument.
for (i = 0; i < nwords; ++i)
ptp[i] = maa_resw[i];
}
清单 6 描述了将所有内容组合在一起的函数。我们将计算方程 ct = (c 1 + 米 1 (c 2 , B 1 )) mod n if c2大于 c1或 ct = (c 2 + 米 2 (c 1 , B 2 )) 否则。它从减法开始。请注意,我们使用 n 作为模数,我们将处于乘法和加法的完整键长度。减法后,我们将结果从 maa_resw 移动到 maa_aw,并复制我们的乘数 m1或米 2 ,我们的参数 c 成maa_bw,并开始模乘法。在最后一步中,我们将乘法的结果从 maa_resw 复制到 maa_aw,然后复制 c1或 c 2 ,我们的参数 b,进入maa_bw并进行模块化加法。完成后,我们的纯文本是maa_resw的。
void sum_mul_sub(int nwords, ulong *a, ulong *b, ulong *c, ulong *n)
{
int i;
// prepare to subtract b from a
for (i = 0; i < nwords/2; ++i)
{
maa_aw[i] = a[i];
maa_bw[i] = b[i];
maa_modw[i] = n[i];
}
// clear the upper words of maa_a and maa_b and copy the rest of n
for (i = nwords/2; i < nwords; ++i)
{
maa_aw[i] = 0;
maa_bw[i] = 0;
maa_modw[i] = n[i];
}
// this is a full size operation.
// start the subtraction
MAWS = 32*nwords;
MACT = 0xB; // subtract and start
while (MACT & 1)
;
// copy the result over to maa_aw and
// put or multiplicand into maa_bw
for (i = 0; i < nwords; ++i)
{
maa_aw[i] = maa_resw[i];
maa_bw[i] = c[i];
}
MACT = 5; // multiply and start
while (MACT & 1)
;
for (i = 0; i < nwords/2; ++i)
{
maa_aw[i] = maa_resw[i];
maa_bw[i] = b[i];
}
for (i = nwords/2; i < nwords; ++i)
{
maa_aw[i] = maa_resw[i];
maa_bw[i] = 0;
}
MACT = 0x9; // add and start
while (MACT & 1)
;
}
表 1 和表 2 给出了使用上述算法可以实现的速度改进的指示。随着模量尺寸的增加,我们得到的时间减少更大。
这里介绍的 C 实现旨在证明使用此算法可以提高速度。该代码还显示了如何操作 MAA。可以做很多事情来提高算法的速度,包括循环展开、循环优化、使用编译器优化的数据移动例程以及使用汇编语言。
最快和最简单的速度改进是操作MAA的MAMS寄存器,这将消除一些数据移动。MAMS 寄存器允许我们重命名内存段。为简单起见,此应用程序中未完成此操作。
从理论上讲,通过使用这种算法,应该可以在提高速度的情况下接近 4 比 1 的时序比。
始终使用加密环作为您的加密时钟源。这是通过清除电源管理寄存器 (PMR) 中的主加密源选择(MCSS、PMR.7)来实现的。解密时,建议将模块化算术加速器控制寄存器(MACT)的优化计算控制(OCALC,MACT.4)清除为零,禁用该功能。
表 1.MAXQ1103 在25MHz,MAA运行在加密环路| 大小 | ModExp (ms) | 显像管(毫秒) | 率 |
| ------------------------------------------- | --------------- | ---------------- | ---- |
| 2048 | 549 | 166 | 3.3 |
| 1024 | 82.0 | 29.6 | 2.8 |
| 512 | 14.2 | 7.25 | 2.0 |
| 256 | 3.37 | 3.08 | 1.1 |
Table 2. DeepCover Secure Microcontroller (MAXQ1050) at 24MHz with the MAA Running with Crypto Ring| Size | ModExp (ms) | CRT (ms) | Ratio |
| -------------------------------------- | ------------- | ---------- | ------- |
| 2048 | 1760 | 492 | 3.6 |
| 1024 | 244 | 75.7 | 3.2 |
| 512 | 37.1 | 14.3 | 2.6 |
| 256 | 6.80 | 4.49 | 1.5 |
This example goes through the steps of constructing the public and private keys for RSA, then taking a sample message, encrypting it, and decrypting it. Then we show how the same encrypted message can be decrypted using the CRT.
我们首先找到几个质数。设 p = 0xE747 和 q = 0xC7A5。两者都是 16 位质数。
这给了我们 n = p × q = 0xB45D41C3 和 phi = (p - 1)(q - 1) = 0xB45B92D8。两者都是 32 位。
我们可以选择 e = 0x10001,因为 gcd(e, phi) = 1。这给了我们公钥。我们的私钥被选中,因此 e × d mod phi = 1。使用扩展的欧几里得算法,我们计算d = 0x9B111CC9。
我们任意选择我们的纯文本,pt = 0xABCDEF12。我们的密文,ct = pt^和^mod n = 0x87CCFE27。要恢复纯文本,请执行 ct^d^莫德·这是一个 32 位模幂。这原则上是 RSA 加密/解密过程。
现在我们将使用中文余数定理恢复纯文本。
离线时,我们预先计算四个常量。第一个是 piqtp = 0x9E1D261C,即 (p^-1^Mod Q) × p.第二个是 qiptq = 0x16401BA8,即 (q^-1^mod p) times q.它们都是 32 位长。您可以使用扩展的欧几里得算法或执行 p^Q-2^模组 q 和 q^P-2^mod p 找到逆数。我们还需要 dphip = d mod phi(p) = 0x9B111CC9 mod (0xE747 - 1) = 0x4AAB 和 dphiq = d mod phi(q) = 0x9B111CC9 mod (0xC7A5 - 1) = 0x9A0D。这些数字都是 16 位,大小是 n 的一半。
在线计算从通过 mod p 减少密文开始。密文长 32 位,模长 16 位。为了使用 MAA 进行归约,我们将模数 p 向左移动 16 位并将密文乘以 216。这看起来像0x87CCFE27 × 0x10000 mod 0xE7470000 = 0x36B00000。现在我们将答案向右移动 16 位,或者只抓住单词的上部 16 位。我们需要这个值来执行 16 位模幂0x36B0^德菲普^mod p,看起来像0x36B0^0x4AAB^模组 0xE747 = 0x6425 = PTP。
使用密文 mod q 的第二个模块化约简随着 mod 0xC87A27 = 0x10000D0 7x50000CCFE0 × 543x0000而扩展。将答案向右移动 16 位,或者只是抓住上面的单词,得到减少,0x543D。使用此结果并执行模幂0x543D^德菲克^mod q,看起来像0x543D^0x9A0D^模组0xC7A5 = 0x1671 = ptq.
如果 ptp 大于 ptq,我们计算 (ptq + (ptp - ptq) × qiptq) mod n,否则我们计算 (ptp + (ptq - ptp) × piqtp) mod n。请记住,piqtp 和 qiptq 是预先计算的,长度为 32 位。
我们看到 ptp 大于 ptq。差值,ptp - ptq = 0x4DB4。((ptp - ptq) 和 qiptq) mod n 和 (0x4DB4 × 0x16401BA8) mod 0xB45D41C3 的乘积是0xABCDD8A1。添加 ptq,0x1671会给我们返回纯文本,0xABCDEF12,我们就完成了。
审核编辑:郭婷
全部0条评论
快来发表一下你的评论吧 !