FYI: multisign
# HG changeset patch
# User weijun
# Date 1244775614 -28800
# Node ID 04a582051d4e724bea27c1ca37cb817108c8cbe0
# Parent 28c2dd378b5484cf937a7465a323c7cbf16ce9dc
6848277: multiple signature with different digest algorithm fail
Reviewed-by: nobody
--- a/src/share/classes/sun/security/util/ManifestDigester.java Thu Jun 11 16:17:05 2009 +0800
+++ b/src/share/classes/sun/security/util/ManifestDigester.java Fri Jun 12 11:00:14 2009 +0800
@@ -28,12 +28,16 @@
import java.security.*;
import java.util.HashMap;
import java.io.ByteArrayOutputStream;
+import java.util.Arrays;
/**
* This class is used to compute digests on sections of the Manifest.
*/
public class ManifestDigester {
+ /* Are we debugging ? */
+ static final Debug debug = Debug.getInstance("jar");
+
public static final String MF_MAIN_ATTRS = "Manifest-Main-Attributes";
/** the raw bytes of the manifest */
@@ -211,11 +215,75 @@
if (oldStyle) {
doOldStyle(md,rawBytes, offset, lengthWithBlankLine);
} else {
- md.update(rawBytes, offset, lengthWithBlankLine);
+ md.update(onlyThisDigest(md, rawBytes, offset, lengthWithBlankLine));
}
return md.digest();
}
+ /**
+ * Removes unrelated digest lines from the section
+ * @param md this digest, whose getAlgorithm() returns the needed prefix
+ * @return the filtered section
+ */
+ private byte[] onlyThisDigest(MessageDigest md, byte[] allBytes,
+ int offset, int len) {
+
+ byte[] result = Arrays.copyOfRange(allBytes, offset, offset+len);
+ String alg = md.getAlgorithm();
+ char[] digest = new char[] {'-', 'D', 'i', 'g', 'e', 's', 't'};
+
+ int lineStart = 0; // start position of current line
+ boolean badLine = false; // current line should be removed
+ boolean inKey = true; // ':' is not met, in the key side now.
+ // we only need to check the key side
+
+ // Now we copy from src to dest inside result
+ int n = result.length;
+ int i = 0, // current position of src
+ j = 0, // current position of dest
+ count = 0; // couting the "-Digest" chars
+
+ for (i = 0; i < n; i++) {
+ if (i != j) result[j] = result[i];
+ j++;
+ if (result[i] == '\n') {
+ if (badLine) {
+ j = lineStart; // reset dest pointer, ignore the line
+ }
+ lineStart = i+1;
+ badLine = false;
+ inKey = true;
+ count = 0;
+ } else if (result[i] == ':') {
+ inKey = false;
+ } else {
+ if (inKey && result[i] == digest[count] && i < n-1) {
+ count++;
+ if (count == 7) { // Full match of '-Digest'
+ String prefix = new String(
+ result, lineStart, i-6-lineStart);
+ if (!prefix.equals(alg) &&
+ (result[i+1]==':' || result[i+1]=='-')) {
+ badLine = true;
+ }
+ inKey = false; // We don't check the suffix
+ }
+ } else {
+ count = 0;
+ }
+ }
+ }
+ if (j != n) {
+ result = Arrays.copyOf(result, j);
+ if (debug != null) {
+ debug.println("ManifestDigester.onlyThisDigest: from [" +
+ new String(allBytes, offset, length) + "] to [" +
+ new String(result) + "] using " + alg);
+ }
+ }
+ return result;
+ }
+
private void doOldStyle(MessageDigest md,
byte[] bytes,
int offset,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/tools/jarsigner/multisign.sh Fri Jun 12 11:00:14 2009 +0800
@@ -0,0 +1,63 @@
+#
+# Copyright 2009 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 6848277
+# @summary multiple signature with different digest algorithm fail
+#
+# @run shell multisign.sh
+#
+
+if [ "${TESTJAVA}" = "" ] ; then
+ JAVAC_CMD=`which javac`
+ TESTJAVA=`dirname $JAVAC_CMD`/..
+fi
+
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+ Windows_* )
+ FS="\\"
+ ;;
+ * )
+ FS="/"
+ ;;
+esac
+
+KS=multi.jks
+JFILE=ab.jar
+
+KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS"
+JAR=$TESTJAVA${FS}bin${FS}jar
+JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner
+
+rm $KS $JFILE
+echo A > A
+$KT -alias a -dname CN=a -keyalg rsa -genkey
+$KT -alias b -dname CN=b -keyalg rsa -genkey
+$JAR cvf $JFILE A
+$JARSIGNER -keystore $KS -storepass changeit -digestalg SHA1 $JFILE a || exit 1
+$JARSIGNER -keystore $KS -storepass changeit -digestalg MD5 $JFILE b || exit 2
+$JARSIGNER -verify -debug $JFILE || exit 3
+
+exit 0