Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
5546b971
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
5546b971
编写于
3月 31, 2014
作者:
X
xuelei
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8031346: Enhance RSA key handling
Reviewed-by: ahgross, ascarpino, asmotrak, robm, weijun, wetmore
上级
464b0ee8
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
235 addition
and
84 deletion
+235
-84
src/share/classes/sun/security/rsa/RSACore.java
src/share/classes/sun/security/rsa/RSACore.java
+235
-84
未找到文件。
src/share/classes/sun/security/rsa/RSACore.java
浏览文件 @
5546b971
/*
* Copyright (c) 2003, 201
1
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 201
4
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
...
...
@@ -50,6 +50,15 @@ import sun.security.jca.JCAUtil;
*/
public
final
class
RSACore
{
// globally enable/disable use of blinding
private
final
static
boolean
ENABLE_BLINDING
=
true
;
// cache for blinding parameters. Map<BigInteger, BlindingParameters>
// use a weak hashmap so that cached values are automatically cleared
// when the modulus is GC'ed
private
final
static
Map
<
BigInteger
,
BlindingParameters
>
blindingCache
=
new
WeakHashMap
<>();
private
RSACore
()
{
// empty
}
...
...
@@ -100,12 +109,12 @@ public final class RSACore {
if
(
key
instanceof
RSAPrivateCrtKey
)
{
return
crtCrypt
(
msg
,
(
RSAPrivateCrtKey
)
key
);
}
else
{
return
c
rypt
(
msg
,
key
.
getModulus
(),
key
.
getPrivateExponent
());
return
priC
rypt
(
msg
,
key
.
getModulus
(),
key
.
getPrivateExponent
());
}
}
/**
* RSA public key ops
and non-CRT private key ops
. Simple modPow().
* RSA public key ops. Simple modPow().
*/
private
static
byte
[]
crypt
(
byte
[]
msg
,
BigInteger
n
,
BigInteger
exp
)
throws
BadPaddingException
{
...
...
@@ -114,23 +123,30 @@ public final class RSACore {
return
toByteArray
(
c
,
getByteLength
(
n
));
}
/**
* RSA non-CRT private key operations.
*/
private
static
byte
[]
priCrypt
(
byte
[]
msg
,
BigInteger
n
,
BigInteger
exp
)
throws
BadPaddingException
{
BigInteger
c
=
parseMsg
(
msg
,
n
);
BlindingRandomPair
brp
=
null
;
BigInteger
m
;
if
(
ENABLE_BLINDING
)
{
brp
=
getBlindingRandomPair
(
null
,
exp
,
n
);
c
=
c
.
multiply
(
brp
.
u
).
mod
(
n
);
m
=
c
.
modPow
(
exp
,
n
);
m
=
m
.
multiply
(
brp
.
v
).
mod
(
n
);
}
else
{
m
=
c
.
modPow
(
exp
,
n
);
}
return
toByteArray
(
m
,
getByteLength
(
n
));
}
/**
* RSA private key operations with CRT. Algorithm and variable naming
* are taken from PKCS#1 v2.1, section 5.1.2.
*
* The only difference is the addition of blinding to twart timing attacks.
* This is described in the RSA Bulletin#2 (Jan 96) among other places.
* This means instead of implementing RSA as
* m = c ^ d mod n (or RSA in CRT variant)
* we do
* r = random(0, n-1)
* c' = c * r^e mod n
* m' = c' ^ d mod n (or RSA in CRT variant)
* m = m' * r^-1 mod n (where r^-1 is the modular inverse of r mod n)
* This works because r^(e*d) * r^-1 = r * r^-1 = 1 (all mod n)
*
* We do not generate new blinding parameters for each operation but reuse
* them BLINDING_MAX_REUSE times (see definition below).
*/
private
static
byte
[]
crtCrypt
(
byte
[]
msg
,
RSAPrivateCrtKey
key
)
throws
BadPaddingException
{
...
...
@@ -141,13 +157,13 @@ public final class RSACore {
BigInteger
dP
=
key
.
getPrimeExponentP
();
BigInteger
dQ
=
key
.
getPrimeExponentQ
();
BigInteger
qInv
=
key
.
getCrtCoefficient
();
BigInteger
e
=
key
.
getPublicExponent
();
BigInteger
d
=
key
.
getPrivateExponent
();
Blinding
Parameters
params
;
Blinding
RandomPair
brp
;
if
(
ENABLE_BLINDING
)
{
params
=
getBlindingParameters
(
key
);
c
=
c
.
multiply
(
params
.
re
).
mod
(
n
);
}
else
{
params
=
null
;
brp
=
getBlindingRandomPair
(
e
,
d
,
n
);
c
=
c
.
multiply
(
brp
.
u
).
mod
(
n
);
}
// m1 = c ^ dP mod p
...
...
@@ -165,8 +181,8 @@ public final class RSACore {
// m = m2 + q * h
BigInteger
m
=
h
.
multiply
(
q
).
add
(
m2
);
if
(
params
!=
null
)
{
m
=
m
.
multiply
(
params
.
rIn
v
).
mod
(
n
);
if
(
ENABLE_BLINDING
)
{
m
=
m
.
multiply
(
brp
.
v
).
mod
(
n
);
}
return
toByteArray
(
m
,
getByteLength
(
n
));
...
...
@@ -208,82 +224,217 @@ public final class RSACore {
return
t
;
}
// globally enable/disable use of blinding
private
final
static
boolean
ENABLE_BLINDING
=
true
;
// maximum number of times that we will use a set of blinding parameters
// value suggested by Paul Kocher (quoted by NSS)
private
final
static
int
BLINDING_MAX_REUSE
=
50
;
/**
* Parameters (u,v) for RSA Blinding. This is described in the RSA
* Bulletin#2 (Jan 96) and other places:
*
* ftp://ftp.rsa.com/pub/pdfs/bull-2.pdf
*
* The standard RSA Blinding decryption requires the public key exponent
* (e) and modulus (n), and converts ciphertext (c) to plaintext (p).
*
* Before the modular exponentiation operation, the input message should
* be multiplied by (u (mod n)), and afterward the result is corrected
* by multiplying with (v (mod n)). The system should reject messages
* equal to (0 (mod n)). That is:
*
* 1. Generate r between 0 and n-1, relatively prime to n.
* 2. Compute x = (c*u) mod n
* 3. Compute y = (x^d) mod n
* 4. Compute p = (y*v) mod n
*
* The Java APIs allows for either standard RSAPrivateKey or
* RSAPrivateCrtKey RSA keys.
*
* If the public exponent is available to us (e.g. RSAPrivateCrtKey),
* choose a random r, then let (u, v):
*
* u = r ^ e mod n
* v = r ^ (-1) mod n
*
* The proof follows:
*
* p = (((c * u) ^ d mod n) * v) mod n
* = ((c ^ d) * (u ^ d) * v) mod n
* = ((c ^ d) * (r ^ e) ^ d) * (r ^ (-1))) mod n
* = ((c ^ d) * (r ^ (e * d)) * (r ^ (-1))) mod n
* = ((c ^ d) * (r ^ 1) * (r ^ (-1))) mod n (see below)
* = (c ^ d) mod n
*
* because in RSA cryptosystem, d is the multiplicative inverse of e:
*
* (r^(e * d)) mod n
* = (r ^ 1) mod n
* = r mod n
*
* However, if the public exponent is not available (e.g. RSAPrivateKey),
* we mitigate the timing issue by using a similar random number blinding
* approach using the private key:
*
* u = r
* v = ((r ^ (-1)) ^ d) mod n
*
* This returns the same plaintext because:
*
* p = (((c * u) ^ d mod n) * v) mod n
* = ((c ^ d) * (u ^ d) * v) mod n
* = ((c ^ d) * (u ^ d) * ((u ^ (-1)) ^d)) mod n
* = (c ^ d) mod n
*
* Computing inverses mod n and random number generation is slow, so
* it is often not practical to generate a new random (u, v) pair for
* each new exponentiation. The calculation of parameters might even be
* subject to timing attacks. However, (u, v) pairs should not be
* reused since they themselves might be compromised by timing attacks,
* leaving the private exponent vulnerable. An efficient solution to
* this problem is update u and v before each modular exponentiation
* step by computing:
*
* u = u ^ 2
* v = v ^ 2
*
* The total performance cost is small.
*/
private
final
static
class
BlindingRandomPair
{
final
BigInteger
u
;
final
BigInteger
v
;
// cache for blinding parameters. Map<BigInteger, BlindingParameters>
// use a weak hashmap so that cached values are automatically cleared
// when the modulus is GC'ed
private
final
static
Map
<
BigInteger
,
BlindingParameters
>
blindingCache
=
new
WeakHashMap
<>();
BlindingRandomPair
(
BigInteger
u
,
BigInteger
v
)
{
this
.
u
=
u
;
this
.
v
=
v
;
}
}
/**
* Set of blinding parameters for a given RSA key.
*
* The RSA modulus is usually unique, so we index by modulus in
* blindingCache. However, to protect against the unlikely case of two
* keys sharing the same modulus, we also store the public exponent.
* This means we cannot cache blinding parameters for multiple keys that
* share the same modulus, but since sharing moduli is fundamentally broken
* an insecure, this does not matter.
* {@code blindingCache}. However, to protect against the unlikely
* case of two keys sharing the same modulus, we also store the public
* or the private exponent. This means we cannot cache blinding
* parameters for multiple keys that share the same modulus, but
* since sharing moduli is fundamentally broken and insecure, this
* does not matter.
*/
private
static
final
class
BlindingParameters
{
// e (RSA public exponent)
final
BigInteger
e
;
// r ^ e mod n
final
BigInteger
re
;
// inverse of r mod n
final
BigInteger
rInv
;
// how many more times this parameter object can be used
private
volatile
int
remainingUses
;
BlindingParameters
(
BigInteger
e
,
BigInteger
re
,
BigInteger
rInv
)
{
private
final
static
class
BlindingParameters
{
private
final
static
BigInteger
BIG_TWO
=
BigInteger
.
valueOf
(
2L
);
// RSA public exponent
private
final
BigInteger
e
;
// hash code of RSA private exponent
private
final
BigInteger
d
;
// r ^ e mod n (CRT), or r mod n (Non-CRT)
private
BigInteger
u
;
// r ^ (-1) mod n (CRT) , or ((r ^ (-1)) ^ d) mod n (Non-CRT)
private
BigInteger
v
;
// e: the public exponent
// d: the private exponent
// n: the modulus
BlindingParameters
(
BigInteger
e
,
BigInteger
d
,
BigInteger
n
)
{
this
.
u
=
null
;
this
.
v
=
null
;
this
.
e
=
e
;
this
.
re
=
re
;
this
.
rInv
=
rInv
;
// initialize remaining uses, subtract current use now
remainingUses
=
BLINDING_MAX_REUSE
-
1
;
this
.
d
=
d
;
int
len
=
n
.
bitLength
();
SecureRandom
random
=
JCAUtil
.
getSecureRandom
();
u
=
new
BigInteger
(
len
,
random
).
mod
(
n
);
// Although the possibility is very much limited that u is zero
// or is not relatively prime to n, we still want to be careful
// about the special value.
//
// Secure random generation is expensive, try to use BigInteger.ONE
// this time if this new generated random number is zero or is not
// relatively prime to n. Next time, new generated secure random
// number will be used instead.
if
(
u
.
equals
(
BigInteger
.
ZERO
))
{
u
=
BigInteger
.
ONE
;
// use 1 this time
}
try
{
// The call to BigInteger.modInverse() checks that u is
// relatively prime to n. Otherwise, ArithmeticException is
// thrown.
v
=
u
.
modInverse
(
n
);
}
catch
(
ArithmeticException
ae
)
{
// if u is not relatively prime to n, use 1 this time
u
=
BigInteger
.
ONE
;
v
=
BigInteger
.
ONE
;
}
if
(
e
!=
null
)
{
u
=
u
.
modPow
(
e
,
n
);
// e: the public exponent
// u: random ^ e
// v: random ^ (-1)
}
else
{
v
=
v
.
modPow
(
d
,
n
);
// d: the private exponent
// u: random
// v: random ^ (-d)
}
}
boolean
valid
(
BigInteger
e
)
{
int
k
=
remainingUses
--;
return
(
k
>
0
)
&&
this
.
e
.
equals
(
e
);
// return null if need to reset the parameters
BlindingRandomPair
getBlindingRandomPair
(
BigInteger
e
,
BigInteger
d
,
BigInteger
n
)
{
if
((
this
.
e
!=
null
&&
this
.
e
.
equals
(
e
))
||
(
this
.
d
!=
null
&&
this
.
d
.
equals
(
d
)))
{
BlindingRandomPair
brp
=
null
;
synchronized
(
this
)
{
if
(!
u
.
equals
(
BigInteger
.
ZERO
)
&&
!
v
.
equals
(
BigInteger
.
ZERO
))
{
brp
=
new
BlindingRandomPair
(
u
,
v
);
if
(
u
.
compareTo
(
BigInteger
.
ONE
)
<=
0
||
v
.
compareTo
(
BigInteger
.
ONE
)
<=
0
)
{
// need to reset the random pair next time
u
=
BigInteger
.
ZERO
;
v
=
BigInteger
.
ZERO
;
}
else
{
u
=
u
.
modPow
(
BIG_TWO
,
n
);
v
=
v
.
modPow
(
BIG_TWO
,
n
);
}
}
// Otherwise, need to reset the random pair.
}
return
brp
;
}
return
null
;
}
}
/**
* Return valid RSA blinding parameters for the given private key.
* Use cached parameters if available. If not, generate new parameters
* and cache.
*/
private
static
BlindingParameters
getBlindingParameters
(
RSAPrivateCrtKey
key
)
{
BigInteger
modulus
=
key
.
getModulus
();
BigInteger
e
=
key
.
getPublicExponent
();
BlindingParameters
params
;
// we release the lock between get() and put()
// that means threads might concurrently generate new blinding
// parameters for the same modulus. this is only a slight waste
// of cycles and seems preferable in terms of scalability
// to locking out all threads while generating new parameters
private
static
BlindingRandomPair
getBlindingRandomPair
(
BigInteger
e
,
BigInteger
d
,
BigInteger
n
)
{
BlindingParameters
bps
=
null
;
synchronized
(
blindingCache
)
{
params
=
blindingCache
.
get
(
modulus
);
bps
=
blindingCache
.
get
(
n
);
}
if
((
params
!=
null
)
&&
params
.
valid
(
e
))
{
return
params
;
if
(
bps
==
null
)
{
bps
=
new
BlindingParameters
(
e
,
d
,
n
);
synchronized
(
blindingCache
)
{
blindingCache
.
putIfAbsent
(
n
,
bps
);
}
}
int
len
=
modulus
.
bitLength
();
SecureRandom
random
=
JCAUtil
.
getSecureRandom
();
BigInteger
r
=
new
BigInteger
(
len
,
random
).
mod
(
modulus
);
BigInteger
re
=
r
.
modPow
(
e
,
modulus
);
BigInteger
rInv
=
r
.
modInverse
(
modulus
);
params
=
new
BlindingParameters
(
e
,
re
,
rInv
);
synchronized
(
blindingCache
)
{
blindingCache
.
put
(
modulus
,
params
);
BlindingRandomPair
brp
=
bps
.
getBlindingRandomPair
(
e
,
d
,
n
);
if
(
brp
==
null
)
{
// need to reset the blinding parameters
bps
=
new
BlindingParameters
(
e
,
d
,
n
);
synchronized
(
blindingCache
)
{
blindingCache
.
replace
(
n
,
bps
);
}
brp
=
bps
.
getBlindingRandomPair
(
e
,
d
,
n
);
}
return
params
;
return
brp
;
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录