Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
d4ac959d
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看板
提交
d4ac959d
编写于
4月 08, 2009
作者:
W
weijun
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
4811968: ASN.1 (X509Certificate) implementations don't handle large OID components
Reviewed-by: xuelei
上级
dcf31cd6
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
730 addition
and
286 deletion
+730
-286
src/share/classes/sun/security/util/ObjectIdentifier.java
src/share/classes/sun/security/util/ObjectIdentifier.java
+484
-283
test/sun/security/util/Oid/OidFormat.java
test/sun/security/util/Oid/OidFormat.java
+16
-3
test/sun/security/util/Oid/S11N.sh
test/sun/security/util/Oid/S11N.sh
+164
-0
test/sun/security/util/Oid/SerialTest.java
test/sun/security/util/Oid/SerialTest.java
+66
-0
未找到文件。
src/share/classes/sun/security/util/ObjectIdentifier.java
浏览文件 @
d4ac959d
...
@@ -26,7 +26,8 @@
...
@@ -26,7 +26,8 @@
package
sun.security.util
;
package
sun.security.util
;
import
java.io.*
;
import
java.io.*
;
import
java.math.BigInteger
;
import
java.util.Arrays
;
/**
/**
* Represent an ISO Object Identifier.
* Represent an ISO Object Identifier.
...
@@ -44,105 +45,186 @@ import java.io.*;
...
@@ -44,105 +45,186 @@ import java.io.*;
* hierarchy, and other organizations can easily acquire the ability
* hierarchy, and other organizations can easily acquire the ability
* to assign such unique identifiers.
* to assign such unique identifiers.
*
*
*
* @author David Brownell
* @author David Brownell
* @author Amit Kapoor
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @author Hemma Prafullchandra
*/
*/
final
public
final
public
class
ObjectIdentifier
implements
Serializable
class
ObjectIdentifier
implements
Serializable
{
{
/** use serialVersionUID from JDK 1.1. for interoperability */
/**
* We use the DER value (no tag, no length) as the internal format
* @serial
*/
private
byte
[]
encoding
=
null
;
private
transient
volatile
String
stringForm
;
/*
* IMPORTANT NOTES FOR CODE CHANGES (bug 4811968) IN JDK 1.7.0
* ===========================================================
*
* (Almost) serialization compatibility with old versions:
*
* serialVersionUID is unchanged. Old field "component" is changed to
* type Object so that "poison" (unknown object type for old versions)
* can be put inside if there are huge components that cannot be saved
* as integers.
*
* New version use the new filed "encoding" only.
*
* Below are all 4 cases in a serialization/deserialization process:
*
* 1. old -> old: Not covered here
* 2. old -> new: There's no "encoding" field, new readObject() reads
* "components" and "componentLen" instead and inits correctly.
* 3. new -> new: "encoding" field exists, new readObject() uses it
* (ignoring the other 2 fields) and inits correctly.
* 4. new -> old: old readObject() only recognizes "components" and
* "componentLen" fields. If no huge components are involved, they
* are serialized as legal values and old object can init correctly.
* Otherwise, old object cannot recognize the form (component not int[])
* and throw a ClassNotFoundException at deserialization time.
*
* Therfore, for the first 3 cases, exact compatibility is preserved. In
* the 4th case, non-huge OID is still supportable in old versions, while
* huge OID is not.
*/
private
static
final
long
serialVersionUID
=
8697030238860181294L
;
private
static
final
long
serialVersionUID
=
8697030238860181294L
;
private
static
final
int
maxFirstComponent
=
2
;
private
static
final
int
maxSecondComponent
=
39
;
/**
/**
* C
onstructs an object identifier from a string. This string
* C
hanged to Object
*
should be of the form 1.23.34.45.56 etc.
*
@serial
*/
*/
p
ublic
ObjectIdentifier
(
String
oid
)
throws
IOException
p
rivate
Object
components
=
null
;
// path from root
{
/**
int
ch
=
'.'
;
* @serial
int
start
=
0
;
*/
int
end
=
0
;
private
int
componentLen
=
-
1
;
// how much is used.
// Calculate length of oid
// Is the components field calculated?
componentLen
=
0
;
transient
private
boolean
componentsCalculated
=
false
;
while
((
end
=
oid
.
indexOf
(
ch
,
start
))
!=
-
1
)
{
start
=
end
+
1
;
private
void
readObject
(
ObjectInputStream
is
)
componentLen
+=
1
;
throws
IOException
,
ClassNotFoundException
{
is
.
defaultReadObject
();
if
(
encoding
==
null
)
{
// from an old version
init
((
int
[])
components
,
componentLen
);
}
}
componentLen
+=
1
;
}
components
=
new
int
[
componentLen
];
start
=
0
;
private
void
writeObject
(
ObjectOutputStream
os
)
int
i
=
0
;
throws
IOException
{
String
comp
=
null
;
if
(!
componentsCalculated
)
{
try
{
int
[]
comps
=
toIntArray
();
while
((
end
=
oid
.
indexOf
(
ch
,
start
))
!=
-
1
)
{
if
(
comps
!=
null
)
{
// every one understands this
comp
=
oid
.
substring
(
start
,
end
);
components
=
comps
;
components
[
i
++]
=
Integer
.
valueOf
(
comp
).
intValue
();
componentLen
=
comps
.
length
;
start
=
end
+
1
;
}
else
{
components
=
HugeOidNotSupportedByOldJDK
.
theOne
;
}
}
comp
=
oid
.
substring
(
start
);
componentsCalculated
=
true
;
components
[
i
]
=
Integer
.
valueOf
(
comp
).
intValue
();
}
catch
(
Exception
e
)
{
throw
new
IOException
(
"ObjectIdentifier() -- Invalid format: "
+
e
.
toString
(),
e
);
}
}
checkValidOid
(
components
,
componentLen
);
os
.
defaultWriteObject
();
this
.
stringForm
=
oid
;
}
static
class
HugeOidNotSupportedByOldJDK
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
static
HugeOidNotSupportedByOldJDK
theOne
=
new
HugeOidNotSupportedByOldJDK
();
}
}
/**
/**
* Check if the values make a legal OID. There must be at least 2
* Constructs, from a string. This string should be of the form 1.23.56.
* components and they must be all non-negative. The first component
* Validity check included.
* should be 0,1 or 2. When the first component is 0 or 1, the
* second component should be less than or equal to 39
*
* @param values the components that will make the OID
* @param len the number of components to check. Note that the allocation
* size of <code>values</code> may be longer than <code>len</code>.
* In this case, only the first <code>len</code> items are checked.
* @exception IOException if this is not a legal OID
*/
*/
p
rivate
void
checkValidOid
(
int
[]
values
,
int
len
)
throws
IOException
{
p
ublic
ObjectIdentifier
(
String
oid
)
throws
IOException
if
(
values
==
null
||
len
<
2
)
{
{
throw
new
IOException
(
"ObjectIdentifier() -- "
+
int
ch
=
'.'
;
"Must be at least two oid components "
)
;
int
start
=
0
;
}
int
end
=
0
;
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
int
pos
=
0
;
if
(
values
[
i
]
<
0
)
{
byte
[]
tmp
=
new
byte
[
oid
.
length
()];
throw
new
IOException
(
"ObjectIdentifier() -- "
+
int
first
=
0
,
second
;
"oid component #"
+
(
i
+
1
)
+
" must be non-negative "
);
int
count
=
0
;
}
}
if
(
values
[
0
]
>
maxFirstComponent
)
{
try
{
throw
new
IOException
(
"ObjectIdentifier() -- "
+
String
comp
=
null
;
"First oid component is invalid "
);
do
{
}
int
length
=
0
;
// length of one section
end
=
oid
.
indexOf
(
ch
,
start
);
if
(
end
==
-
1
)
{
comp
=
oid
.
substring
(
start
);
length
=
oid
.
length
()
-
start
;
}
else
{
comp
=
oid
.
substring
(
start
,
end
);
length
=
end
-
start
;
}
if
(
values
[
0
]
<
2
&&
values
[
1
]
>
maxSecondComponent
)
{
if
(
length
>
9
)
{
throw
new
IOException
(
"ObjectIdentifier() -- "
+
BigInteger
bignum
=
new
BigInteger
(
comp
);
"Second oid component is invalid "
);
if
(
count
==
0
)
{
checkFirstComponent
(
bignum
);
first
=
bignum
.
intValue
();
}
else
{
if
(
count
==
1
)
{
checkSecondComponent
(
first
,
bignum
);
bignum
=
bignum
.
add
(
BigInteger
.
valueOf
(
40
*
first
));
}
else
{
checkOtherComponent
(
count
,
bignum
);
}
pos
+=
pack7Oid
(
bignum
,
tmp
,
pos
);
}
}
else
{
int
num
=
Integer
.
parseInt
(
comp
);
if
(
count
==
0
)
{
checkFirstComponent
(
num
);
first
=
num
;
}
else
{
if
(
count
==
1
)
{
checkSecondComponent
(
first
,
num
);
num
+=
40
*
first
;
}
else
{
checkOtherComponent
(
count
,
num
);
}
pos
+=
pack7Oid
(
num
,
tmp
,
pos
);
}
}
start
=
end
+
1
;
count
++;
}
while
(
end
!=
-
1
);
checkCount
(
count
);
encoding
=
new
byte
[
pos
];
System
.
arraycopy
(
tmp
,
0
,
encoding
,
0
,
pos
);
this
.
stringForm
=
oid
;
}
catch
(
IOException
ioe
)
{
// already detected by checkXXX
throw
ioe
;
}
catch
(
Exception
e
)
{
throw
new
IOException
(
"ObjectIdentifier() -- Invalid format: "
+
e
.
toString
(),
e
);
}
}
}
}
/**
/**
* Construct
s an object ID from an array of integers. This
* Construct
or, from an array of integers.
*
is used to construct constant object IDs
.
*
Validity check included
.
*/
*/
public
ObjectIdentifier
(
int
values
[])
throws
IOException
public
ObjectIdentifier
(
int
values
[])
throws
IOException
{
{
checkValidOid
(
values
,
values
.
length
);
checkCount
(
values
.
length
);
components
=
values
.
clone
();
checkFirstComponent
(
values
[
0
]);
componentLen
=
values
.
length
;
checkSecondComponent
(
values
[
0
],
values
[
1
]);
for
(
int
i
=
2
;
i
<
values
.
length
;
i
++)
checkOtherComponent
(
i
,
values
[
i
]);
init
(
values
,
values
.
length
);
}
}
/**
/**
* Constructs an object ID from an ASN.1 encoded input stream.
* Constructor, from an ASN.1 encoded input stream.
* Validity check NOT included.
* The encoding of the ID in the stream uses "DER", a BER/1 subset.
* The encoding of the ID in the stream uses "DER", a BER/1 subset.
* In this case, that means a triple { typeId, length, data }.
* In this case, that means a triple { typeId, length, data }.
*
*
...
@@ -152,8 +234,7 @@ class ObjectIdentifier implements Serializable
...
@@ -152,8 +234,7 @@ class ObjectIdentifier implements Serializable
* @param in DER-encoded data holding an object ID
* @param in DER-encoded data holding an object ID
* @exception IOException indicates a decoding error
* @exception IOException indicates a decoding error
*/
*/
public
ObjectIdentifier
(
DerInputStream
in
)
public
ObjectIdentifier
(
DerInputStream
in
)
throws
IOException
throws
IOException
{
{
byte
type_id
;
byte
type_id
;
int
bufferEnd
;
int
bufferEnd
;
...
@@ -174,215 +255,67 @@ class ObjectIdentifier implements Serializable
...
@@ -174,215 +255,67 @@ class ObjectIdentifier implements Serializable
+
" (tag = "
+
type_id
+
")"
+
" (tag = "
+
type_id
+
")"
);
);
bufferEnd
=
in
.
available
()
-
in
.
getLength
()
-
1
;
encoding
=
new
byte
[
in
.
getLength
()];
if
(
bufferEnd
<
0
)
in
.
getBytes
(
encoding
);
throw
new
IOException
(
check
(
encoding
);
"ObjectIdentifier() -- not enough data"
);
initFromEncoding
(
in
,
bufferEnd
);
}
}
/*
/*
* Build the OID from the rest of a DER input buffer; the tag
* Constructor, from the rest of a DER input buffer;
* and length have been removed/verified
* the tag and length have been removed/verified
* Validity check NOT included.
*/
*/
ObjectIdentifier
(
DerInputBuffer
buf
)
throws
IOException
ObjectIdentifier
(
DerInputBuffer
buf
)
throws
IOException
{
{
initFromEncoding
(
new
DerInputStream
(
buf
),
0
);
DerInputStream
in
=
new
DerInputStream
(
buf
);
encoding
=
new
byte
[
in
.
available
()];
in
.
getBytes
(
encoding
);
check
(
encoding
);
}
}
/**
private
void
init
(
int
[]
components
,
int
length
)
{
* Private constructor for use by newInternal(). Dummy argument
int
pos
=
0
;
* to avoid clash with the public constructor.
byte
[]
tmp
=
new
byte
[
length
*
5
+
1
];
// +1 for empty input
*/
private
ObjectIdentifier
(
int
[]
components
,
boolean
dummy
)
{
if
(
components
[
1
]
<
Integer
.
MAX_VALUE
-
components
[
0
]*
40
)
this
.
components
=
components
;
pos
+=
pack7Oid
(
components
[
0
]*
40
+
components
[
1
],
tmp
,
pos
);
this
.
componentLen
=
components
.
length
;
else
{
BigInteger
big
=
BigInteger
.
valueOf
(
components
[
1
]);
big
=
big
.
add
(
BigInteger
.
valueOf
(
components
[
0
]*
40
));
pos
+=
pack7Oid
(
big
,
tmp
,
pos
);
}
for
(
int
i
=
2
;
i
<
length
;
i
++)
{
pos
+=
pack7Oid
(
components
[
i
],
tmp
,
pos
);
}
encoding
=
new
byte
[
pos
];
System
.
arraycopy
(
tmp
,
0
,
encoding
,
0
,
pos
);
}
}
/**
/**
* Create a new ObjectIdentifier for internal use. The values are
* This method is kept for compatibility reasons. The new implementation
* does the check and conversion. All around the JDK, the method is called
* in static blocks to initialize pre-defined ObjectIdentifieies. No
* obvious performance hurt will be made after this change.
*
* Old doc: Create a new ObjectIdentifier for internal use. The values are
* neither checked nor cloned.
* neither checked nor cloned.
*/
*/
public
static
ObjectIdentifier
newInternal
(
int
[]
values
)
{
public
static
ObjectIdentifier
newInternal
(
int
[]
values
)
{
return
new
ObjectIdentifier
(
values
,
true
);
try
{
}
return
new
ObjectIdentifier
(
values
);
}
catch
(
IOException
ex
)
{
/*
throw
new
RuntimeException
(
ex
);
* Helper function -- get the OID from a stream, after tag and
// Should not happen, internal calls always uses legal values.
* length are verified.
*/
private
void
initFromEncoding
(
DerInputStream
in
,
int
bufferEnd
)
throws
IOException
{
/*
* Now get the components ("sub IDs") one at a time. We fill a
* temporary buffer, resizing it as needed.
*/
int
component
;
boolean
first_subid
=
true
;
for
(
components
=
new
int
[
allocationQuantum
],
componentLen
=
0
;
in
.
available
()
>
bufferEnd
;
)
{
component
=
getComponent
(
in
);
if
(
component
<
0
)
{
throw
new
IOException
(
"ObjectIdentifier() -- "
+
"component values must be nonnegative"
);
}
if
(
first_subid
)
{
int
X
,
Y
;
/*
* NOTE: the allocation quantum is large enough that we know
* we don't have to reallocate here!
*/
if
(
component
<
40
)
X
=
0
;
else
if
(
component
<
80
)
X
=
1
;
else
X
=
2
;
Y
=
component
-
(
X
*
40
);
components
[
0
]
=
X
;
components
[
1
]
=
Y
;
componentLen
=
2
;
first_subid
=
false
;
}
else
{
/*
* Other components are encoded less exotically. The only
* potential trouble is the need to grow the array.
*/
if
(
componentLen
>=
components
.
length
)
{
int
tmp_components
[];
tmp_components
=
new
int
[
components
.
length
+
allocationQuantum
];
System
.
arraycopy
(
components
,
0
,
tmp_components
,
0
,
components
.
length
);
components
=
tmp_components
;
}
components
[
componentLen
++]
=
component
;
}
}
checkValidOid
(
components
,
componentLen
);
/*
* Final sanity check -- if we didn't use exactly the number of bytes
* specified, something's quite wrong.
*/
if
(
in
.
available
()
!=
bufferEnd
)
{
throw
new
IOException
(
"ObjectIdentifier() -- malformed input data"
);
}
}
}
}
/*
/*
* n.b. the only public interface is DerOutputStream.putOID()
* n.b. the only public interface is DerOutputStream.putOID()
*/
*/
void
encode
(
DerOutputStream
out
)
throws
IOException
void
encode
(
DerOutputStream
out
)
throws
IOException
{
{
DerOutputStream
bytes
=
new
DerOutputStream
();
out
.
write
(
DerValue
.
tag_ObjectId
,
encoding
);
int
i
;
// According to ISO X.660, when the 1st component is 0 or 1, the 2nd
// component is restricted to be less than or equal to 39, thus make
// it small enough to be encoded into one single byte.
if
(
components
[
0
]
<
2
)
{
bytes
.
write
((
components
[
0
]
*
40
)
+
components
[
1
]);
}
else
{
putComponent
(
bytes
,
(
components
[
0
]
*
40
)
+
components
[
1
]);
}
for
(
i
=
2
;
i
<
componentLen
;
i
++)
putComponent
(
bytes
,
components
[
i
]);
/*
* Now that we've constructed the component, encode
* it in the stream we were given.
*/
out
.
write
(
DerValue
.
tag_ObjectId
,
bytes
);
}
/*
* Tricky OID component parsing technique ... note that one bit
* per octet is lost, this returns at most 28 bits of component.
* Also, notice this parses in big-endian format.
*/
private
static
int
getComponent
(
DerInputStream
in
)
throws
IOException
{
int
retval
,
i
,
tmp
;
for
(
i
=
0
,
retval
=
0
;
i
<
4
;
i
++)
{
retval
<<=
7
;
tmp
=
in
.
getByte
();
retval
|=
(
tmp
&
0x07f
);
if
((
tmp
&
0x080
)
==
0
)
return
retval
;
}
throw
new
IOException
(
"ObjectIdentifier() -- component value too big"
);
}
/*
* Reverse of the above routine. Notice it needs to emit in
* big-endian form, so it buffers the output until it's ready.
* (Minimum length encoding is a DER requirement.)
*/
private
static
void
putComponent
(
DerOutputStream
out
,
int
val
)
throws
IOException
{
int
i
;
// TODO: val must be <128*128*128*128 here, otherwise, 4 bytes is not
// enough to hold it. Will address this later.
byte
buf
[]
=
new
byte
[
4
]
;
for
(
i
=
0
;
i
<
4
;
i
++)
{
buf
[
i
]
=
(
byte
)
(
val
&
0x07f
);
val
>>>=
7
;
if
(
val
==
0
)
break
;
}
for
(
;
i
>
0
;
--
i
)
out
.
write
(
buf
[
i
]
|
0x080
);
out
.
write
(
buf
[
0
]);
}
// XXX this API should probably facilitate the JDK sort utility
/**
* Compares this identifier with another, for sorting purposes.
* An identifier does not precede itself.
*
* @param other identifer that may precede this one.
* @return true iff <em>other</em> precedes this one
* in a particular sorting order.
*/
public
boolean
precedes
(
ObjectIdentifier
other
)
{
int
i
;
// shorter IDs go first
if
(
other
==
this
||
componentLen
<
other
.
componentLen
)
return
false
;
if
(
other
.
componentLen
<
componentLen
)
return
true
;
// for each component, the lesser component goes first
for
(
i
=
0
;
i
<
componentLen
;
i
++)
{
if
(
other
.
components
[
i
]
<
components
[
i
])
return
true
;
}
// identical IDs don't precede each other
return
false
;
}
}
/**
/**
...
@@ -398,6 +331,7 @@ class ObjectIdentifier implements Serializable
...
@@ -398,6 +331,7 @@ class ObjectIdentifier implements Serializable
*
*
* @return true iff the names are identical.
* @return true iff the names are identical.
*/
*/
@Override
public
boolean
equals
(
Object
obj
)
{
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
{
if
(
this
==
obj
)
{
return
true
;
return
true
;
...
@@ -406,23 +340,71 @@ class ObjectIdentifier implements Serializable
...
@@ -406,23 +340,71 @@ class ObjectIdentifier implements Serializable
return
false
;
return
false
;
}
}
ObjectIdentifier
other
=
(
ObjectIdentifier
)
obj
;
ObjectIdentifier
other
=
(
ObjectIdentifier
)
obj
;
if
(
componentLen
!=
other
.
componentLen
)
{
return
Arrays
.
equals
(
encoding
,
other
.
encoding
);
return
false
;
}
for
(
int
i
=
0
;
i
<
componentLen
;
i
++)
{
if
(
components
[
i
]
!=
other
.
components
[
i
])
{
return
false
;
}
}
return
true
;
}
}
@Override
public
int
hashCode
()
{
public
int
hashCode
()
{
int
h
=
componentLen
;
return
Arrays
.
hashCode
(
encoding
);
for
(
int
i
=
0
;
i
<
componentLen
;
i
++)
{
}
h
+=
components
[
i
]
*
37
;
/**
* Private helper method for serialization. To be compatible with old
* versions of JDK.
* @return components in an int array, if all the components are less than
* Integer.MAX_VALUE. Otherwise, null.
*/
private
int
[]
toIntArray
()
{
int
length
=
encoding
.
length
;
int
[]
result
=
new
int
[
20
];
int
which
=
0
;
int
fromPos
=
0
;
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
if
((
encoding
[
i
]
&
0x80
)
==
0
)
{
// one section [fromPos..i]
if
(
i
-
fromPos
+
1
>
4
)
{
BigInteger
big
=
new
BigInteger
(
pack
(
encoding
,
fromPos
,
i
-
fromPos
+
1
,
7
,
8
));
if
(
fromPos
==
0
)
{
result
[
which
++]
=
2
;
BigInteger
second
=
big
.
subtract
(
BigInteger
.
valueOf
(
80
));
if
(
second
.
compareTo
(
BigInteger
.
valueOf
(
Integer
.
MAX_VALUE
))
==
1
)
{
return
null
;
}
else
{
result
[
which
++]
=
second
.
intValue
();
}
}
else
{
if
(
big
.
compareTo
(
BigInteger
.
valueOf
(
Integer
.
MAX_VALUE
))
==
1
)
{
return
null
;
}
else
{
result
[
which
++]
=
big
.
intValue
();
}
}
}
else
{
int
retval
=
0
;
for
(
int
j
=
fromPos
;
j
<=
i
;
j
++)
{
retval
<<=
7
;
byte
tmp
=
encoding
[
j
];
retval
|=
(
tmp
&
0x07f
);
}
if
(
fromPos
==
0
)
{
if
(
retval
<
80
)
{
result
[
which
++]
=
retval
/
40
;
result
[
which
++]
=
retval
%
40
;
}
else
{
result
[
which
++]
=
2
;
result
[
which
++]
=
retval
-
80
;
}
}
else
{
result
[
which
++]
=
retval
;
}
}
fromPos
=
i
+
1
;
}
if
(
which
>=
result
.
length
)
{
result
=
Arrays
.
copyOf
(
result
,
which
+
10
);
}
}
}
return
h
;
return
Arrays
.
copyOf
(
result
,
which
)
;
}
}
/**
/**
...
@@ -431,15 +413,52 @@ class ObjectIdentifier implements Serializable
...
@@ -431,15 +413,52 @@ class ObjectIdentifier implements Serializable
* user-friendly descriptive strings, since those strings
* user-friendly descriptive strings, since those strings
* will not be understood everywhere.
* will not be understood everywhere.
*/
*/
@Override
public
String
toString
()
{
public
String
toString
()
{
String
s
=
stringForm
;
String
s
=
stringForm
;
if
(
s
==
null
)
{
if
(
s
==
null
)
{
StringBuffer
sb
=
new
StringBuffer
(
componentLen
*
4
);
int
length
=
encoding
.
length
;
for
(
int
i
=
0
;
i
<
componentLen
;
i
++)
{
StringBuffer
sb
=
new
StringBuffer
(
length
*
4
);
if
(
i
!=
0
)
{
sb
.
append
(
'.'
);
int
fromPos
=
0
;
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
if
((
encoding
[
i
]
&
0x80
)
==
0
)
{
// one section [fromPos..i]
if
(
fromPos
!=
0
)
{
// not the first segment
sb
.
append
(
'.'
);
}
if
(
i
-
fromPos
+
1
>
4
)
{
// maybe big integer
BigInteger
big
=
new
BigInteger
(
pack
(
encoding
,
fromPos
,
i
-
fromPos
+
1
,
7
,
8
));
if
(
fromPos
==
0
)
{
// first section encoded with more than 4 bytes,
// must be 2.something
sb
.
append
(
"2."
);
sb
.
append
(
big
.
subtract
(
BigInteger
.
valueOf
(
80
)));
}
else
{
sb
.
append
(
big
);
}
}
else
{
// small integer
int
retval
=
0
;
for
(
int
j
=
fromPos
;
j
<=
i
;
j
++)
{
retval
<<=
7
;
byte
tmp
=
encoding
[
j
];
retval
|=
(
tmp
&
0x07f
);
}
if
(
fromPos
==
0
)
{
if
(
retval
<
80
)
{
sb
.
append
(
retval
/
40
);
sb
.
append
(
'.'
);
sb
.
append
(
retval
%
40
);
}
else
{
sb
.
append
(
"2."
);
sb
.
append
(
retval
-
80
);
}
}
else
{
sb
.
append
(
retval
);
}
}
fromPos
=
i
+
1
;
}
}
sb
.
append
(
components
[
i
]);
}
}
s
=
sb
.
toString
();
s
=
sb
.
toString
();
stringForm
=
s
;
stringForm
=
s
;
...
@@ -447,15 +466,197 @@ class ObjectIdentifier implements Serializable
...
@@ -447,15 +466,197 @@ class ObjectIdentifier implements Serializable
return
s
;
return
s
;
}
}
/*
/**
* To simplify, we assume no individual component of an object ID is
* Repack all bits from input to output. On the both sides, only a portion
* larger than 32 bits. Then we represent the path from the root as
* (from the least significant bit) of the 8 bits in a byte is used. This
* an array that's (usually) only filled at the beginning.
* number is defined as the number of useful bits (NUB) for the array. All the
* used bits from the input byte array and repacked into the output in the
* exactly same order. The output bits are aligned so that the final bit of
* the input (the least significant bit in the last byte), when repacked as
* the final bit of the output, is still at the least significant position.
* Zeroes will be padded on the left side of the first output byte if
* necessary. All unused bits in the output are also zeroed.
*
* For example: if the input is 01001100 with NUB 8, the output which
* has a NUB 6 will look like:
* 00000001 00001100
* The first 2 bits of the output bytes are unused bits. The other bits
* turn out to be 000001 001100. While the 8 bits on the right are from
* the input, the left 4 zeroes are padded to fill the 6 bits space.
*
* @param in the input byte array
* @param ioffset start point inside <code>in</code>
* @param ilength number of bytes to repack
* @param iw NUB for input
* @param ow NUB for output
* @return the repacked bytes
*/
*/
private
int
components
[];
// path from root
private
static
byte
[]
pack
(
byte
[]
in
,
int
ioffset
,
int
ilength
,
int
iw
,
int
ow
)
{
private
int
componentLen
;
// how much is used.
assert
(
iw
>
0
&&
iw
<=
8
):
"input NUB must be between 1 and 8"
;
assert
(
ow
>
0
&&
ow
<=
8
):
"output NUB must be between 1 and 8"
;
private
transient
volatile
String
stringForm
;
if
(
iw
==
ow
)
{
return
in
.
clone
();
}
int
bits
=
ilength
*
iw
;
// number of all used bits
byte
[]
out
=
new
byte
[(
bits
+
ow
-
1
)/
ow
];
// starting from the 0th bit in the input
int
ipos
=
0
;
// the number of padding 0's needed in the output, skip them
int
opos
=
(
bits
+
ow
-
1
)/
ow
*
ow
-
bits
;
private
static
final
int
allocationQuantum
=
5
;
// >= 2
while
(
ipos
<
bits
)
{
int
count
=
iw
-
ipos
%
iw
;
// unpacked bits in current input byte
if
(
count
>
ow
-
opos
%
ow
)
{
// free space available in output byte
count
=
ow
-
opos
%
ow
;
// choose the smaller number
}
// and move them!
out
[
opos
/
ow
]
|=
// paste!
(((
in
[
ioffset
+
ipos
/
iw
]+
256
)
// locate the byte (+256 so that it's never negative)
>>
(
iw
-
ipos
%
iw
-
count
))
// move to the end of a byte
&
((
1
<<
(
count
))-
1
))
// zero out all other bits
<<
(
ow
-
opos
%
ow
-
count
);
// move to the output position
ipos
+=
count
;
// advance
opos
+=
count
;
// advance
}
return
out
;
}
/**
* Repack from NUB 8 to a NUB 7 OID sub-identifier, remove all
* unnecessary 0 headings, set the first bit of all non-tail
* output bytes to 1 (as ITU-T Rec. X.690 8.19.2 says), and
* paste it into an existing byte array.
* @param out the existing array to be pasted into
* @param ooffset the starting position to paste
* @return the number of bytes pasted
*/
private
static
int
pack7Oid
(
byte
[]
in
,
int
ioffset
,
int
ilength
,
byte
[]
out
,
int
ooffset
)
{
byte
[]
pack
=
pack
(
in
,
ioffset
,
ilength
,
8
,
7
);
int
firstNonZero
=
pack
.
length
-
1
;
// paste at least one byte
for
(
int
i
=
pack
.
length
-
2
;
i
>=
0
;
i
--)
{
if
(
pack
[
i
]
!=
0
)
{
firstNonZero
=
i
;
}
pack
[
i
]
|=
0x80
;
}
System
.
arraycopy
(
pack
,
firstNonZero
,
out
,
ooffset
,
pack
.
length
-
firstNonZero
);
return
pack
.
length
-
firstNonZero
;
}
/**
* Repack from NUB 7 to NUB 8, remove all unnecessary 0
* headings, and paste it into an existing byte array.
* @param out the existing array to be pasted into
* @param ooffset the starting position to paste
* @return the number of bytes pasted
*/
private
static
int
pack8
(
byte
[]
in
,
int
ioffset
,
int
ilength
,
byte
[]
out
,
int
ooffset
)
{
byte
[]
pack
=
pack
(
in
,
ioffset
,
ilength
,
7
,
8
);
int
firstNonZero
=
pack
.
length
-
1
;
// paste at least one byte
for
(
int
i
=
pack
.
length
-
2
;
i
>=
0
;
i
--)
{
if
(
pack
[
i
]
!=
0
)
{
firstNonZero
=
i
;
}
}
System
.
arraycopy
(
pack
,
firstNonZero
,
out
,
ooffset
,
pack
.
length
-
firstNonZero
);
return
pack
.
length
-
firstNonZero
;
}
/**
* Pack the int into a OID sub-identifier DER encoding
*/
private
static
int
pack7Oid
(
int
input
,
byte
[]
out
,
int
ooffset
)
{
byte
[]
b
=
new
byte
[
4
];
b
[
0
]
=
(
byte
)(
input
>>
24
);
b
[
1
]
=
(
byte
)(
input
>>
16
);
b
[
2
]
=
(
byte
)(
input
>>
8
);
b
[
3
]
=
(
byte
)(
input
);
return
pack7Oid
(
b
,
0
,
4
,
out
,
ooffset
);
}
/**
* Pack the BigInteger into a OID subidentifier DER encoding
*/
private
static
int
pack7Oid
(
BigInteger
input
,
byte
[]
out
,
int
ooffset
)
{
byte
[]
b
=
input
.
toByteArray
();
return
pack7Oid
(
b
,
0
,
b
.
length
,
out
,
ooffset
);
}
/**
* Private methods to check validity of OID. They must be --
* 1. at least 2 components
* 2. all components must be non-negative
* 3. the first must be 0, 1 or 2
* 4. if the first is 0 or 1, the second must be <40
*/
/**
* Check the DER encoding. Since DER encoding defines that the integer bits
* are unsigned, so there's no need to check the MSB.
*/
private
static
void
check
(
byte
[]
encoding
)
throws
IOException
{
int
length
=
encoding
.
length
;
if
(
length
<
1
||
// too short
(
encoding
[
length
-
1
]
&
0x80
)
!=
0
)
{
// not ended
throw
new
IOException
(
"ObjectIdentifier() -- "
+
"Invalid DER encoding, not ended"
);
}
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
// 0x80 at the beginning of a subidentifier
if
(
encoding
[
i
]
==
(
byte
)
0x80
&&
(
i
==
0
||
(
encoding
[
i
-
1
]
&
0x80
)
==
0
))
{
throw
new
IOException
(
"ObjectIdentifier() -- "
+
"Invalid DER encoding, useless extra octet detected"
);
}
}
}
private
static
void
checkCount
(
int
count
)
throws
IOException
{
if
(
count
<
2
)
{
throw
new
IOException
(
"ObjectIdentifier() -- "
+
"Must be at least two oid components "
);
}
}
private
static
void
checkFirstComponent
(
int
first
)
throws
IOException
{
if
(
first
<
0
||
first
>
2
)
{
throw
new
IOException
(
"ObjectIdentifier() -- "
+
"First oid component is invalid "
);
}
}
private
static
void
checkFirstComponent
(
BigInteger
first
)
throws
IOException
{
if
(
first
.
signum
()
==
-
1
||
first
.
compareTo
(
BigInteger
.
valueOf
(
2
))
==
1
)
{
throw
new
IOException
(
"ObjectIdentifier() -- "
+
"First oid component is invalid "
);
}
}
private
static
void
checkSecondComponent
(
int
first
,
int
second
)
throws
IOException
{
if
(
second
<
0
||
first
!=
2
&&
second
>
39
)
{
throw
new
IOException
(
"ObjectIdentifier() -- "
+
"Second oid component is invalid "
);
}
}
private
static
void
checkSecondComponent
(
int
first
,
BigInteger
second
)
throws
IOException
{
if
(
second
.
signum
()
==
-
1
||
first
!=
2
&&
second
.
compareTo
(
BigInteger
.
valueOf
(
39
))
==
1
)
{
throw
new
IOException
(
"ObjectIdentifier() -- "
+
"Second oid component is invalid "
);
}
}
private
static
void
checkOtherComponent
(
int
i
,
int
num
)
throws
IOException
{
if
(
num
<
0
)
{
throw
new
IOException
(
"ObjectIdentifier() -- "
+
"oid component #"
+
(
i
+
1
)
+
" must be non-negative "
);
}
}
private
static
void
checkOtherComponent
(
int
i
,
BigInteger
num
)
throws
IOException
{
if
(
num
.
signum
()
==
-
1
)
{
throw
new
IOException
(
"ObjectIdentifier() -- "
+
"oid component #"
+
(
i
+
1
)
+
" must be non-negative "
);
}
}
}
}
test/sun/security/util/Oid/OidFormat.java
浏览文件 @
d4ac959d
...
@@ -63,9 +63,22 @@ public class OidFormat {
...
@@ -63,9 +63,22 @@ public class OidFormat {
"1.2.3"
,
"1.2.3445"
,
"1.2.3"
,
"1.2.3445"
,
"1.3.6.1.4.1.42.2.17"
,
"1.3.6.1.4.1.42.2.17"
,
// 4811968: ASN.1 cannot handle huge OID components
// 4811968: ASN.1 cannot handle huge OID components
//"2.16.764.1.3101555394.1.0.100.2.1",
"2.16.764.1.3101555394.1.0.100.2.1"
,
//"1.2.2147483647.4",
"2.2726957624935694386592435"
,
// as huge as possible
//"1.2.268435456.4",
"1.2.777777777777777777"
,
"1.2.888888888888888888.111111111111111.2222222222222.33333333333333333.44444444444444"
,
"1.2."
+
"1111111111111111111111111111111111111111111111111111111111111."
+
"2222222222222222222222222222222222222222222222222222222222222222."
+
"333333333333333333333333333333333333333333333333333333333333333."
+
"4444444444444444444444444444444444444444444444444444444."
+
"55555555555555555555555555555555555555555555555555555555555555555555555."
+
"666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666."
+
"77777777777777777777777777777777777777777777777777777777777777777777777777."
+
"8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888."
+
"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
,
"1.2.2147483647.4"
,
"1.2.268435456.4"
,
};
};
for
(
String
s:
goodOids
)
{
for
(
String
s:
goodOids
)
{
...
...
test/sun/security/util/Oid/S11N.sh
0 → 100644
浏览文件 @
d4ac959d
#
# Copyright 2004-2005 Sun Microsystems, Inc. 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
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
# CA 95054 USA or visit www.sun.com if you need additional information or
# have any questions.
#
# @test
# @bug 4811968
# @summary Serialization compatibility with old versions
# @author Weijun Wang
#
# set a few environment variables so that the shell-script can run stand-alone
# in the source directory
if
[
"
${
TESTSRC
}
"
=
""
]
;
then
TESTSRC
=
"."
fi
if
[
"
${
TESTCLASSES
}
"
=
""
]
;
then
TESTCLASSES
=
"."
fi
if
[
"
${
TESTJAVA
}
"
=
""
]
;
then
echo
"TESTJAVA not set. Test cannot execute."
echo
"FAILED!!!"
exit
1
fi
# set platform-dependent variables
PF
=
""
OS
=
`
uname
-s
`
case
"
$OS
"
in
SunOS
)
FS
=
"/"
ARCH
=
`
isainfo
`
case
"
$ARCH
"
in
sparc
*
)
PF
=
"solaris-sparc"
;;
i[3-6]86
)
PF
=
"solaris-i586"
;;
amd64
*
)
PF
=
"solaris-amd64"
;;
*
)
echo
"Unsupported System: Solaris
${
ARCH
}
"
exit
0
;
;;
esac
;;
Linux
)
ARCH
=
`
uname
-m
`
FS
=
"/"
case
"
$ARCH
"
in
i[3-6]86
)
PF
=
"linux-i586"
;;
amd64
*
)
PF
=
"linux-amd64"
;;
*
)
echo
"Unsupported System: Linux
${
ARCH
}
"
exit
0
;
;;
esac
;;
Windows
*
)
FS
=
"
\\
"
PF
=
"windows-i586"
# 'uname -m' does not give us enough information -
# should rely on $PROCESSOR_IDENTIFIER (as is done in Defs-windows.gmk),
# but JTREG does not pass this env variable when executing a shell script.
#
# execute test program - rely on it to exit if platform unsupported
;;
*
)
echo
"Unsupported System:
${
OS
}
"
exit
0
;
;;
esac
# the test code
${
TESTJAVA
}${
FS
}
bin
${
FS
}
javac
-source
1.3
-target
1.3
-d
.
${
TESTSRC
}${
FS
}
SerialTest.java
||
exit
10
OLDJAVA
=
"
/java/re/j2se/1.6.0/latest/binaries/
${
PF
}
/java/re/j2se/1.5.0/latest/binaries/
${
PF
}
/java/re/j2se/1.4.2/latest/binaries/
${
PF
}
"
SMALL
=
"
0.0
1.1
2.2
1.2.3456
1.2.2147483647.4
1.2.268435456.4
"
HUGE
=
"
2.16.764.1.3101555394.1.0.100.2.1
1.2.2147483648.4
2.3.4444444444444444444444
1.2.888888888888888888.111111111111111.2222222222222.33333333333333333.44444444444444
"
for
oid
in
${
SMALL
}
;
do
echo
${
oid
}
# new ->
${
TESTJAVA
}${
FS
}
bin
${
FS
}
java SerialTest out
${
oid
}
>
tmp.oid.serial
||
exit
1
# -> new
${
TESTJAVA
}${
FS
}
bin
${
FS
}
java SerialTest
in
${
oid
}
< tmp.oid.serial
||
exit
2
for
oldj
in
${
OLDJAVA
}
;
do
if
[
-d
${
oldj
}
]
;
then
echo
${
oldj
}
# -> old
${
oldj
}${
FS
}
bin
${
FS
}
java SerialTest
in
${
oid
}
< tmp.oid.serial
||
exit
3
# old ->
${
oldj
}${
FS
}
bin
${
FS
}
java SerialTest out
${
oid
}
>
tmp.oid.serial.old
||
exit
4
# -> new
${
TESTJAVA
}${
FS
}
bin
${
FS
}
java SerialTest
in
${
oid
}
< tmp.oid.serial.old
||
exit
5
fi
done
done
for
oid
in
${
HUGE
}
;
do
echo
${
oid
}
# new ->
${
TESTJAVA
}${
FS
}
bin
${
FS
}
java SerialTest out
${
oid
}
>
tmp.oid.serial
||
exit
1
# -> new
${
TESTJAVA
}${
FS
}
bin
${
FS
}
java SerialTest
in
${
oid
}
< tmp.oid.serial
||
exit
2
for
oldj
in
${
OLDJAVA
}
;
do
if
[
-d
${
oldj
}
]
;
then
echo
${
oldj
}
# -> old
${
oldj
}${
FS
}
bin
${
FS
}
java SerialTest badin < tmp.oid.serial
||
exit
3
fi
done
done
rm
-f
tmp.oid.serial
rm
-f
tmp.oid.serial.old
rm
-f
SerialTest.class
exit
0
test/sun/security/util/Oid/SerialTest.java
0 → 100644
浏览文件 @
d4ac959d
/*
* Copyright 2004 Sun Microsystems, Inc. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* read S11.sh
*/
import
java.io.*
;
import
sun.security.util.*
;
/**
* Test OID serialization between versions
*
* java SerialTest out oid // write a OID into System.out
* java SerialTest in oid // read from System.in and compare it with oid
* java SerialTest badin // make sure *cannot* read from System.in
*/
class
SerialTest
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
if
(
args
[
0
].
equals
(
"out"
))
out
(
args
[
1
]);
else
if
(
args
[
0
].
equals
(
"in"
))
in
(
args
[
1
]);
else
badin
();
}
static
void
in
(
String
oid
)
throws
Exception
{
ObjectIdentifier
o
=
(
ObjectIdentifier
)
(
new
ObjectInputStream
(
System
.
in
).
readObject
());
if
(!
o
.
toString
().
equals
(
oid
))
throw
new
Exception
(
"Read Fail "
+
o
+
", not "
+
oid
);
}
static
void
badin
()
throws
Exception
{
boolean
pass
=
true
;
try
{
new
ObjectInputStream
(
System
.
in
).
readObject
();
}
catch
(
Exception
e
)
{
pass
=
false
;
}
if
(
pass
)
throw
new
Exception
(
"Should fail but not"
);
}
static
void
out
(
String
oid
)
throws
Exception
{
new
ObjectOutputStream
(
System
.
out
).
writeObject
(
new
ObjectIdentifier
(
oid
));
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录