Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Third Party Openssl
提交
7d0d0996
T
Third Party Openssl
项目概览
OpenHarmony
/
Third Party Openssl
9 个月 前同步成功
通知
8
Star
18
Fork
1
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
Third Party Openssl
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
7d0d0996
编写于
4月 08, 2001
作者:
B
Bodo Möller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
binary algorithm for modular inversion
上级
9cddbf14
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
190 addition
and
98 deletion
+190
-98
CHANGES
CHANGES
+7
-0
crypto/bn/bn_gcd.c
crypto/bn/bn_gcd.c
+181
-96
crypto/bn/bn_mod.c
crypto/bn/bn_mod.c
+2
-2
未找到文件。
CHANGES
浏览文件 @
7d0d0996
...
...
@@ -4,6 +4,13 @@
Changes between 0.9.6 and 0.9.7 [xx XXX 2000]
*) Implement binary inversion algorithm for BN_mod_inverse in addition
to the algorithm using long divison. The binary algorithm can be
used only if the modulus is odd. It is faster only for relatively
small moduli (roughly 20% for 128-bit moduli, roughly 5% for 256-bit
moduli), so we use it only for moduli up to 400 bits.
[Bodo Moeller]
*) Change bctest again: '-x' expressions are not available in all
versions of 'test'.
[Bodo Moeller]
...
...
crypto/bn/bn_gcd.c
浏览文件 @
7d0d0996
...
...
@@ -56,7 +56,7 @@
* [including the GNU Public Licence.]
*/
/* ====================================================================
* Copyright (c) 1998-200
0
The OpenSSL Project. All rights reserved.
* Copyright (c) 1998-200
1
The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
...
...
@@ -240,131 +240,216 @@ BIGNUM *BN_mod_inverse(BIGNUM *in,
/* From B = a mod |n|, A = |n| it follows that
*
* 0 <= B < A,
*
sign*X*a == B (mod |n|),
*
-
sign*Y*a == A (mod |n|).
*
-
sign*X*a == B (mod |n|),
*
sign*Y*a == A (mod |n|).
*/
while
(
!
BN_is_zero
(
B
))
if
(
BN_is_odd
(
n
)
&&
(
BN_num_bits
(
n
)
<=
400
))
{
BIGNUM
*
tmp
;
/* Binary inversion algorithm; requires odd modulus.
* This is faster than the general algorithm if the modulus
* is sufficiently small. */
int
shift
;
while
(
!
BN_is_zero
(
B
))
{
/*
* 0 < B < A <= |n|,
* (1) -sign*X*a == B (mod |n|),
* (2) sign*Y*a == A (mod |n|)
*/
/* Now divide B by the maximum possible power of two in the integers,
* and divide X by the same value mod |n|.
* When we're done, (1) still holds. */
shift
=
0
;
while
(
!
BN_is_bit_set
(
B
,
shift
))
/* note that 0 < B */
{
shift
++
;
if
(
BN_is_odd
(
X
))
{
if
(
!
BN_uadd
(
X
,
X
,
n
))
goto
err
;
}
/* now X is even, so we can easily divide it by two */
if
(
!
BN_rshift1
(
X
,
X
))
goto
err
;
}
if
(
shift
>
0
)
{
if
(
!
BN_rshift
(
B
,
B
,
shift
))
goto
err
;
}
/*
* 0 < B < A,
* (*) sign*X*a == B (mod |n|),
* -sign*Y*a == A (mod |n|)
*/
/* (D, M) := (A/B, A%B) ... */
if
(
BN_num_bits
(
A
)
==
BN_num_bits
(
B
))
{
if
(
!
BN_one
(
D
))
goto
err
;
if
(
!
BN_sub
(
M
,
A
,
B
))
goto
err
;
/* Same for A and Y. Afterwards, (2) still holds. */
shift
=
0
;
while
(
!
BN_is_bit_set
(
A
,
shift
))
/* note that 0 < A */
{
shift
++
;
if
(
BN_is_odd
(
Y
))
{
if
(
!
BN_uadd
(
Y
,
Y
,
n
))
goto
err
;
}
/* now Y is even */
if
(
!
BN_rshift1
(
Y
,
Y
))
goto
err
;
}
if
(
shift
>
0
)
{
if
(
!
BN_rshift
(
A
,
A
,
shift
))
goto
err
;
}
/* We still have (1) and (2), but A may no longer be larger than B.
* Both A and B are odd.
* The following computations ensure that
*
* 0 =< B < A = |n|,
* (1) -sign*X*a == B (mod |n|),
* (2) sign*Y*a == A (mod |n|)
*/
if
(
BN_ucmp
(
B
,
A
)
>=
0
)
{
/* -sign*(X + Y)*a == B - A (mod |n|) */
if
(
!
BN_uadd
(
X
,
X
,
Y
))
goto
err
;
/* NB: we could use BN_mod_add_quick(X, X, Y, n), but that
* actually makes the algorithm slower */
if
(
!
BN_usub
(
B
,
B
,
A
))
goto
err
;
}
else
{
/* sign*(X + Y)*a == A - B (mod |n|) */
if
(
!
BN_uadd
(
Y
,
Y
,
X
))
goto
err
;
/* as above, BN_mod_add_quick(Y, Y, X, n) would slow things down */
if
(
!
BN_usub
(
A
,
A
,
B
))
goto
err
;
}
}
else
if
(
BN_num_bits
(
A
)
==
BN_num_bits
(
B
)
+
1
)
}
else
{
/* general inversion algorithm (less efficient than binary inversion) */
while
(
!
BN_is_zero
(
B
))
{
/* A/B is 1, 2, or 3 */
if
(
!
BN_lshift1
(
T
,
B
))
goto
err
;
if
(
BN_ucmp
(
A
,
T
)
<
0
)
BIGNUM
*
tmp
;
/*
* 0 < B < A,
* (*) -sign*X*a == B (mod |n|),
* sign*Y*a == A (mod |n|)
*/
/* (D, M) := (A/B, A%B) ... */
if
(
BN_num_bits
(
A
)
==
BN_num_bits
(
B
))
{
/* A < 2*B, so D=1 */
if
(
!
BN_one
(
D
))
goto
err
;
if
(
!
BN_sub
(
M
,
A
,
B
))
goto
err
;
}
else
else
if
(
BN_num_bits
(
A
)
==
BN_num_bits
(
B
)
+
1
)
{
/* A >= 2*B, so D=2 or D=3 */
if
(
!
BN_sub
(
M
,
A
,
T
))
goto
err
;
if
(
!
BN_add
(
D
,
T
,
B
))
goto
err
;
/* use D (:= 3*B) as temp */
if
(
BN_ucmp
(
A
,
D
)
<
0
)
/* A/B is 1, 2, or 3 */
if
(
!
BN_lshift1
(
T
,
B
))
goto
err
;
if
(
BN_ucmp
(
A
,
T
)
<
0
)
{
/* A <
3*B, so D=2
*/
if
(
!
BN_
set_word
(
D
,
2
))
goto
err
;
/* M (= A - 2*B) already has the correct value */
/* A <
2*B, so D=1
*/
if
(
!
BN_
one
(
D
))
goto
err
;
if
(
!
BN_sub
(
M
,
A
,
B
))
goto
err
;
}
else
{
/* only D=3 remains */
if
(
!
BN_set_word
(
D
,
3
))
goto
err
;
/* currently M = A - 2*B, but we need M = A - 3*B */
if
(
!
BN_sub
(
M
,
M
,
B
))
goto
err
;
/* A >= 2*B, so D=2 or D=3 */
if
(
!
BN_sub
(
M
,
A
,
T
))
goto
err
;
if
(
!
BN_add
(
D
,
T
,
B
))
goto
err
;
/* use D (:= 3*B) as temp */
if
(
BN_ucmp
(
A
,
D
)
<
0
)
{
/* A < 3*B, so D=2 */
if
(
!
BN_set_word
(
D
,
2
))
goto
err
;
/* M (= A - 2*B) already has the correct value */
}
else
{
/* only D=3 remains */
if
(
!
BN_set_word
(
D
,
3
))
goto
err
;
/* currently M = A - 2*B, but we need M = A - 3*B */
if
(
!
BN_sub
(
M
,
M
,
B
))
goto
err
;
}
}
}
}
else
{
if
(
!
BN_div
(
D
,
M
,
A
,
B
,
ctx
))
goto
err
;
}
/* Now
* A = D*B + M;
* thus we have
* (**) -sign*Y*a == D*B + M (mod |n|).
*/
tmp
=
A
;
/* keep the BIGNUM object, the value does not matter */
/* (A, B) := (B, A mod B) ... */
A
=
B
;
B
=
M
;
/* ... so we have 0 <= B < A again */
/* Since the former M is now B and the former B is now A,
* (**) translates into
* -sign*Y*a == D*A + B (mod |n|),
* i.e.
* -sign*Y*a - D*A == B (mod |n|).
* Similarly, (*) translates into
* sign*X*a == A (mod |n|).
*
* Thus,
* -sign*Y*a - D*sign*X*a == B (mod |n|),
* i.e.
* -sign*(Y + D*X)*a == B (mod |n|).
*
* So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at
* sign*X*a == B (mod |n|),
* -sign*Y*a == A (mod |n|).
* Note that X and Y stay non-negative all the time.
*/
/* most of the time D is very small, so we can optimize tmp := D*X+Y */
if
(
BN_is_one
(
D
))
{
if
(
!
BN_add
(
tmp
,
X
,
Y
))
goto
err
;
}
else
{
if
(
BN_is_word
(
D
,
2
))
{
if
(
!
BN_lshift1
(
tmp
,
X
))
goto
err
;
}
else
if
(
BN_is_word
(
D
,
4
))
else
{
if
(
!
BN_
lshift
(
tmp
,
X
,
2
))
goto
err
;
if
(
!
BN_
div
(
D
,
M
,
A
,
B
,
ctx
))
goto
err
;
}
else
if
(
D
->
top
==
1
)
/* Now
* A = D*B + M;
* thus we have
* (**) sign*Y*a == D*B + M (mod |n|).
*/
tmp
=
A
;
/* keep the BIGNUM object, the value does not matter */
/* (A, B) := (B, A mod B) ... */
A
=
B
;
B
=
M
;
/* ... so we have 0 <= B < A again */
/* Since the former M is now B and the former B is now A,
* (**) translates into
* sign*Y*a == D*A + B (mod |n|),
* i.e.
* sign*Y*a - D*A == B (mod |n|).
* Similarly, (*) translates into
* -sign*X*a == A (mod |n|).
*
* Thus,
* sign*Y*a + D*sign*X*a == B (mod |n|),
* i.e.
* sign*(Y + D*X)*a == B (mod |n|).
*
* So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at
* -sign*X*a == B (mod |n|),
* sign*Y*a == A (mod |n|).
* Note that X and Y stay non-negative all the time.
*/
/* most of the time D is very small, so we can optimize tmp := D*X+Y */
if
(
BN_is_one
(
D
))
{
if
(
!
BN_copy
(
tmp
,
X
))
goto
err
;
if
(
!
BN_mul_word
(
tmp
,
D
->
d
[
0
]))
goto
err
;
if
(
!
BN_add
(
tmp
,
X
,
Y
))
goto
err
;
}
else
{
if
(
!
BN_mul
(
tmp
,
D
,
X
,
ctx
))
goto
err
;
if
(
BN_is_word
(
D
,
2
))
{
if
(
!
BN_lshift1
(
tmp
,
X
))
goto
err
;
}
else
if
(
BN_is_word
(
D
,
4
))
{
if
(
!
BN_lshift
(
tmp
,
X
,
2
))
goto
err
;
}
else
if
(
D
->
top
==
1
)
{
if
(
!
BN_copy
(
tmp
,
X
))
goto
err
;
if
(
!
BN_mul_word
(
tmp
,
D
->
d
[
0
]))
goto
err
;
}
else
{
if
(
!
BN_mul
(
tmp
,
D
,
X
,
ctx
))
goto
err
;
}
if
(
!
BN_add
(
tmp
,
tmp
,
Y
))
goto
err
;
}
if
(
!
BN_add
(
tmp
,
tmp
,
Y
))
goto
err
;
M
=
Y
;
/* keep the BIGNUM object, the value does not matter */
Y
=
X
;
X
=
tmp
;
sign
=
-
sign
;
}
M
=
Y
;
/* keep the BIGNUM object, the value does not matter */
Y
=
X
;
X
=
tmp
;
sign
=
-
sign
;
}
/*
* The while loop (Euclid's algorithm) ends when
* A == gcd(a,n);
* we have
*
-
sign*Y*a == A (mod |n|),
*
sign*Y*a == A (mod |n|),
* where Y is non-negative.
*/
...
...
@@ -378,7 +463,7 @@ BIGNUM *BN_mod_inverse(BIGNUM *in,
if
(
BN_is_one
(
A
))
{
/* Y*a == 1 (mod |n|) */
if
(
BN_ucmp
(
Y
,
n
)
<
0
)
if
(
!
Y
->
neg
&&
BN_ucmp
(
Y
,
n
)
<
0
)
{
if
(
!
BN_copy
(
R
,
Y
))
goto
err
;
}
...
...
crypto/bn/bn_mod.c
浏览文件 @
7d0d0996
...
...
@@ -150,8 +150,8 @@ int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_
int
BN_mod_add_quick
(
BIGNUM
*
r
,
const
BIGNUM
*
a
,
const
BIGNUM
*
b
,
const
BIGNUM
*
m
)
{
if
(
!
BN_add
(
r
,
a
,
b
))
return
0
;
if
(
BN_cmp
(
r
,
m
)
>=
0
)
return
BN_sub
(
r
,
r
,
m
);
if
(
BN_
u
cmp
(
r
,
m
)
>=
0
)
return
BN_
u
sub
(
r
,
r
,
m
);
return
1
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录