OpenSSL密码库算法笔记——第 3.3章 模逆

2019-04-13 16:13发布

在模运算中,一般没有直接做模除法。模除法a/b mod m都是先计算模逆t=b-1 mod m,再计算模乘at mod m。因此本节就来讨论模逆运算该怎样实现。 求模逆的算法主要是扩展欧几里德算法。该算法的大意如下。 假设计算a^{-1}modm。算法通过反复迭代Ad+dm=uCa+em=v(A、C、d、e为某些待定数)而得出a^{-1}modm,这里的迭代主要是做乘法和减法。 算法的步骤大概是这样的。开始的时候先进行初始化——取A=1,d=0,C=0,e=1,得到:                 …………(3.2) 然后反复做如下迭代(为了记号的方便,迭代过程中始终让u≥v,否则,交换<1>、<2>两式):
  • q=left lfloor u/v 
ight 
floor
  • 新的<1>式 ← 老的<2>式;
  • 新的<2>式 ← 老的<1>式-q×老的<2>式;
如此迭代,直到v=0为止。最后得出Amodm=a^{-1}modm,注意最后得出的A可能是负数(比如下面举的例子就是这样),此时只需要加上m即可。   下面给出用扩展欧几里德算法计算的详细描述。算法中出现的符号和上面的介绍一致,新增加的三个变量t1,t2,t3为临时变量。算法可参见[2,§4.5.2算法X]。 ─────────────────────────────────────── ─────────────────────────────────────── 以上是一般情况下的扩展欧几里德算法。如果模数m为奇数(为了以示区别,记此时的奇模数为p),算法可以变的更加简单快捷——利用反复的右移(即除2)来代替除法。 下面来看看这个特殊的算法怎样计算a^{-1}modp,这里的p为奇数。(也可参见[9,算法8])。 ───────────────────────────────────────   ─────────────────────────────────────── 下面介绍的求模逆的C程序综合利用了以上两种算法:当模数是奇数而且字长小于450时,利用特殊的扩展欧几里德算法——模数为奇数的扩展欧几里德算法来进行计算,如果模数不满足这个条件,就用一般的扩展欧几里德算法来进行计算。 ─────────────────────────────────────── BIGNUM *BN_mod_inverse(BIGNUM *in,const BIGNUM *a, const BIGNUM *n) 功能:    求模逆 输入:    a【被模数】,n【模数】 输出:    in ← 1/a mod n 返回:    in【正常】 or NULL【出错】 出处:    bn_gcd.c ─────────────────────────────────────── 有一个特殊的模逆函数BN_mod_inverse_no_branch,它利用一些特殊的方法来防止信息泄漏,抵抗能量攻击。其算法思想类似普通的扩展欧几里德算法,但其中间用了点小技巧以防止信息泄漏,详细情况请参见原函数。 ─────────────────────────────────────── static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n) 功能:    用抗能量攻击法求模逆 输入:    a【被模数】,n【模数】 输出:    in ← 1/a mod n 返回:    in【正常】 or NULL【出错】 出处:    bn_gcd.c ───────────────────────────────────────