Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
eb346a3f
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看板
提交
eb346a3f
编写于
4月 11, 2011
作者:
W
weijun
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
7012160: read SF file in signed jar in streaming mode
Reviewed-by: mullan
上级
3d1573d8
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
621 addition
and
376 deletion
+621
-376
src/share/classes/java/util/jar/JarFile.java
src/share/classes/java/util/jar/JarFile.java
+10
-12
src/share/classes/java/util/jar/JarInputStream.java
src/share/classes/java/util/jar/JarInputStream.java
+2
-2
src/share/classes/java/util/jar/JarVerifier.java
src/share/classes/java/util/jar/JarVerifier.java
+56
-168
src/share/classes/sun/security/pkcs/PKCS7.java
src/share/classes/sun/security/pkcs/PKCS7.java
+169
-9
src/share/classes/sun/security/pkcs/SignerInfo.java
src/share/classes/sun/security/pkcs/SignerInfo.java
+14
-126
src/share/classes/sun/security/util/ManifestEntryVerifier.java
...hare/classes/sun/security/util/ManifestEntryVerifier.java
+3
-3
src/share/classes/sun/security/util/SignatureFileManifest.java
...hare/classes/sun/security/util/SignatureFileManifest.java
+251
-0
src/share/classes/sun/security/util/SignatureFileVerifier.java
...hare/classes/sun/security/util/SignatureFileVerifier.java
+116
-56
未找到文件。
src/share/classes/java/util/jar/JarFile.java
浏览文件 @
eb346a3f
...
...
@@ -37,6 +37,7 @@ import java.security.CodeSource;
import
sun.security.action.GetPropertyAction
;
import
sun.security.util.ManifestEntryVerifier
;
import
sun.misc.SharedSecrets
;
import
sun.security.util.SignatureFileVerifier
;
/**
* The <code>JarFile</code> class is used to read the contents of a jar file
...
...
@@ -178,7 +179,7 @@ class JarFile extends ZipFile {
byte
[]
b
=
getBytes
(
manEntry
);
man
=
new
Manifest
(
new
ByteArrayInputStream
(
b
));
if
(!
jvInitialized
)
{
jv
=
new
JarVerifier
(
b
);
jv
=
new
JarVerifier
(
b
,
man
);
}
}
else
{
man
=
new
Manifest
(
super
.
getInputStream
(
manEntry
));
...
...
@@ -297,10 +298,7 @@ class JarFile extends ZipFile {
if
(
names
!=
null
)
{
for
(
int
i
=
0
;
i
<
names
.
length
;
i
++)
{
String
name
=
names
[
i
].
toUpperCase
(
Locale
.
ENGLISH
);
if
(
name
.
endsWith
(
".DSA"
)
||
name
.
endsWith
(
".RSA"
)
||
name
.
endsWith
(
".EC"
)
||
name
.
endsWith
(
".SF"
))
{
if
(
SignatureFileVerifier
.
isBlockOrSF
(
name
))
{
// Assume since we found a signature-related file
// that the jar is signed and that we therefore
// need a JarVerifier and Manifest
...
...
@@ -329,17 +327,17 @@ class JarFile extends ZipFile {
if
(
names
!=
null
)
{
for
(
int
i
=
0
;
i
<
names
.
length
;
i
++)
{
JarEntry
e
=
getJarEntry
(
names
[
i
]);
if
(!
e
.
isDirectory
())
{
if
(!
e
.
isDirectory
()
&&
SignatureFileVerifier
.
isBlock
(
names
[
i
]))
{
if
(
mev
==
null
)
{
mev
=
new
ManifestEntryVerifier
(
getManifestFromReference
());
}
byte
[]
b
=
getBytes
(
e
);
if
(
b
!=
null
&&
b
.
length
>
0
)
{
jv
.
beginEntry
(
e
,
mev
);
jv
.
update
(
b
.
length
,
b
,
0
,
b
.
length
,
mev
);
jv
.
update
(-
1
,
null
,
0
,
0
,
mev
);
}
String
key
=
names
[
i
].
substring
(
0
,
names
[
i
].
lastIndexOf
(
"."
));
jv
.
verifyBlock
(
names
[
i
],
getBytes
(
e
),
super
.
getInputStream
(
getJarEntry
(
key
+
".SF"
)));
}
}
}
...
...
src/share/classes/java/util/jar/JarInputStream.java
浏览文件 @
eb346a3f
/*
* Copyright (c) 1997, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
1
, 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
...
...
@@ -95,7 +95,7 @@ class JarInputStream extends ZipInputStream {
man
.
read
(
new
ByteArrayInputStream
(
bytes
));
closeEntry
();
if
(
doVerify
)
{
jv
=
new
JarVerifier
(
bytes
);
jv
=
new
JarVerifier
(
bytes
,
man
);
mev
=
new
ManifestEntryVerifier
(
man
);
}
return
(
JarEntry
)
super
.
getNextEntry
();
...
...
src/share/classes/java/util/jar/JarVerifier.java
浏览文件 @
eb346a3f
...
...
@@ -48,35 +48,18 @@ class JarVerifier {
/* a table mapping names to code signers, for jar entries that have
had their actual hashes verified */
private
Hashtable
verifiedSigners
;
private
Map
verifiedSigners
;
/* a table mapping names to code signers, for jar entries that have
passed the .SF/.DSA/.EC -> MANIFEST check */
private
Hashtable
sigFileSigners
;
/* a hash table to hold .SF bytes */
private
Hashtable
sigFileData
;
/** "queue" of pending PKCS7 blocks that we couldn't parse
* until we parsed the .SF file */
private
ArrayList
pendingBlocks
;
private
Map
sigFileSigners
;
/* cache of CodeSigner objects */
private
ArrayList
signerCache
;
/* Are we parsing a block? */
private
boolean
parsingBlockOrSF
=
false
;
/* Are we done parsing META-INF entries? */
private
boolean
parsingMeta
=
true
;
/* Are there are files to verify? */
private
boolean
anyToVerify
=
true
;
/* The output stream to use when keeping track of files we are interested
in */
private
ByteArrayOutputStream
baos
;
/** The ManifestDigester object */
private
volatile
ManifestDigester
manDig
;
...
...
@@ -92,20 +75,20 @@ class JarVerifier {
/** collect -DIGEST-MANIFEST values for blacklist */
private
List
manifestDigests
;
public
JarVerifier
(
byte
rawBytes
[])
{
/** The manifest object */
Manifest
man
=
null
;
public
JarVerifier
(
byte
rawBytes
[],
Manifest
man
)
{
this
.
man
=
man
;
manifestRawBytes
=
rawBytes
;
sigFileSigners
=
new
Hashtable
();
verifiedSigners
=
new
Hashtable
();
sigFileData
=
new
Hashtable
(
11
);
pendingBlocks
=
new
ArrayList
();
baos
=
new
ByteArrayOutputStream
();
sigFileSigners
=
new
HashMap
();
verifiedSigners
=
new
HashMap
();
manifestDigests
=
new
ArrayList
();
}
/**
* This method scans to see which entry we're parsing and
* keeps various state information depending on what type of
* file is being parsed.
* This method scans to see which entry we're parsing and keeps
* various state information depending on the file being parsed.
*/
public
void
beginEntry
(
JarEntry
je
,
ManifestEntryVerifier
mev
)
throws
IOException
...
...
@@ -129,30 +112,6 @@ class JarVerifier {
* b. digest mismatch between the actual jar entry and the manifest
*/
if
(
parsingMeta
)
{
String
uname
=
name
.
toUpperCase
(
Locale
.
ENGLISH
);
if
((
uname
.
startsWith
(
"META-INF/"
)
||
uname
.
startsWith
(
"/META-INF/"
)))
{
if
(
je
.
isDirectory
())
{
mev
.
setEntry
(
null
,
je
);
return
;
}
if
(
SignatureFileVerifier
.
isBlockOrSF
(
uname
))
{
/* We parse only DSA, RSA or EC PKCS7 blocks. */
parsingBlockOrSF
=
true
;
baos
.
reset
();
mev
.
setEntry
(
null
,
je
);
}
return
;
}
}
if
(
parsingMeta
)
{
doneWithMeta
();
}
if
(
je
.
isDirectory
())
{
mev
.
setEntry
(
null
,
je
);
return
;
...
...
@@ -188,11 +147,7 @@ class JarVerifier {
throws
IOException
{
if
(
b
!=
-
1
)
{
if
(
parsingBlockOrSF
)
{
baos
.
write
(
b
);
}
else
{
mev
.
update
((
byte
)
b
);
}
mev
.
update
((
byte
)
b
);
}
else
{
processEntry
(
mev
);
}
...
...
@@ -207,11 +162,7 @@ class JarVerifier {
throws
IOException
{
if
(
n
!=
-
1
)
{
if
(
parsingBlockOrSF
)
{
baos
.
write
(
b
,
off
,
n
);
}
else
{
mev
.
update
(
b
,
off
,
n
);
}
mev
.
update
(
b
,
off
,
n
);
}
else
{
processEntry
(
mev
);
}
...
...
@@ -223,101 +174,10 @@ class JarVerifier {
private
void
processEntry
(
ManifestEntryVerifier
mev
)
throws
IOException
{
if
(!
parsingBlockOrSF
)
{
JarEntry
je
=
mev
.
getEntry
();
if
((
je
!=
null
)
&&
(
je
.
signers
==
null
))
{
je
.
signers
=
mev
.
verify
(
verifiedSigners
,
sigFileSigners
);
je
.
certs
=
mapSignersToCertArray
(
je
.
signers
);
}
}
else
{
try
{
parsingBlockOrSF
=
false
;
if
(
debug
!=
null
)
{
debug
.
println
(
"processEntry: processing block"
);
}
String
uname
=
mev
.
getEntry
().
getName
()
.
toUpperCase
(
Locale
.
ENGLISH
);
if
(
uname
.
endsWith
(
".SF"
))
{
String
key
=
uname
.
substring
(
0
,
uname
.
length
()-
3
);
byte
bytes
[]
=
baos
.
toByteArray
();
// add to sigFileData in case future blocks need it
sigFileData
.
put
(
key
,
bytes
);
// check pending blocks, we can now process
// anyone waiting for this .SF file
Iterator
it
=
pendingBlocks
.
iterator
();
while
(
it
.
hasNext
())
{
SignatureFileVerifier
sfv
=
(
SignatureFileVerifier
)
it
.
next
();
if
(
sfv
.
needSignatureFile
(
key
))
{
if
(
debug
!=
null
)
{
debug
.
println
(
"processEntry: processing pending block"
);
}
sfv
.
setSignatureFile
(
bytes
);
sfv
.
process
(
sigFileSigners
,
manifestDigests
);
}
}
return
;
}
// now we are parsing a signature block file
String
key
=
uname
.
substring
(
0
,
uname
.
lastIndexOf
(
"."
));
if
(
signerCache
==
null
)
signerCache
=
new
ArrayList
();
if
(
manDig
==
null
)
{
synchronized
(
manifestRawBytes
)
{
if
(
manDig
==
null
)
{
manDig
=
new
ManifestDigester
(
manifestRawBytes
);
manifestRawBytes
=
null
;
}
}
}
SignatureFileVerifier
sfv
=
new
SignatureFileVerifier
(
signerCache
,
manDig
,
uname
,
baos
.
toByteArray
());
if
(
sfv
.
needSignatureFileBytes
())
{
// see if we have already parsed an external .SF file
byte
[]
bytes
=
(
byte
[])
sigFileData
.
get
(
key
);
if
(
bytes
==
null
)
{
// put this block on queue for later processing
// since we don't have the .SF bytes yet
// (uname, block);
if
(
debug
!=
null
)
{
debug
.
println
(
"adding pending block"
);
}
pendingBlocks
.
add
(
sfv
);
return
;
}
else
{
sfv
.
setSignatureFile
(
bytes
);
}
}
sfv
.
process
(
sigFileSigners
,
manifestDigests
);
}
catch
(
IOException
ioe
)
{
// e.g. sun.security.pkcs.ParsingException
if
(
debug
!=
null
)
debug
.
println
(
"processEntry caught: "
+
ioe
);
// ignore and treat as unsigned
}
catch
(
SignatureException
se
)
{
if
(
debug
!=
null
)
debug
.
println
(
"processEntry caught: "
+
se
);
// ignore and treat as unsigned
}
catch
(
NoSuchAlgorithmException
nsae
)
{
if
(
debug
!=
null
)
debug
.
println
(
"processEntry caught: "
+
nsae
);
// ignore and treat as unsigned
}
catch
(
CertificateException
ce
)
{
if
(
debug
!=
null
)
debug
.
println
(
"processEntry caught: "
+
ce
);
// ignore and treat as unsigned
}
JarEntry
je
=
mev
.
getEntry
();
if
((
je
!=
null
)
&&
(
je
.
signers
==
null
))
{
je
.
signers
=
mev
.
verify
(
verifiedSigners
,
sigFileSigners
);
je
.
certs
=
mapSignersToCertArray
(
je
.
signers
);
}
}
...
...
@@ -354,15 +214,15 @@ class JarVerifier {
* Force a read of the entry data to generate the
* verification hash.
*/
try
{
InputStream
s
=
jar
.
getInputStream
(
entry
);
try
(
InputStream
s
=
jar
.
getInputStream
(
entry
))
{
byte
[]
buffer
=
new
byte
[
1024
];
int
n
=
buffer
.
length
;
while
(
n
!=
-
1
)
{
n
=
s
.
read
(
buffer
,
0
,
buffer
.
length
);
}
s
.
close
();
}
catch
(
IOException
e
)
{
// Ignore. When an exception is thrown, code signer
// will not be assigned.
}
}
return
getCodeSigners
(
name
);
...
...
@@ -408,11 +268,7 @@ class JarVerifier {
*/
void
doneWithMeta
()
{
parsingMeta
=
false
;
anyToVerify
=
!
sigFileSigners
.
isEmpty
();
baos
=
null
;
sigFileData
=
null
;
pendingBlocks
=
null
;
signerCache
=
null
;
manDig
=
null
;
// MANIFEST.MF is always treated as signed and verified,
...
...
@@ -423,6 +279,41 @@ class JarVerifier {
}
}
/**
* Verifies a PKCS7 SignedData block
* @param key name of block
* @param block the pkcs7 file
* @param ins the clear data
*/
void
verifyBlock
(
String
key
,
byte
[]
block
,
InputStream
ins
)
{
try
{
if
(
signerCache
==
null
)
signerCache
=
new
ArrayList
();
if
(
manDig
==
null
)
{
synchronized
(
manifestRawBytes
)
{
if
(
manDig
==
null
)
{
manDig
=
new
ManifestDigester
(
manifestRawBytes
);
manifestRawBytes
=
null
;
}
}
}
SignatureFileVerifier
sfv
=
new
SignatureFileVerifier
(
signerCache
,
man
,
manDig
,
key
,
block
);
if
(
sfv
.
needSignatureFile
())
{
// see if we have already parsed an external .SF file
sfv
.
setSignatureFile
(
ins
);
}
sfv
.
process
(
sigFileSigners
,
manifestDigests
);
}
catch
(
Exception
e
)
{
if
(
debug
!=
null
)
{
e
.
printStackTrace
();
}
}
}
static
class
VerifierStream
extends
java
.
io
.
InputStream
{
private
InputStream
is
;
...
...
@@ -553,10 +444,7 @@ class JarVerifier {
* but this handles a CodeSource of any type, just in case.
*/
CodeSource
[]
sources
=
mapSignersToCodeSources
(
cs
.
getLocation
(),
getJarCodeSigners
(),
true
);
List
sourceList
=
new
ArrayList
();
for
(
int
i
=
0
;
i
<
sources
.
length
;
i
++)
{
sourceList
.
add
(
sources
[
i
]);
}
List
sourceList
=
Arrays
.
asList
(
sources
);
int
j
=
sourceList
.
indexOf
(
cs
);
if
(
j
!=
-
1
)
{
CodeSigner
[]
match
;
...
...
src/share/classes/sun/security/pkcs/PKCS7.java
浏览文件 @
eb346a3f
/*
* Copyright (c) 1996, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 201
1
, 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
...
...
@@ -38,6 +38,7 @@ import java.security.*;
import
sun.security.util.*
;
import
sun.security.x509.AlgorithmId
;
import
sun.security.x509.CertificateIssuerName
;
import
sun.security.x509.KeyUsageExtension
;
import
sun.security.x509.X509CertImpl
;
import
sun.security.x509.X509CertInfo
;
import
sun.security.x509.X509CRLImpl
;
...
...
@@ -492,7 +493,7 @@ public class PKCS7 {
// CRLs (optional)
if
(
crls
!=
null
&&
crls
.
length
!=
0
)
{
// cast to X509CRLImpl[] since X509CRLImpl implements DerEncoder
Set
<
X509CRLImpl
>
implCRLs
=
new
HashSet
<
X509CRLImpl
>(
crls
.
length
);
Set
<
X509CRLImpl
>
implCRLs
=
new
HashSet
<>(
crls
.
length
);
for
(
X509CRL
crl:
crls
)
{
if
(
crl
instanceof
X509CRLImpl
)
implCRLs
.
add
((
X509CRLImpl
)
crl
);
...
...
@@ -529,6 +530,168 @@ public class PKCS7 {
block
.
encode
(
out
);
}
/**
* Verifying signed data using an external chunked data source.
*/
public
static
class
PKCS7Verifier
{
private
final
SignerInfo
si
;
// Signer to verify
private
final
MessageDigest
md
;
// MessageDigest object for chunks
private
final
Signature
sig
;
// Signature object for chunks
private
PKCS7Verifier
(
SignerInfo
si
,
MessageDigest
md
,
Signature
sig
)
{
this
.
si
=
si
;
this
.
md
=
md
;
this
.
sig
=
sig
;
}
public
static
PKCS7Verifier
from
(
PKCS7
block
,
SignerInfo
si
)
throws
SignatureException
,
NoSuchAlgorithmException
{
try
{
MessageDigest
md
=
null
;
Signature
sig
;
ContentInfo
content
=
block
.
getContentInfo
();
String
digestAlgname
=
si
.
getDigestAlgorithmId
().
getName
();
// if there are authenticate attributes, feed data chunks to
// the message digest. In this case, pv.md is not null
if
(
si
.
authenticatedAttributes
!=
null
)
{
// first, check content type
ObjectIdentifier
contentType
=
(
ObjectIdentifier
)
si
.
authenticatedAttributes
.
getAttributeValue
(
PKCS9Attribute
.
CONTENT_TYPE_OID
);
if
(
contentType
==
null
||
!
contentType
.
equals
(
content
.
contentType
))
return
null
;
// contentType does not match, bad SignerInfo
// now, check message digest
byte
[]
messageDigest
=
(
byte
[])
si
.
authenticatedAttributes
.
getAttributeValue
(
PKCS9Attribute
.
MESSAGE_DIGEST_OID
);
if
(
messageDigest
==
null
)
// fail if there is no message digest
return
null
;
md
=
MessageDigest
.
getInstance
(
digestAlgname
);
}
// put together digest algorithm and encryption algorithm
// to form signing algorithm
String
encryptionAlgname
=
si
.
getDigestEncryptionAlgorithmId
().
getName
();
// Workaround: sometimes the encryptionAlgname is actually
// a signature name
String
tmp
=
AlgorithmId
.
getEncAlgFromSigAlg
(
encryptionAlgname
);
if
(
tmp
!=
null
)
encryptionAlgname
=
tmp
;
String
algname
=
AlgorithmId
.
makeSigAlg
(
digestAlgname
,
encryptionAlgname
);
sig
=
Signature
.
getInstance
(
algname
);
X509Certificate
cert
=
si
.
getCertificate
(
block
);
if
(
cert
==
null
)
{
return
null
;
}
if
(
cert
.
hasUnsupportedCriticalExtension
())
{
throw
new
SignatureException
(
"Certificate has unsupported "
+
"critical extension(s)"
);
}
// Make sure that if the usage of the key in the certificate is
// restricted, it can be used for digital signatures.
// XXX We may want to check for additional extensions in the
// future.
boolean
[]
keyUsageBits
=
cert
.
getKeyUsage
();
if
(
keyUsageBits
!=
null
)
{
KeyUsageExtension
keyUsage
;
try
{
// We don't care whether or not this extension was marked
// critical in the certificate.
// We're interested only in its value (i.e., the bits set)
// and treat the extension as critical.
keyUsage
=
new
KeyUsageExtension
(
keyUsageBits
);
}
catch
(
IOException
ioe
)
{
throw
new
SignatureException
(
"Failed to parse keyUsage "
+
"extension"
);
}
boolean
digSigAllowed
=
((
Boolean
)
keyUsage
.
get
(
KeyUsageExtension
.
DIGITAL_SIGNATURE
)).
booleanValue
();
boolean
nonRepuAllowed
=
((
Boolean
)
keyUsage
.
get
(
KeyUsageExtension
.
NON_REPUDIATION
)).
booleanValue
();
if
(!
digSigAllowed
&&
!
nonRepuAllowed
)
{
throw
new
SignatureException
(
"Key usage restricted: "
+
"cannot be used for "
+
"digital signatures"
);
}
}
PublicKey
key
=
cert
.
getPublicKey
();
sig
.
initVerify
(
key
);
return
new
PKCS7Verifier
(
si
,
md
,
sig
);
}
catch
(
IOException
e
)
{
throw
new
SignatureException
(
"IO error verifying signature:\n"
+
e
.
getMessage
());
}
catch
(
InvalidKeyException
e
)
{
throw
new
SignatureException
(
"InvalidKey: "
+
e
.
getMessage
());
}
}
public
void
update
(
byte
[]
data
,
int
off
,
int
end
)
throws
SignatureException
{
if
(
md
!=
null
)
{
md
.
update
(
data
,
off
,
end
-
off
);
}
else
{
sig
.
update
(
data
,
off
,
end
-
off
);
}
}
public
SignerInfo
verify
()
throws
SignatureException
{
try
{
// if there are authenticate attributes, get the message
// digest and compare it with the digest of data
if
(
md
!=
null
)
{
// now, check message digest
byte
[]
messageDigest
=
(
byte
[])
si
.
authenticatedAttributes
.
getAttributeValue
(
PKCS9Attribute
.
MESSAGE_DIGEST_OID
);
byte
[]
computedMessageDigest
=
md
.
digest
();
if
(!
MessageDigest
.
isEqual
(
messageDigest
,
computedMessageDigest
))
{
return
null
;
}
// message digest attribute matched
// digest of original data
// the data actually signed is the DER encoding of
// the authenticated attributes (tagged with
// the "SET OF" tag, not 0xA0).
byte
[]
dataSigned
=
si
.
authenticatedAttributes
.
getDerEncoding
();
sig
.
update
(
dataSigned
);
}
if
(
sig
.
verify
(
si
.
getEncryptedDigest
()))
{
return
si
;
}
}
catch
(
IOException
e
)
{
throw
new
SignatureException
(
"IO error verifying signature:\n"
+
e
.
getMessage
());
}
return
null
;
}
}
/**
* This verifies a given SignerInfo.
*
...
...
@@ -554,19 +717,16 @@ public class PKCS7 {
public
SignerInfo
[]
verify
(
byte
[]
bytes
)
throws
NoSuchAlgorithmException
,
SignatureException
{
Vector
<
SignerInfo
>
intResult
=
new
Vector
<
SignerInfo
>();
List
<
SignerInfo
>
intResult
=
new
ArrayList
<
>();
for
(
int
i
=
0
;
i
<
signerInfos
.
length
;
i
++)
{
SignerInfo
signerInfo
=
verify
(
signerInfos
[
i
],
bytes
);
if
(
signerInfo
!=
null
)
{
intResult
.
add
Element
(
signerInfo
);
intResult
.
add
(
signerInfo
);
}
}
if
(
intResult
.
size
()
!=
0
)
{
SignerInfo
[]
result
=
new
SignerInfo
[
intResult
.
size
()];
intResult
.
copyInto
(
result
);
return
result
;
if
(!
intResult
.
isEmpty
())
{
return
intResult
.
toArray
(
new
SignerInfo
[
intResult
.
size
()]);
}
return
null
;
}
...
...
src/share/classes/sun/security/pkcs/SignerInfo.java
浏览文件 @
eb346a3f
/*
* Copyright (c) 1996, 20
09
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 20
11
, 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
...
...
@@ -230,7 +230,7 @@ public class SignerInfo implements DerEncoder {
if
(
userCert
==
null
)
return
null
;
ArrayList
<
X509Certificate
>
certList
=
new
ArrayList
<
X509Certificate
>();
ArrayList
<
X509Certificate
>
certList
=
new
ArrayList
<>();
certList
.
add
(
userCert
);
X509Certificate
[]
pkcsCerts
=
block
.
getCertificates
();
...
...
@@ -276,132 +276,20 @@ public class SignerInfo implements DerEncoder {
/* Returns null if verify fails, this signerInfo if
verify succeeds. */
SignerInfo
verify
(
PKCS7
block
,
byte
[]
data
)
throws
NoSuchAlgorithmException
,
SignatureException
{
try
{
ContentInfo
content
=
block
.
getContentInfo
();
if
(
data
==
null
)
{
data
=
content
.
getContentBytes
();
}
String
digestAlgname
=
getDigestAlgorithmId
().
getName
();
byte
[]
dataSigned
;
// if there are authenticate attributes, get the message
// digest and compare it with the digest of data
if
(
authenticatedAttributes
==
null
)
{
dataSigned
=
data
;
}
else
{
// first, check content type
ObjectIdentifier
contentType
=
(
ObjectIdentifier
)
authenticatedAttributes
.
getAttributeValue
(
PKCS9Attribute
.
CONTENT_TYPE_OID
);
if
(
contentType
==
null
||
!
contentType
.
equals
(
content
.
contentType
))
return
null
;
// contentType does not match, bad SignerInfo
// now, check message digest
byte
[]
messageDigest
=
(
byte
[])
authenticatedAttributes
.
getAttributeValue
(
PKCS9Attribute
.
MESSAGE_DIGEST_OID
);
if
(
messageDigest
==
null
)
// fail if there is no message digest
return
null
;
MessageDigest
md
=
MessageDigest
.
getInstance
(
digestAlgname
);
byte
[]
computedMessageDigest
=
md
.
digest
(
data
);
if
(
messageDigest
.
length
!=
computedMessageDigest
.
length
)
return
null
;
for
(
int
i
=
0
;
i
<
messageDigest
.
length
;
i
++)
{
if
(
messageDigest
[
i
]
!=
computedMessageDigest
[
i
])
return
null
;
}
// message digest attribute matched
// digest of original data
// the data actually signed is the DER encoding of
// the authenticated attributes (tagged with
// the "SET OF" tag, not 0xA0).
dataSigned
=
authenticatedAttributes
.
getDerEncoding
();
throws
NoSuchAlgorithmException
,
SignatureException
{
PKCS7
.
PKCS7Verifier
p7v
=
PKCS7
.
PKCS7Verifier
.
from
(
block
,
this
);
if
(
p7v
==
null
)
return
null
;
if
(
data
==
null
)
{
try
{
data
=
block
.
getContentInfo
().
getContentBytes
();
}
catch
(
IOException
e
)
{
throw
new
SignatureException
(
"IO error verifying signature:\n"
+
e
.
getMessage
());
}
// put together digest algorithm and encryption algorithm
// to form signing algorithm
String
encryptionAlgname
=
getDigestEncryptionAlgorithmId
().
getName
();
// Workaround: sometimes the encryptionAlgname is actually
// a signature name
String
tmp
=
AlgorithmId
.
getEncAlgFromSigAlg
(
encryptionAlgname
);
if
(
tmp
!=
null
)
encryptionAlgname
=
tmp
;
String
algname
=
AlgorithmId
.
makeSigAlg
(
digestAlgname
,
encryptionAlgname
);
Signature
sig
=
Signature
.
getInstance
(
algname
);
X509Certificate
cert
=
getCertificate
(
block
);
if
(
cert
==
null
)
{
return
null
;
}
if
(
cert
.
hasUnsupportedCriticalExtension
())
{
throw
new
SignatureException
(
"Certificate has unsupported "
+
"critical extension(s)"
);
}
// Make sure that if the usage of the key in the certificate is
// restricted, it can be used for digital signatures.
// XXX We may want to check for additional extensions in the
// future.
boolean
[]
keyUsageBits
=
cert
.
getKeyUsage
();
if
(
keyUsageBits
!=
null
)
{
KeyUsageExtension
keyUsage
;
try
{
// We don't care whether or not this extension was marked
// critical in the certificate.
// We're interested only in its value (i.e., the bits set)
// and treat the extension as critical.
keyUsage
=
new
KeyUsageExtension
(
keyUsageBits
);
}
catch
(
IOException
ioe
)
{
throw
new
SignatureException
(
"Failed to parse keyUsage "
+
"extension"
);
}
boolean
digSigAllowed
=
((
Boolean
)
keyUsage
.
get
(
KeyUsageExtension
.
DIGITAL_SIGNATURE
)).
booleanValue
();
boolean
nonRepuAllowed
=
((
Boolean
)
keyUsage
.
get
(
KeyUsageExtension
.
NON_REPUDIATION
)).
booleanValue
();
if
(!
digSigAllowed
&&
!
nonRepuAllowed
)
{
throw
new
SignatureException
(
"Key usage restricted: "
+
"cannot be used for "
+
"digital signatures"
);
}
}
PublicKey
key
=
cert
.
getPublicKey
();
sig
.
initVerify
(
key
);
sig
.
update
(
dataSigned
);
if
(
sig
.
verify
(
encryptedDigest
))
{
return
this
;
}
}
catch
(
IOException
e
)
{
throw
new
SignatureException
(
"IO error verifying signature:\n"
+
e
.
getMessage
());
}
catch
(
InvalidKeyException
e
)
{
throw
new
SignatureException
(
"InvalidKey: "
+
e
.
getMessage
());
}
return
null
;
p7v
.
update
(
data
,
0
,
data
.
length
);
return
p7v
.
verify
();
}
/* Verify the content of the pkcs7 block. */
...
...
src/share/classes/sun/security/util/ManifestEntryVerifier.java
浏览文件 @
eb346a3f
/*
* Copyright (c) 1997, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
1
, 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
...
...
@@ -191,8 +191,8 @@ public class ManifestEntryVerifier {
*
*
*/
public
CodeSigner
[]
verify
(
Hashtable
<
String
,
CodeSigner
[]>
verifiedSigners
,
Hashtable
<
String
,
CodeSigner
[]>
sigFileSigners
)
public
CodeSigner
[]
verify
(
Map
<
String
,
CodeSigner
[]>
verifiedSigners
,
Map
<
String
,
CodeSigner
[]>
sigFileSigners
)
throws
JarException
{
if
(
skip
)
{
...
...
src/share/classes/sun/security/util/SignatureFileManifest.java
0 → 100644
浏览文件 @
eb346a3f
/*
* Copyright (c) 2011, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package
sun.security.util
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.util.Arrays
;
import
java.util.jar.Attributes
;
import
java.util.jar.Manifest
;
/**
* This class provides streaming mode reading of manifest files.
* Used by {@link SignatureFileVerifier}.
*/
class
SignatureFileManifest
extends
Manifest
{
/*
* Reading a manifest into this object by calling update(byte[]) on chunks.
* During the reading, the bytes are saved in (@code current} until a line
* is complete and the key-value pair is saved in {@code currentAttr}. When
* a section is complete, {@code consumeAttr} is called to merge
* {@code currentAttr} into main attributes or a named entry.
*/
// Internal state during update() style reading
// 0. not in update mode
// 1, in update mode but main attributes not completed yet
// 2. main attributes completed, still reading the entries
private
int
state
=
0
;
// The partial line read
private
byte
[]
current
;
// Number of bytes in current
private
int
currentPos
=
0
;
// The current Attribute
private
Attributes
currentAttr
;
/**
* Reads a manifest in chunks.
* <p>
* This method must be called in a row, reading chunks from a single
* manifest file by order. After all chunks are read, caller must call
* {@code update(null)} to fully consume the manifest.
* <p>
* The entry names and attributes read will be merged in with the current
* manifest entries. The {@link #read} method cannot be called inside a
* row of update calls.
* <p>
* Along with the calls, caller can call {@link #getMainAttributes()},
* {@link #getAttributes(java.lang.String)} or {@link #getEntries()}
* to get already available contents. However, in order not to return
* partial result, when the main attributes in the new manifest is not
* consumed completely, {@link #getMainAttributes()} throws an
* {@code IllegalStateException}. When a certain named entry is not
* consumed completely, {@link #getAttributes(java.lang.String)}
* returns the old {@code Attributes} for the name (if it exists).
*
* @param data null for last call, otherwise, feeding chunks
* @param offset offset into data to begin read
* @param length length of data after offset to read
* @exception IOException if an I/O error has occurred
* @exception IllegalStateException if {@code update(null)} is called
* without any previous {@code update(non-null)} call
*/
public
void
update
(
byte
[]
data
,
int
offset
,
int
length
)
throws
IOException
{
// The last call
if
(
data
==
null
)
{
if
(
state
==
0
)
{
throw
new
IllegalStateException
(
"No data to update"
);
}
// We accept manifest not ended with \n or \n\n
if
(
hasLastByte
())
{
consumeCurrent
();
}
// We accept empty lines at the end
if
(!
currentAttr
.
isEmpty
())
{
consumeAttr
();
}
state
=
0
;
// back to non-update state
current
=
null
;
currentAttr
=
null
;
return
;
}
// The first call
if
(
state
==
0
)
{
current
=
new
byte
[
1024
];
currentAttr
=
super
.
getMainAttributes
();
// the main attribute
state
=
1
;
}
int
end
=
offset
+
length
;
while
(
offset
<
end
)
{
switch
(
data
[
offset
])
{
case
'\r'
:
break
;
// always skip
case
'\n'
:
if
(
hasLastByte
()
&&
lastByte
()
==
'\n'
)
{
// new section
consumeCurrent
();
consumeAttr
();
if
(
state
==
1
)
{
state
=
2
;
}
currentAttr
=
new
Attributes
(
2
);
}
else
{
if
(
hasLastByte
())
{
// save \n into current but do not parse,
// there might be a continuation later
ensureCapacity
();
current
[
currentPos
++]
=
data
[
offset
];
}
else
if
(
state
==
1
)
{
// there can be multiple empty lines between
// sections, but cannot be at the beginning
throw
new
IOException
(
"invalid manifest format"
);
}
}
break
;
case
' '
:
if
(!
hasLastByte
())
{
throw
new
IOException
(
"invalid manifest format"
);
}
else
if
(
lastByte
()
==
'\n'
)
{
currentPos
--;
// continuation, remove last \n
}
else
{
// a very normal ' '
ensureCapacity
();
current
[
currentPos
++]
=
data
[
offset
];
}
break
;
default
:
if
(
hasLastByte
()
&&
lastByte
()
==
'\n'
)
{
// The start of a new pair, not continuation
consumeCurrent
();
// the last line read
}
ensureCapacity
();
current
[
currentPos
++]
=
data
[
offset
];
break
;
}
offset
++;
}
}
/**
* Returns the main Attributes for the Manifest.
* @exception IllegalStateException the main attributes is being read
* @return the main Attributes for the Manifest
*/
public
Attributes
getMainAttributes
()
{
if
(
state
==
1
)
{
throw
new
IllegalStateException
();
}
return
super
.
getMainAttributes
();
}
/**
* Reads the Manifest from the specified InputStream. The entry
* names and attributes read will be merged in with the current
* manifest entries.
*
* @param is the input stream
* @exception IOException if an I/O error has occurred
* @exception IllegalStateException if called between two {@link #update}
* calls
*/
public
void
read
(
InputStream
is
)
throws
IOException
{
if
(
state
!=
0
)
{
throw
new
IllegalStateException
(
"Cannot call read between updates"
);
}
super
.
read
(
is
);
}
/*
* ---------- Helper methods -----------------
*/
private
void
ensureCapacity
()
{
if
(
currentPos
>=
current
.
length
-
1
)
{
current
=
Arrays
.
copyOf
(
current
,
current
.
length
*
2
);
}
}
private
boolean
hasLastByte
()
{
return
currentPos
>
0
;
}
private
byte
lastByte
()
{
return
current
[
currentPos
-
1
];
}
// Parse current as key:value and save into currentAttr.
// There MUST be something inside current.
private
void
consumeCurrent
()
throws
IOException
{
// current normally has a \n end, except for the last line
if
(
current
[
currentPos
-
1
]
==
'\n'
)
currentPos
--;
for
(
int
i
=
0
;
i
<
currentPos
;
i
++)
{
if
(
current
[
i
]
==
':'
)
{
String
key
=
new
String
(
current
,
0
,
0
,
i
);
i
++;
while
(
i
<
currentPos
&&
current
[
i
]
==
' '
)
{
i
++;
}
String
value
=
new
String
(
current
,
i
,
currentPos
-
i
,
"UTF-8"
);
currentAttr
.
putValue
(
key
,
value
);
currentPos
=
0
;
return
;
}
}
throw
new
IOException
(
"invalid header field"
);
}
// Merge currentAttr into Manifest
private
void
consumeAttr
()
throws
IOException
{
// Only needed for named entries. For the main attribute, key/value
// is added into attr directly, but since getMainAttributes() throws
// an exception, the partial data is not leaked.
if
(
state
!=
1
)
{
String
name
=
currentAttr
.
getValue
(
"Name"
);
if
(
name
!=
null
)
{
currentAttr
.
remove
(
new
Attributes
.
Name
(
"Name"
));
Attributes
old
=
getAttributes
(
name
);
if
(
old
!=
null
)
old
.
putAll
(
currentAttr
);
else
getEntries
().
put
(
name
,
currentAttr
);
}
else
{
throw
new
IOException
(
"invalid manifest format"
);
}
}
}
}
src/share/classes/sun/security/util/SignatureFileVerifier.java
浏览文件 @
eb346a3f
...
...
@@ -55,8 +55,8 @@ public class SignatureFileVerifier {
/** the PKCS7 block for this .DSA/.RSA/.EC file */
private
PKCS7
block
;
/
** the raw bytes of the .SF file */
private
byte
sfBytes
[]
;
/
/ the content of the raw .SF file as an InputStream
private
InputStream
sfStream
;
/** the name of the signature block file, uppercased and without
* the extension (.DSA/.RSA/.EC)
...
...
@@ -66,6 +66,9 @@ public class SignatureFileVerifier {
/** the ManifestDigester */
private
ManifestDigester
md
;
/** The MANIFEST.MF */
private
Manifest
man
;
/** cache of created MessageDigest objects */
private
HashMap
<
String
,
MessageDigest
>
createdDigests
;
...
...
@@ -83,6 +86,7 @@ public class SignatureFileVerifier {
* @param rawBytes the raw bytes of the signature block file
*/
public
SignatureFileVerifier
(
ArrayList
<
CodeSigner
[]>
signerCache
,
Manifest
man
,
ManifestDigester
md
,
String
name
,
byte
rawBytes
[])
...
...
@@ -94,13 +98,18 @@ public class SignatureFileVerifier {
try
{
obj
=
Providers
.
startJarVerification
();
block
=
new
PKCS7
(
rawBytes
);
sfBytes
=
block
.
getContentInfo
().
getData
();
byte
[]
contentData
=
block
.
getContentInfo
().
getData
();
if
(
contentData
!=
null
)
{
sfStream
=
new
ByteArrayInputStream
(
contentData
);
}
certificateFactory
=
CertificateFactory
.
getInstance
(
"X509"
);
}
finally
{
Providers
.
stopJarVerification
(
obj
);
}
this
.
name
=
name
.
substring
(
0
,
name
.
lastIndexOf
(
"."
))
.
toUpperCase
(
Locale
.
ENGLISH
);
this
.
man
=
man
;
this
.
md
=
md
;
this
.
signerCache
=
signerCache
;
}
...
...
@@ -108,31 +117,13 @@ public class SignatureFileVerifier {
/**
* returns true if we need the .SF file
*/
public
boolean
needSignatureFile
Bytes
()
public
boolean
needSignatureFile
()
{
return
sfBytes
==
null
;
return
sfStream
==
null
;
}
/**
* returns true if we need this .SF file.
*
* @param name the name of the .SF file without the extension
*
*/
public
boolean
needSignatureFile
(
String
name
)
{
return
this
.
name
.
equalsIgnoreCase
(
name
);
}
/**
* used to set the raw bytes of the .SF file when it
* is external to the signature block file.
*/
public
void
setSignatureFile
(
byte
sfBytes
[])
{
this
.
sfBytes
=
sfBytes
;
public
void
setSignatureFile
(
InputStream
ins
)
{
this
.
sfStream
=
ins
;
}
/**
...
...
@@ -145,12 +136,18 @@ public class SignatureFileVerifier {
* Signature File or PKCS7 block file name
*/
public
static
boolean
isBlockOrSF
(
String
s
)
{
// we currently only support DSA and RSA PKCS7 blocks
if
(
s
.
endsWith
(
".SF"
)
||
s
.
endsWith
(
".DSA"
)
||
s
.
endsWith
(
".RSA"
)
||
s
.
endsWith
(
".EC"
))
{
return
true
;
}
return
false
;
return
s
.
endsWith
(
".SF"
)
||
isBlock
(
s
);
}
/**
* Utility method used by JarVerifier to determine PKCS7 block
* files names that are supported
*
* @param s file name
* @return true if the input file name is a PKCS7 block file name
*/
public
static
boolean
isBlock
(
String
s
)
{
return
s
.
endsWith
(
".DSA"
)
||
s
.
endsWith
(
".RSA"
)
||
s
.
endsWith
(
".EC"
);
}
/** get digest from cache */
...
...
@@ -180,7 +177,7 @@ public class SignatureFileVerifier {
*
*
*/
public
void
process
(
Hashtable
<
String
,
CodeSigner
[]>
signers
,
public
void
process
(
Map
<
String
,
CodeSigner
[]>
signers
,
List
manifestDigests
)
throws
IOException
,
SignatureException
,
NoSuchAlgorithmException
,
JarException
,
CertificateException
...
...
@@ -197,31 +194,86 @@ public class SignatureFileVerifier {
}
private
void
processImpl
(
Hashtable
<
String
,
CodeSigner
[]>
signers
,
private
void
processImpl
(
Map
<
String
,
CodeSigner
[]>
signers
,
List
manifestDigests
)
throws
IOException
,
SignatureException
,
NoSuchAlgorithmException
,
JarException
,
CertificateException
{
Manifest
sf
=
new
Manifest
();
sf
.
read
(
new
ByteArrayInputStream
(
sfBytes
))
;
SignatureFileManifest
sf
=
new
SignatureFile
Manifest
();
InputStream
ins
=
sfStream
;
String
version
=
sf
.
getMainAttributes
().
getValue
(
Attributes
.
Name
.
SIGNATURE_VERSION
);
byte
[]
buffer
=
new
byte
[
4096
];
int
sLen
=
block
.
getSignerInfos
().
length
;
boolean
mainOK
=
false
;
// main attributes of SF is available...
boolean
manifestSigned
=
false
;
// and it matches MANIFEST.MF
BASE64Decoder
decoder
=
new
BASE64Decoder
();
if
((
version
==
null
)
||
!(
version
.
equalsIgnoreCase
(
"1.0"
)))
{
// XXX: should this be an exception?
// for now we just ignore this signature file
return
;
PKCS7
.
PKCS7Verifier
[]
pvs
=
new
PKCS7
.
PKCS7Verifier
[
sLen
];
for
(
int
i
=
0
;
i
<
sLen
;
i
++)
{
pvs
[
i
]
=
PKCS7
.
PKCS7Verifier
.
from
(
block
,
block
.
getSignerInfos
()[
i
]);
}
SignerInfo
[]
infos
=
block
.
verify
(
sfBytes
);
/*
* Verify SF in streaming mode. The chunks of the file are fed into
* the Manifest object sf and all PKCS7Verifiers. As soon as the main
* attributes is available, we'll check if manifestSigned is true. If
* yes, there is no need to fill in sf's entries field, since it should
* be identical to entries in man.
*/
while
(
true
)
{
int
len
=
ins
.
read
(
buffer
);
if
(
len
<
0
)
{
if
(!
manifestSigned
)
{
sf
.
update
(
null
,
0
,
0
);
}
break
;
}
else
{
for
(
int
i
=
0
;
i
<
sLen
;
i
++)
{
if
(
pvs
[
i
]
!=
null
)
pvs
[
i
].
update
(
buffer
,
0
,
len
);
}
// Continue reading if verifyManifestHash fails (or, the
// main attributes is not available yet)
if
(!
manifestSigned
)
{
sf
.
update
(
buffer
,
0
,
len
);
if
(!
mainOK
)
{
try
{
Attributes
attr
=
sf
.
getMainAttributes
();
String
version
=
attr
.
getValue
(
Attributes
.
Name
.
SIGNATURE_VERSION
);
if
((
version
==
null
)
||
!(
version
.
equalsIgnoreCase
(
"1.0"
)))
{
// XXX: should this be an exception?
// for now we just ignore this signature file
return
;
}
if
(
infos
==
null
)
{
mainOK
=
true
;
manifestSigned
=
verifyManifestHash
(
sf
,
md
,
decoder
,
manifestDigests
);
}
catch
(
IllegalStateException
ise
)
{
// main attributes not available yet
}
}
}
}
}
List
<
SignerInfo
>
intResult
=
new
ArrayList
<>(
sLen
);
for
(
int
i
=
0
;
i
<
sLen
;
i
++)
{
if
(
pvs
[
i
]
!=
null
)
{
SignerInfo
signerInfo
=
pvs
[
i
].
verify
();
if
(
signerInfo
!=
null
)
{
intResult
.
add
(
signerInfo
);
}
}
}
if
(
intResult
.
isEmpty
())
{
throw
new
SecurityException
(
"cannot verify signature block file "
+
name
);
}
BASE64Decoder
decoder
=
new
BASE64Decoder
();
SignerInfo
[]
infos
=
intResult
.
toArray
(
new
SignerInfo
[
intResult
.
size
()]);
CodeSigner
[]
newSigners
=
getSigners
(
infos
,
block
);
...
...
@@ -229,26 +281,37 @@ public class SignatureFileVerifier {
if
(
newSigners
==
null
)
return
;
Iterator
<
Map
.
Entry
<
String
,
Attributes
>>
entries
=
sf
.
getEntries
().
entrySet
().
iterator
();
// see if we can verify the whole manifest first
boolean
manifestSigned
=
verifyManifestHash
(
sf
,
md
,
decoder
,
manifestDigests
);
// verify manifest main attributes
if
(!
manifestSigned
&&
!
verifyManifestMainAttrs
(
sf
,
md
,
decoder
))
{
throw
new
SecurityException
(
"Invalid signature file digest for Manifest main attributes"
);
}
// go through each section in the signature file
Iterator
<
Map
.
Entry
<
String
,
Attributes
>>
entries
;
if
(
manifestSigned
)
{
if
(
debug
!=
null
)
{
debug
.
println
(
"full manifest signature match, "
+
"update signer info from MANIFEST.MF"
);
}
entries
=
man
.
getEntries
().
entrySet
().
iterator
();
}
else
{
if
(
debug
!=
null
)
{
debug
.
println
(
"full manifest signature unmatch, "
+
"update signer info from SF file"
);
}
entries
=
sf
.
getEntries
().
entrySet
().
iterator
();
}
// go through each section
while
(
entries
.
hasNext
())
{
Map
.
Entry
<
String
,
Attributes
>
e
=
entries
.
next
();
String
name
=
e
.
getKey
();
if
(
manifestSigned
||
(
verifySection
(
e
.
getValue
(),
name
,
md
,
decoder
)))
{
(
verifySection
(
e
.
getValue
(),
name
,
md
,
decoder
)))
{
if
(
name
.
startsWith
(
"./"
))
name
=
name
.
substring
(
2
);
...
...
@@ -593,7 +656,6 @@ public class SignatureFileVerifier {
if
(
set
==
subset
)
return
true
;
boolean
match
;
for
(
int
i
=
0
;
i
<
subset
.
length
;
i
++)
{
if
(!
contains
(
set
,
subset
[
i
]))
return
false
;
...
...
@@ -613,8 +675,6 @@ public class SignatureFileVerifier {
if
((
oldSigners
==
null
)
&&
(
signers
==
newSigners
))
return
true
;
boolean
match
;
// make sure all oldSigners are in signers
if
((
oldSigners
!=
null
)
&&
!
isSubSet
(
oldSigners
,
signers
))
return
false
;
...
...
@@ -638,7 +698,7 @@ public class SignatureFileVerifier {
}
void
updateSigners
(
CodeSigner
[]
newSigners
,
Hashtable
<
String
,
CodeSigner
[]>
signers
,
String
name
)
{
Map
<
String
,
CodeSigner
[]>
signers
,
String
name
)
{
CodeSigner
[]
oldSigners
=
signers
.
get
(
name
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录