提交 19d4067e 编写于 作者: R robm

Merge

......@@ -92,7 +92,12 @@ final class LdapReferralContext implements DirContext, LdapContext {
try {
referral = refEx.getNextReferral();
if (referral == null) {
throw (NamingException)(previousEx.fillInStackTrace());
if (previousEx != null) {
throw (NamingException)(previousEx.fillInStackTrace());
} else {
throw new NamingException(
"Illegal encoding: referral is empty");
}
}
} catch (LdapReferralException e) {
......
......@@ -170,7 +170,8 @@ public final class URLPermission extends Permission {
parseURI(getName());
int colon = actions.indexOf(':');
if (actions.lastIndexOf(':') != colon) {
throw new IllegalArgumentException("invalid actions string");
throw new IllegalArgumentException(
"Invalid actions string: \"" + actions + "\"");
}
String methods, headers;
......@@ -371,7 +372,8 @@ public final class URLPermission extends Permission {
l.add(s);
b = new StringBuilder();
} else if (c == ' ' || c == '\t') {
throw new IllegalArgumentException("white space not allowed");
throw new IllegalArgumentException(
"White space not allowed in methods: \"" + methods + "\"");
} else {
if (c >= 'a' && c <= 'z') {
c += 'A' - 'a';
......@@ -398,7 +400,8 @@ public final class URLPermission extends Permission {
}
b.append(c);
} else if (c == ' ' || c == '\t') {
throw new IllegalArgumentException("white space not allowed");
throw new IllegalArgumentException(
"White space not allowed in headers: \"" + headers + "\"");
} else if (c == '-') {
capitalizeNext = true;
b.append(c);
......@@ -423,14 +426,16 @@ public final class URLPermission extends Permission {
int len = url.length();
int delim = url.indexOf(':');
if (delim == -1 || delim + 1 == len) {
throw new IllegalArgumentException("invalid URL string");
throw new IllegalArgumentException(
"Invalid URL string: \"" + url + "\"");
}
scheme = url.substring(0, delim).toLowerCase();
this.ssp = url.substring(delim + 1);
if (!ssp.startsWith("//")) {
if (!ssp.equals("*")) {
throw new IllegalArgumentException("invalid URL string");
throw new IllegalArgumentException(
"Invalid URL string: \"" + url + "\"");
}
this.authority = new Authority(scheme, "*");
return;
......
/*
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2016, 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
......@@ -47,7 +47,6 @@ import java.util.Arrays;
import java.util.Locale;
import java.util.Objects;
import java.util.ResourceBundle;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import sun.util.locale.provider.LocaleProviderAdapter;
......@@ -146,6 +145,12 @@ public class DateFormatSymbols implements Serializable, Cloneable {
initializeData(locale);
}
/**
* Constructs an uninitialized DateFormatSymbols.
*/
private DateFormatSymbols(boolean flag) {
}
/**
* Era strings. For example: "AD" and "BC". An array of 2 strings,
* indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>.
......@@ -677,54 +682,80 @@ public class DateFormatSymbols implements Serializable, Cloneable {
*/
transient volatile int cachedHashCode = 0;
private void initializeData(Locale desiredLocale) {
locale = desiredLocale;
// Copy values of a cached instance if any.
/**
* Initializes this DateFormatSymbols with the locale data. This method uses
* a cached DateFormatSymbols instance for the given locale if available. If
* there's no cached one, this method creates an uninitialized instance and
* populates its fields from the resource bundle for the locale, and caches
* the instance. Note: zoneStrings isn't initialized in this method.
*/
private void initializeData(Locale locale) {
SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
DateFormatSymbols dfs;
if (ref != null && (dfs = ref.get()) != null) {
copyMembers(dfs, this);
return;
}
// Initialize the fields from the ResourceBundle for locale.
LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(DateFormatSymbolsProvider.class, locale);
// Avoid any potential recursions
if (!(adapter instanceof ResourceBundleBasedAdapter)) {
adapter = LocaleProviderAdapter.getResourceBundleBased();
}
ResourceBundle resource = ((ResourceBundleBasedAdapter)adapter).getLocaleData().getDateFormatData(locale);
// JRE and CLDR use different keys
// JRE: Eras, short.Eras and narrow.Eras
// CLDR: long.Eras, Eras and narrow.Eras
if (resource.containsKey("Eras")) {
eras = resource.getStringArray("Eras");
} else if (resource.containsKey("long.Eras")) {
eras = resource.getStringArray("long.Eras");
} else if (resource.containsKey("short.Eras")) {
eras = resource.getStringArray("short.Eras");
}
months = resource.getStringArray("MonthNames");
shortMonths = resource.getStringArray("MonthAbbreviations");
ampms = resource.getStringArray("AmPmMarkers");
localPatternChars = resource.getString("DateTimePatternChars");
// Day of week names are stored in a 1-based array.
weekdays = toOneBasedArray(resource.getStringArray("DayNames"));
shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations"));
// Put a clone in the cache
ref = new SoftReference<>((DateFormatSymbols)this.clone());
SoftReference<DateFormatSymbols> x = cachedInstances.putIfAbsent(locale, ref);
if (x != null) {
DateFormatSymbols y = x.get();
if (y == null) {
// Replace the empty SoftReference with ref.
cachedInstances.put(locale, ref);
if (ref == null || (dfs = ref.get()) == null) {
if (ref != null) {
// Remove the empty SoftReference
cachedInstances.remove(locale, ref);
}
dfs = new DateFormatSymbols(false);
// Initialize the fields from the ResourceBundle for locale.
LocaleProviderAdapter adapter
= LocaleProviderAdapter.getAdapter(DateFormatSymbolsProvider.class, locale);
// Avoid any potential recursions
if (!(adapter instanceof ResourceBundleBasedAdapter)) {
adapter = LocaleProviderAdapter.getResourceBundleBased();
}
ResourceBundle resource
= ((ResourceBundleBasedAdapter)adapter).getLocaleData().getDateFormatData(locale);
dfs.locale = locale;
// JRE and CLDR use different keys
// JRE: Eras, short.Eras and narrow.Eras
// CLDR: long.Eras, Eras and narrow.Eras
if (resource.containsKey("Eras")) {
dfs.eras = resource.getStringArray("Eras");
} else if (resource.containsKey("long.Eras")) {
dfs.eras = resource.getStringArray("long.Eras");
} else if (resource.containsKey("short.Eras")) {
dfs.eras = resource.getStringArray("short.Eras");
}
dfs.months = resource.getStringArray("MonthNames");
dfs.shortMonths = resource.getStringArray("MonthAbbreviations");
dfs.ampms = resource.getStringArray("AmPmMarkers");
dfs.localPatternChars = resource.getString("DateTimePatternChars");
// Day of week names are stored in a 1-based array.
dfs.weekdays = toOneBasedArray(resource.getStringArray("DayNames"));
dfs.shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations"));
// Put dfs in the cache
ref = new SoftReference<>(dfs);
SoftReference<DateFormatSymbols> x = cachedInstances.putIfAbsent(locale, ref);
if (x != null) {
DateFormatSymbols y = x.get();
if (y == null) {
// Replace the empty SoftReference with ref.
cachedInstances.replace(locale, x, ref);
} else {
ref = x;
dfs = y;
}
}
// If the bundle's locale isn't the target locale, put another cache
// entry for the bundle's locale.
Locale bundleLocale = resource.getLocale();
if (!bundleLocale.equals(locale)) {
SoftReference<DateFormatSymbols> z
= cachedInstances.putIfAbsent(bundleLocale, ref);
if (z != null && z.get() == null) {
cachedInstances.replace(bundleLocale, z, ref);
}
}
}
// Copy the field values from dfs to this instance.
copyMembers(dfs, this);
}
private static String[] toOneBasedArray(String[] src) {
......@@ -806,12 +837,14 @@ public class DateFormatSymbols implements Serializable, Cloneable {
/**
* Clones all the data members from the source DateFormatSymbols to
* the target DateFormatSymbols. This is only for subclasses.
* the target DateFormatSymbols.
*
* @param src the source DateFormatSymbols.
* @param dst the target DateFormatSymbols.
*/
private void copyMembers(DateFormatSymbols src, DateFormatSymbols dst)
{
dst.locale = src.locale;
dst.eras = Arrays.copyOf(src.eras, src.eras.length);
dst.months = Arrays.copyOf(src.months, src.months.length);
dst.shortMonths = Arrays.copyOf(src.shortMonths, src.shortMonths.length);
......
/*
* Copyright (c) 2008, 2012, 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.invoke.anon;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import sun.misc.IOUtils;
/**
* Anonymous class loader. Will load any valid classfile, producing
* a {@link Class} metaobject, without installing that class in the
* system dictionary. Therefore, {@link Class#forName(String)} will never
* produce a reference to an anonymous class.
* <p>
* The access permissions of the anonymous class are borrowed from
* a <em>host class</em>. The new class behaves as if it were an
* inner class of the host class. It can access the host's private
* members, if the creator of the class loader has permission to
* do so (or to create accessible reflective objects).
* <p>
* When the anonymous class is loaded, elements of its constant pool
* can be patched to new values. This provides a hook to pre-resolve
* named classes in the constant pool to other classes, including
* anonymous ones. Also, string constants can be pre-resolved to
* any reference. (The verifier treats non-string, non-class reference
* constants as plain objects.)
* <p>
* Why include the patching function? It makes some use cases much easier.
* Second, the constant pool needed some internal patching anyway,
* to anonymize the loaded class itself. Finally, if you are going
* to use this seriously, you'll want to build anonymous classes
* on top of pre-existing anonymous classes, and that requires patching.
*
* <p>%%% TO-DO:
* <ul>
* <li>needs better documentation</li>
* <li>needs more security work (for safe delegation)</li>
* <li>needs a clearer story about error processing</li>
* <li>patch member references also (use ';' as delimiter char)</li>
* <li>patch method references to (conforming) method handles</li>
* </ul>
*
* @author jrose
* @author Remi Forax
* @see <a href="http://blogs.sun.com/jrose/entry/anonymous_classes_in_the_vm">
* http://blogs.sun.com/jrose/entry/anonymous_classes_in_the_vm</a>
*/
public class AnonymousClassLoader {
final Class<?> hostClass;
// Privileged constructor.
private AnonymousClassLoader(Class<?> hostClass) {
this.hostClass = hostClass;
}
public static AnonymousClassLoader make(sun.misc.Unsafe unsafe, Class<?> hostClass) {
if (unsafe == null) throw new NullPointerException();
return new AnonymousClassLoader(hostClass);
}
public Class<?> loadClass(byte[] classFile) {
if (defineAnonymousClass == null) {
// no JVM support; try to fake an approximation
try {
return fakeLoadClass(new ConstantPoolParser(classFile).createPatch());
} catch (InvalidConstantPoolFormatException ee) {
throw new IllegalArgumentException(ee);
}
}
return loadClass(classFile, null);
}
public Class<?> loadClass(ConstantPoolPatch classPatch) {
if (defineAnonymousClass == null) {
// no JVM support; try to fake an approximation
return fakeLoadClass(classPatch);
}
Object[] patches = classPatch.patchArray;
// Convert class names (this late in the game)
// to use slash '/' instead of dot '.'.
// Java likes dots, but the JVM likes slashes.
for (int i = 0; i < patches.length; i++) {
Object value = patches[i];
if (value != null) {
byte tag = classPatch.getTag(i);
switch (tag) {
case ConstantPoolVisitor.CONSTANT_Class:
if (value instanceof String) {
if (patches == classPatch.patchArray)
patches = patches.clone();
patches[i] = ((String)value).replace('.', '/');
}
break;
case ConstantPoolVisitor.CONSTANT_Fieldref:
case ConstantPoolVisitor.CONSTANT_Methodref:
case ConstantPoolVisitor.CONSTANT_InterfaceMethodref:
case ConstantPoolVisitor.CONSTANT_NameAndType:
// When/if the JVM supports these patches,
// we'll probably need to reformat them also.
// Meanwhile, let the class loader create the error.
break;
}
}
}
return loadClass(classPatch.outer.classFile, classPatch.patchArray);
}
private Class<?> loadClass(byte[] classFile, Object[] patchArray) {
try {
return (Class<?>)
defineAnonymousClass.invoke(unsafe,
hostClass, classFile, patchArray);
} catch (Exception ex) {
throwReflectedException(ex);
throw new RuntimeException("error loading into "+hostClass, ex);
}
}
private static void throwReflectedException(Exception ex) {
if (ex instanceof InvocationTargetException) {
Throwable tex = ((InvocationTargetException)ex).getTargetException();
if (tex instanceof Error)
throw (Error) tex;
ex = (Exception) tex;
}
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}
}
private Class<?> fakeLoadClass(ConstantPoolPatch classPatch) {
// Implementation:
// 1. Make up a new name nobody has used yet.
// 2. Inspect the tail-header of the class to find the this_class index.
// 3. Patch the CONSTANT_Class for this_class to the new name.
// 4. Add other CP entries required by (e.g.) string patches.
// 5. Flatten Class constants down to their names, making sure that
// the host class loader can pick them up again accurately.
// 6. Generate the edited class file bytes.
//
// Potential limitations:
// * The class won't be truly anonymous, and may interfere with others.
// * Flattened class constants might not work, because of loader issues.
// * Pseudo-string constants will not flatten down to real strings.
// * Method handles will (of course) fail to flatten to linkage strings.
if (true) throw new UnsupportedOperationException("NYI");
Object[] cpArray;
try {
cpArray = classPatch.getOriginalCP();
} catch (InvalidConstantPoolFormatException ex) {
throw new RuntimeException(ex);
}
int thisClassIndex = classPatch.getParser().getThisClassIndex();
String thisClassName = (String) cpArray[thisClassIndex];
synchronized (AnonymousClassLoader.class) {
thisClassName = thisClassName+"\\|"+(++fakeNameCounter);
}
classPatch.putUTF8(thisClassIndex, thisClassName);
byte[] classFile = null;
return unsafe.defineClass(null, classFile, 0, classFile.length,
hostClass.getClassLoader(),
hostClass.getProtectionDomain());
}
private static int fakeNameCounter = 99999;
// ignore two warnings on this line:
private static sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
// preceding line requires that this class be on the boot class path
static private final Method defineAnonymousClass;
static {
Method dac = null;
Class<? extends sun.misc.Unsafe> unsafeClass = unsafe.getClass();
try {
dac = unsafeClass.getMethod("defineAnonymousClass",
Class.class,
byte[].class,
Object[].class);
} catch (Exception ee) {
dac = null;
}
defineAnonymousClass = dac;
}
private static void noJVMSupport() {
throw new UnsupportedOperationException("no JVM support for anonymous classes");
}
private static native Class<?> loadClassInternal(Class<?> hostClass,
byte[] classFile,
Object[] patchArray);
public static byte[] readClassFile(Class<?> templateClass) throws IOException {
String templateName = templateClass.getName();
int lastDot = templateName.lastIndexOf('.');
java.net.URL url = templateClass.getResource(templateName.substring(lastDot+1)+".class");
java.net.URLConnection connection = url.openConnection();
int contentLength = connection.getContentLength();
if (contentLength < 0)
throw new IOException("invalid content length "+contentLength);
return IOUtils.readFully(connection.getInputStream(), contentLength, true);
}
}
/*
* Copyright (c) 2008, 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.invoke.anon;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import static sun.invoke.anon.ConstantPoolVisitor.*;
/** A constant pool parser.
*/
public class ConstantPoolParser {
final byte[] classFile;
final byte[] tags;
final char[] firstHeader; // maghi, maglo, minor, major, cplen
// these are filled in on first parse:
int endOffset;
char[] secondHeader; // flags, this_class, super_class, intlen
// used to decode UTF8 array
private char[] charArray = new char[80];
/** Creates a constant pool parser.
* @param classFile an array of bytes containing a class.
* @throws InvalidConstantPoolFormatException if the header of the class has errors.
*/
public ConstantPoolParser(byte[] classFile) throws InvalidConstantPoolFormatException {
this.classFile = classFile;
this.firstHeader = parseHeader(classFile);
this.tags = new byte[firstHeader[4]];
}
/** Create a constant pool parser by loading the bytecodes of the
* class taken as argument.
*
* @param templateClass the class to parse.
*
* @throws IOException raised if an I/O occurs when loading
* the bytecode of the template class.
* @throws InvalidConstantPoolFormatException if the header of the class has errors.
*
* @see #ConstantPoolParser(byte[])
* @see AnonymousClassLoader#readClassFile(Class)
*/
public ConstantPoolParser(Class<?> templateClass) throws IOException, InvalidConstantPoolFormatException {
this(AnonymousClassLoader.readClassFile(templateClass));
}
/** Creates an empty patch to patch the class file
* used by the current parser.
* @return a new class patch.
*/
public ConstantPoolPatch createPatch() {
return new ConstantPoolPatch(this);
}
/** Report the tag of the indicated CP entry.
* @param index
* @return one of {@link ConstantPoolVisitor#CONSTANT_Utf8}, etc.
*/
public byte getTag(int index) {
getEndOffset(); // trigger an exception if we haven't parsed yet
return tags[index];
}
/** Report the length of the constant pool. */
public int getLength() {
return firstHeader[4];
}
/** Report the offset, within the class file, of the start of the constant pool. */
public int getStartOffset() {
return firstHeader.length * 2;
}
/** Report the offset, within the class file, of the end of the constant pool. */
public int getEndOffset() {
if (endOffset == 0)
throw new IllegalStateException("class file has not yet been parsed");
return endOffset;
}
/** Report the CP index of this class's own name. */
public int getThisClassIndex() {
getEndOffset(); // provoke exception if not yet parsed
return secondHeader[1];
}
/** Report the total size of the class file. */
public int getTailLength() {
return classFile.length - getEndOffset();
}
/** Write the head (header plus constant pool)
* of the class file to the indicated stream.
*/
public void writeHead(OutputStream out) throws IOException {
out.write(classFile, 0, getEndOffset());
}
/** Write the head (header plus constant pool)
* of the class file to the indicated stream,
* incorporating the non-null entries of the given array
* as patches.
*/
void writePatchedHead(OutputStream out, Object[] patchArray) {
// this will be useful to partially emulate the class loader on old JVMs
throw new UnsupportedOperationException("Not yet implemented");
}
/** Write the tail (everything after the constant pool)
* of the class file to the indicated stream.
*/
public void writeTail(OutputStream out) throws IOException {
out.write(classFile, getEndOffset(), getTailLength());
}
private static char[] parseHeader(byte[] classFile) throws InvalidConstantPoolFormatException {
char[] result = new char[5];
ByteBuffer buffer = ByteBuffer.wrap(classFile);
for (int i = 0; i < result.length; i++)
result[i] = (char) getUnsignedShort(buffer);
int magic = result[0] << 16 | result[1] << 0;
if (magic != 0xCAFEBABE)
throw new InvalidConstantPoolFormatException("invalid magic number "+magic);
// skip major, minor version
int len = result[4];
if (len < 1)
throw new InvalidConstantPoolFormatException("constant pool length < 1");
return result;
}
/** Parse the constant pool of the class
* calling a method visit* each time a constant pool entry is parsed.
*
* The order of the calls to visit* is not guaranteed to be the same
* than the order of the constant pool entry in the bytecode array.
*
* @param visitor
* @throws InvalidConstantPoolFormatException
*/
public void parse(ConstantPoolVisitor visitor) throws InvalidConstantPoolFormatException {
ByteBuffer buffer = ByteBuffer.wrap(classFile);
buffer.position(getStartOffset()); //skip header
Object[] values = new Object[getLength()];
try {
parseConstantPool(buffer, values, visitor);
} catch(BufferUnderflowException e) {
throw new InvalidConstantPoolFormatException(e);
}
if (endOffset == 0) {
endOffset = buffer.position();
secondHeader = new char[4];
for (int i = 0; i < secondHeader.length; i++) {
secondHeader[i] = (char) getUnsignedShort(buffer);
}
}
resolveConstantPool(values, visitor);
}
private char[] getCharArray(int utfLength) {
if (utfLength <= charArray.length)
return charArray;
return charArray = new char[utfLength];
}
private void parseConstantPool(ByteBuffer buffer, Object[] values, ConstantPoolVisitor visitor) throws InvalidConstantPoolFormatException {
for (int i = 1; i < tags.length; ) {
byte tag = (byte) getUnsignedByte(buffer);
assert(tags[i] == 0 || tags[i] == tag);
tags[i] = tag;
switch (tag) {
case CONSTANT_Utf8:
int utfLen = getUnsignedShort(buffer);
String value = getUTF8(buffer, utfLen, getCharArray(utfLen));
visitor.visitUTF8(i, CONSTANT_Utf8, value);
tags[i] = tag;
values[i++] = value;
break;
case CONSTANT_Integer:
visitor.visitConstantValue(i, tag, buffer.getInt());
i++;
break;
case CONSTANT_Float:
visitor.visitConstantValue(i, tag, buffer.getFloat());
i++;
break;
case CONSTANT_Long:
visitor.visitConstantValue(i, tag, buffer.getLong());
i+=2;
break;
case CONSTANT_Double:
visitor.visitConstantValue(i, tag, buffer.getDouble());
i+=2;
break;
case CONSTANT_Class: // fall through:
case CONSTANT_String:
tags[i] = tag;
values[i++] = new int[] { getUnsignedShort(buffer) };
break;
case CONSTANT_Fieldref: // fall through:
case CONSTANT_Methodref: // fall through:
case CONSTANT_InterfaceMethodref: // fall through:
case CONSTANT_NameAndType:
tags[i] = tag;
values[i++] = new int[] { getUnsignedShort(buffer), getUnsignedShort(buffer) };
break;
default:
throw new AssertionError("invalid constant "+tag);
}
}
}
private void resolveConstantPool(Object[] values, ConstantPoolVisitor visitor) {
// clean out the int[] values, which are temporary
for (int beg = 1, end = values.length-1, beg2, end2;
beg <= end;
beg = beg2, end = end2) {
beg2 = end; end2 = beg-1;
//System.out.println("CP resolve pass: "+beg+".."+end);
for (int i = beg; i <= end; i++) {
Object value = values[i];
if (!(value instanceof int[]))
continue;
int[] array = (int[]) value;
byte tag = tags[i];
switch (tag) {
case CONSTANT_String:
String stringBody = (String) values[array[0]];
visitor.visitConstantString(i, tag, stringBody, array[0]);
values[i] = null;
break;
case CONSTANT_Class: {
String className = (String) values[array[0]];
// use the external form favored by Class.forName:
className = className.replace('/', '.');
visitor.visitConstantString(i, tag, className, array[0]);
values[i] = className;
break;
}
case CONSTANT_NameAndType: {
String memberName = (String) values[array[0]];
String signature = (String) values[array[1]];
visitor.visitDescriptor(i, tag, memberName, signature,
array[0], array[1]);
values[i] = new String[] {memberName, signature};
break;
}
case CONSTANT_Fieldref: // fall through:
case CONSTANT_Methodref: // fall through:
case CONSTANT_InterfaceMethodref: {
Object className = values[array[0]];
Object nameAndType = values[array[1]];
if (!(className instanceof String) ||
!(nameAndType instanceof String[])) {
// one more pass is needed
if (beg2 > i) beg2 = i;
if (end2 < i) end2 = i;
continue;
}
String[] nameAndTypeArray = (String[]) nameAndType;
visitor.visitMemberRef(i, tag,
(String)className,
nameAndTypeArray[0],
nameAndTypeArray[1],
array[0], array[1]);
values[i] = null;
}
break;
default:
continue;
}
}
}
}
private static int getUnsignedByte(ByteBuffer buffer) {
return buffer.get() & 0xFF;
}
private static int getUnsignedShort(ByteBuffer buffer) {
int b1 = getUnsignedByte(buffer);
int b2 = getUnsignedByte(buffer);
return (b1 << 8) + (b2 << 0);
}
private static String getUTF8(ByteBuffer buffer, int utfLen, char[] charArray) throws InvalidConstantPoolFormatException {
int utfLimit = buffer.position() + utfLen;
int index = 0;
while (buffer.position() < utfLimit) {
int c = buffer.get() & 0xff;
if (c > 127) {
buffer.position(buffer.position() - 1);
return getUTF8Extended(buffer, utfLimit, charArray, index);
}
charArray[index++] = (char)c;
}
return new String(charArray, 0, index);
}
private static String getUTF8Extended(ByteBuffer buffer, int utfLimit, char[] charArray, int index) throws InvalidConstantPoolFormatException {
int c, c2, c3;
while (buffer.position() < utfLimit) {
c = buffer.get() & 0xff;
switch (c >> 4) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
/* 0xxxxxxx*/
charArray[index++] = (char)c;
break;
case 12: case 13:
/* 110x xxxx 10xx xxxx*/
c2 = buffer.get();
if ((c2 & 0xC0) != 0x80)
throw new InvalidConstantPoolFormatException(
"malformed input around byte " + buffer.position());
charArray[index++] = (char)(((c & 0x1F) << 6) |
(c2 & 0x3F));
break;
case 14:
/* 1110 xxxx 10xx xxxx 10xx xxxx */
c2 = buffer.get();
c3 = buffer.get();
if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80))
throw new InvalidConstantPoolFormatException(
"malformed input around byte " + (buffer.position()));
charArray[index++] = (char)(((c & 0x0F) << 12) |
((c2 & 0x3F) << 6) |
((c3 & 0x3F) << 0));
break;
default:
/* 10xx xxxx, 1111 xxxx */
throw new InvalidConstantPoolFormatException(
"malformed input around byte " + buffer.position());
}
}
// The number of chars produced may be less than utflen
return new String(charArray, 0, index);
}
}
/*
* Copyright (c) 2008, 2013, 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.invoke.anon;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Map;
import static sun.invoke.anon.ConstantPoolVisitor.*;
/** A class and its patched constant pool.
*
* This class allow to modify (patch) a constant pool
* by changing the value of its entry.
* Entry are referenced using index that can be get
* by parsing the constant pool using
* {@link ConstantPoolParser#parse(ConstantPoolVisitor)}.
*
* @see ConstantPoolVisitor
* @see ConstantPoolParser#createPatch()
*/
public class ConstantPoolPatch {
final ConstantPoolParser outer;
final Object[] patchArray;
ConstantPoolPatch(ConstantPoolParser outer) {
this.outer = outer;
this.patchArray = new Object[outer.getLength()];
}
/** Create a {@link ConstantPoolParser} and
* a {@link ConstantPoolPatch} in one step.
* Equivalent to {@code new ConstantPoolParser(classFile).createPatch()}.
*
* @param classFile an array of bytes containing a class.
* @see #ConstantPoolParser(Class)
*/
public ConstantPoolPatch(byte[] classFile) throws InvalidConstantPoolFormatException {
this(new ConstantPoolParser(classFile));
}
/** Create a {@link ConstantPoolParser} and
* a {@link ConstantPoolPatch} in one step.
* Equivalent to {@code new ConstantPoolParser(templateClass).createPatch()}.
*
* @param templateClass the class to parse.
* @see #ConstantPoolParser(Class)
*/
public ConstantPoolPatch(Class<?> templateClass) throws IOException, InvalidConstantPoolFormatException {
this(new ConstantPoolParser(templateClass));
}
/** Creates a patch from an existing patch.
* All changes are copied from that patch.
* @param patch a patch
*
* @see ConstantPoolParser#createPatch()
*/
public ConstantPoolPatch(ConstantPoolPatch patch) {
outer = patch.outer;
patchArray = patch.patchArray.clone();
}
/** Which parser built this patch? */
public ConstantPoolParser getParser() {
return outer;
}
/** Report the tag at the given index in the constant pool. */
public byte getTag(int index) {
return outer.getTag(index);
}
/** Report the current patch at the given index of the constant pool.
* Null means no patch will be made.
* To observe the unpatched entry at the given index, use
* {@link #getParser()}{@code .}@link ConstantPoolParser#parse(ConstantPoolVisitor)}
*/
public Object getPatch(int index) {
Object value = patchArray[index];
if (value == null) return null;
switch (getTag(index)) {
case CONSTANT_Fieldref:
case CONSTANT_Methodref:
case CONSTANT_InterfaceMethodref:
if (value instanceof String)
value = stripSemis(2, (String) value);
break;
case CONSTANT_NameAndType:
if (value instanceof String)
value = stripSemis(1, (String) value);
break;
}
return value;
}
/** Clear all patches. */
public void clear() {
Arrays.fill(patchArray, null);
}
/** Clear one patch. */
public void clear(int index) {
patchArray[index] = null;
}
/** Produce the patches as an array. */
public Object[] getPatches() {
return patchArray.clone();
}
/** Produce the original constant pool as an array. */
public Object[] getOriginalCP() throws InvalidConstantPoolFormatException {
return getOriginalCP(0, patchArray.length, -1);
}
/** Walk the constant pool, applying patches using the given map.
*
* @param utf8Map Utf8 strings to modify, if encountered
* @param classMap Classes (or their names) to modify, if encountered
* @param valueMap Constant values to modify, if encountered
* @param deleteUsedEntries if true, delete map entries that are used
*/
public void putPatches(final Map<String,String> utf8Map,
final Map<String,Object> classMap,
final Map<Object,Object> valueMap,
boolean deleteUsedEntries) throws InvalidConstantPoolFormatException {
final HashSet<String> usedUtf8Keys;
final HashSet<String> usedClassKeys;
final HashSet<Object> usedValueKeys;
if (deleteUsedEntries) {
usedUtf8Keys = (utf8Map == null) ? null : new HashSet<String>();
usedClassKeys = (classMap == null) ? null : new HashSet<String>();
usedValueKeys = (valueMap == null) ? null : new HashSet<Object>();
} else {
usedUtf8Keys = null;
usedClassKeys = null;
usedValueKeys = null;
}
outer.parse(new ConstantPoolVisitor() {
@Override
public void visitUTF8(int index, byte tag, String utf8) {
putUTF8(index, utf8Map.get(utf8));
if (usedUtf8Keys != null) usedUtf8Keys.add(utf8);
}
@Override
public void visitConstantValue(int index, byte tag, Object value) {
putConstantValue(index, tag, valueMap.get(value));
if (usedValueKeys != null) usedValueKeys.add(value);
}
@Override
public void visitConstantString(int index, byte tag, String name, int nameIndex) {
if (tag == CONSTANT_Class) {
putConstantValue(index, tag, classMap.get(name));
if (usedClassKeys != null) usedClassKeys.add(name);
} else {
assert(tag == CONSTANT_String);
visitConstantValue(index, tag, name);
}
}
});
if (usedUtf8Keys != null) utf8Map.keySet().removeAll(usedUtf8Keys);
if (usedClassKeys != null) classMap.keySet().removeAll(usedClassKeys);
if (usedValueKeys != null) valueMap.keySet().removeAll(usedValueKeys);
}
Object[] getOriginalCP(final int startIndex,
final int endIndex,
final int tagMask) throws InvalidConstantPoolFormatException {
final Object[] cpArray = new Object[endIndex - startIndex];
outer.parse(new ConstantPoolVisitor() {
void show(int index, byte tag, Object value) {
if (index < startIndex || index >= endIndex) return;
if (((1 << tag) & tagMask) == 0) return;
cpArray[index - startIndex] = value;
}
@Override
public void visitUTF8(int index, byte tag, String utf8) {
show(index, tag, utf8);
}
@Override
public void visitConstantValue(int index, byte tag, Object value) {
assert(tag != CONSTANT_String);
show(index, tag, value);
}
@Override
public void visitConstantString(int index, byte tag,
String value, int j) {
show(index, tag, value);
}
@Override
public void visitMemberRef(int index, byte tag,
String className, String memberName,
String signature,
int j, int k) {
show(index, tag, new String[]{ className, memberName, signature });
}
@Override
public void visitDescriptor(int index, byte tag,
String memberName, String signature,
int j, int k) {
show(index, tag, new String[]{ memberName, signature });
}
});
return cpArray;
}
/** Write the head (header plus constant pool)
* of the patched class file to the indicated stream.
*/
void writeHead(OutputStream out) throws IOException {
outer.writePatchedHead(out, patchArray);
}
/** Write the tail (everything after the constant pool)
* of the patched class file to the indicated stream.
*/
void writeTail(OutputStream out) throws IOException {
outer.writeTail(out);
}
private void checkConstantTag(byte tag, Object value) {
if (value == null)
throw new IllegalArgumentException(
"invalid null constant value");
if (classForTag(tag) != value.getClass())
throw new IllegalArgumentException(
"invalid constant value"
+ (tag == CONSTANT_None ? ""
: " for tag "+tagName(tag))
+ " of class "+value.getClass());
}
private void checkTag(int index, byte putTag) {
byte tag = outer.tags[index];
if (tag != putTag)
throw new IllegalArgumentException(
"invalid put operation"
+ " for " + tagName(putTag)
+ " at index " + index + " found " + tagName(tag));
}
private void checkTagMask(int index, int tagBitMask) {
byte tag = outer.tags[index];
int tagBit = ((tag & 0x1F) == tag) ? (1 << tag) : 0;
if ((tagBit & tagBitMask) == 0)
throw new IllegalArgumentException(
"invalid put operation"
+ " at index " + index + " found " + tagName(tag));
}
private static void checkMemberName(String memberName) {
if (memberName.indexOf(';') >= 0)
throw new IllegalArgumentException("memberName " + memberName + " contains a ';'");
}
/** Set the entry of the constant pool indexed by index to
* a new string.
*
* @param index an index to a constant pool entry containing a
* {@link ConstantPoolVisitor#CONSTANT_Utf8} value.
* @param utf8 a string
*
* @see ConstantPoolVisitor#visitUTF8(int, byte, String)
*/
public void putUTF8(int index, String utf8) {
if (utf8 == null) { clear(index); return; }
checkTag(index, CONSTANT_Utf8);
patchArray[index] = utf8;
}
/** Set the entry of the constant pool indexed by index to
* a new value, depending on its dynamic type.
*
* @param index an index to a constant pool entry containing a
* one of the following structures:
* {@link ConstantPoolVisitor#CONSTANT_Integer},
* {@link ConstantPoolVisitor#CONSTANT_Float},
* {@link ConstantPoolVisitor#CONSTANT_Long},
* {@link ConstantPoolVisitor#CONSTANT_Double},
* {@link ConstantPoolVisitor#CONSTANT_String}, or
* {@link ConstantPoolVisitor#CONSTANT_Class}
* @param value a boxed int, float, long or double; or a string or class object
* @throws IllegalArgumentException if the type of the constant does not
* match the constant pool entry type,
* as reported by {@link #getTag(int)}
*
* @see #putConstantValue(int, byte, Object)
* @see ConstantPoolVisitor#visitConstantValue(int, byte, Object)
* @see ConstantPoolVisitor#visitConstantString(int, byte, String, int)
*/
public void putConstantValue(int index, Object value) {
if (value == null) { clear(index); return; }
byte tag = tagForConstant(value.getClass());
checkConstantTag(tag, value);
checkTag(index, tag);
patchArray[index] = value;
}
/** Set the entry of the constant pool indexed by index to
* a new value.
*
* @param index an index to a constant pool entry matching the given tag
* @param tag one of the following values:
* {@link ConstantPoolVisitor#CONSTANT_Integer},
* {@link ConstantPoolVisitor#CONSTANT_Float},
* {@link ConstantPoolVisitor#CONSTANT_Long},
* {@link ConstantPoolVisitor#CONSTANT_Double},
* {@link ConstantPoolVisitor#CONSTANT_String}, or
* {@link ConstantPoolVisitor#CONSTANT_Class}
* @param value a boxed number, string, or class object
* @throws IllegalArgumentException if the type of the constant does not
* match the constant pool entry type, or if a class name contains
* '/' or ';'
*
* @see #putConstantValue(int, Object)
* @see ConstantPoolVisitor#visitConstantValue(int, byte, Object)
* @see ConstantPoolVisitor#visitConstantString(int, byte, String, int)
*/
public void putConstantValue(int index, byte tag, Object value) {
if (value == null) { clear(index); return; }
checkTag(index, tag);
if (tag == CONSTANT_Class && value instanceof String) {
checkClassName((String) value);
} else if (tag == CONSTANT_String) {
// the JVM accepts any object as a patch for a string
} else {
// make sure the incoming value is the right type
checkConstantTag(tag, value);
}
checkTag(index, tag);
patchArray[index] = value;
}
/** Set the entry of the constant pool indexed by index to
* a new {@link ConstantPoolVisitor#CONSTANT_NameAndType} value.
*
* @param index an index to a constant pool entry containing a
* {@link ConstantPoolVisitor#CONSTANT_NameAndType} value.
* @param memberName a memberName
* @param signature a signature
* @throws IllegalArgumentException if memberName contains the character ';'
*
* @see ConstantPoolVisitor#visitDescriptor(int, byte, String, String, int, int)
*/
public void putDescriptor(int index, String memberName, String signature) {
checkTag(index, CONSTANT_NameAndType);
checkMemberName(memberName);
patchArray[index] = addSemis(memberName, signature);
}
/** Set the entry of the constant pool indexed by index to
* a new {@link ConstantPoolVisitor#CONSTANT_Fieldref},
* {@link ConstantPoolVisitor#CONSTANT_Methodref}, or
* {@link ConstantPoolVisitor#CONSTANT_InterfaceMethodref} value.
*
* @param index an index to a constant pool entry containing a member reference
* @param className a class name
* @param memberName a field or method name
* @param signature a field or method signature
* @throws IllegalArgumentException if memberName contains the character ';'
* or signature is not a correct signature
*
* @see ConstantPoolVisitor#visitMemberRef(int, byte, String, String, String, int, int)
*/
public void putMemberRef(int index, byte tag,
String className, String memberName, String signature) {
checkTagMask(tag, CONSTANT_MemberRef_MASK);
checkTag(index, tag);
checkClassName(className);
checkMemberName(memberName);
if (signature.startsWith("(") == (tag == CONSTANT_Fieldref))
throw new IllegalArgumentException("bad signature: "+signature);
patchArray[index] = addSemis(className, memberName, signature);
}
static private final int CONSTANT_MemberRef_MASK =
CONSTANT_Fieldref
| CONSTANT_Methodref
| CONSTANT_InterfaceMethodref;
private static final Map<Class<?>, Byte> CONSTANT_VALUE_CLASS_TAG
= new IdentityHashMap<Class<?>, Byte>();
private static final Class<?>[] CONSTANT_VALUE_CLASS = new Class<?>[16];
static {
Object[][] values = {
{Integer.class, CONSTANT_Integer},
{Long.class, CONSTANT_Long},
{Float.class, CONSTANT_Float},
{Double.class, CONSTANT_Double},
{String.class, CONSTANT_String},
{Class.class, CONSTANT_Class}
};
for (Object[] value : values) {
Class<?> cls = (Class<?>)value[0];
Byte tag = (Byte) value[1];
CONSTANT_VALUE_CLASS_TAG.put(cls, tag);
CONSTANT_VALUE_CLASS[(byte)tag] = cls;
}
}
static Class<?> classForTag(byte tag) {
if ((tag & 0xFF) >= CONSTANT_VALUE_CLASS.length)
return null;
return CONSTANT_VALUE_CLASS[tag];
}
static byte tagForConstant(Class<?> cls) {
Byte tag = CONSTANT_VALUE_CLASS_TAG.get(cls);
return (tag == null) ? CONSTANT_None : (byte)tag;
}
private static void checkClassName(String className) {
if (className.indexOf('/') >= 0 || className.indexOf(';') >= 0)
throw new IllegalArgumentException("invalid class name " + className);
}
static String addSemis(String name, String... names) {
StringBuilder buf = new StringBuilder(name.length() * 5);
buf.append(name);
for (String name2 : names) {
buf.append(';').append(name2);
}
String res = buf.toString();
assert(stripSemis(names.length, res)[0].equals(name));
assert(stripSemis(names.length, res)[1].equals(names[0]));
assert(names.length == 1 ||
stripSemis(names.length, res)[2].equals(names[1]));
return res;
}
static String[] stripSemis(int count, String string) {
String[] res = new String[count+1];
int pos = 0;
for (int i = 0; i < count; i++) {
int pos2 = string.indexOf(';', pos);
if (pos2 < 0) pos2 = string.length(); // yuck
res[i] = string.substring(pos, pos2);
pos = pos2;
}
res[count] = string.substring(pos);
return res;
}
public String toString() {
StringBuilder buf = new StringBuilder(this.getClass().getName());
buf.append("{");
Object[] origCP = null;
for (int i = 0; i < patchArray.length; i++) {
if (patchArray[i] == null) continue;
if (origCP != null) {
buf.append(", ");
} else {
try {
origCP = getOriginalCP();
} catch (InvalidConstantPoolFormatException ee) {
origCP = new Object[0];
}
}
Object orig = (i < origCP.length) ? origCP[i] : "?";
buf.append(orig).append("=").append(patchArray[i]);
}
buf.append("}");
return buf.toString();
}
}
/*
* Copyright (c) 2008, 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.invoke.anon;
/**
* A visitor called by {@link ConstantPoolParser#parse(ConstantPoolVisitor)}
* when a constant pool entry is parsed.
* <p>
* A visit* method is called when a constant pool entry is parsed.
* The first argument is always the constant pool index.
* The second argument is always the constant pool tag,
* even for methods like {@link #visitUTF8(int, byte, String)} which only apply to one tag.
* String arguments refer to Utf8 or NameAndType entries declared elsewhere,
* and are always accompanied by the indexes of those entries.
* <p>
* The order of the calls to the visit* methods is not necessarily related
* to the order of the entries in the constant pool.
* If one entry has a reference to another entry, the latter (lower-level)
* entry will be visited first.
* <p>
* The following table shows the relation between constant pool entry
* types and the corresponding visit* methods:
*
* <table border=1 cellpadding=5 summary="constant pool visitor methods">
* <tr><th>Tag(s)</th><th>Method</th></tr>
* <tr>
* <td>{@link #CONSTANT_Utf8}</td>
* <td>{@link #visitUTF8(int, byte, String)}</td>
* </tr><tr>
* <td>{@link #CONSTANT_Integer}, {@link #CONSTANT_Float},
* {@link #CONSTANT_Long}, {@link #CONSTANT_Double}</td>
* <td>{@link #visitConstantValue(int, byte, Object)}</td>
* </tr><tr>
* <td>{@link #CONSTANT_String}, {@link #CONSTANT_Class}</td>
* <td>{@link #visitConstantString(int, byte, String, int)}</td>
* </tr><tr>
* <td>{@link #CONSTANT_NameAndType}</td>
* <td>{@link #visitDescriptor(int, byte, String, String, int, int)}</td>
* </tr><tr>
* <td>{@link #CONSTANT_Fieldref},
* {@link #CONSTANT_Methodref},
* {@link #CONSTANT_InterfaceMethodref}</td>
* <td>{@link #visitMemberRef(int, byte, String, String, String, int, int)}</td>
* </tr>
* </table>
*
* @see ConstantPoolPatch
* @author Remi Forax
* @author jrose
*/
public class ConstantPoolVisitor {
/** Called each time an UTF8 constant pool entry is found.
* @param index the constant pool index
* @param tag always {@link #CONSTANT_Utf8}
* @param utf8 string encoded in modified UTF-8 format passed as a {@code String}
*
* @see ConstantPoolPatch#putUTF8(int, String)
*/
public void visitUTF8(int index, byte tag, String utf8) {
// do nothing
}
/** Called for each constant pool entry that encodes an integer,
* a float, a long, or a double.
* Constant strings and classes are not managed by this method but
* by {@link #visitConstantString(int, byte, String, int)}.
*
* @param index the constant pool index
* @param tag one of {@link #CONSTANT_Integer},
* {@link #CONSTANT_Float},
* {@link #CONSTANT_Long},
* or {@link #CONSTANT_Double}
* @param value encoded value
*
* @see ConstantPoolPatch#putConstantValue(int, Object)
*/
public void visitConstantValue(int index, byte tag, Object value) {
// do nothing
}
/** Called for each constant pool entry that encodes a string or a class.
* @param index the constant pool index
* @param tag one of {@link #CONSTANT_String},
* {@link #CONSTANT_Class},
* @param name string body or class name (using dot separator)
* @param nameIndex the index of the Utf8 string for the name
*
* @see ConstantPoolPatch#putConstantValue(int, byte, Object)
*/
public void visitConstantString(int index, byte tag,
String name, int nameIndex) {
// do nothing
}
/** Called for each constant pool entry that encodes a name and type.
* @param index the constant pool index
* @param tag always {@link #CONSTANT_NameAndType}
* @param memberName a field or method name
* @param signature the member signature
* @param memberNameIndex index of the Utf8 string for the member name
* @param signatureIndex index of the Utf8 string for the signature
*
* @see ConstantPoolPatch#putDescriptor(int, String, String)
*/
public void visitDescriptor(int index, byte tag,
String memberName, String signature,
int memberNameIndex, int signatureIndex) {
// do nothing
}
/** Called for each constant pool entry that encodes a field or method.
* @param index the constant pool index
* @param tag one of {@link #CONSTANT_Fieldref},
* or {@link #CONSTANT_Methodref},
* or {@link #CONSTANT_InterfaceMethodref}
* @param className the class name (using dot separator)
* @param memberName name of the field or method
* @param signature the field or method signature
* @param classNameIndex index of the Utf8 string for the class name
* @param descriptorIndex index of the NameAndType descriptor constant
*
* @see ConstantPoolPatch#putMemberRef(int, byte, String, String, String)
*/
public void visitMemberRef(int index, byte tag,
String className, String memberName, String signature,
int classNameIndex, int descriptorIndex) {
// do nothing
}
public static final byte
CONSTANT_None = 0,
CONSTANT_Utf8 = 1,
//CONSTANT_Unicode = 2, /* unused */
CONSTANT_Integer = 3,
CONSTANT_Float = 4,
CONSTANT_Long = 5,
CONSTANT_Double = 6,
CONSTANT_Class = 7,
CONSTANT_String = 8,
CONSTANT_Fieldref = 9,
CONSTANT_Methodref = 10,
CONSTANT_InterfaceMethodref = 11,
CONSTANT_NameAndType = 12;
private static String[] TAG_NAMES = {
"Empty",
"Utf8",
null, //"Unicode",
"Integer",
"Float",
"Long",
"Double",
"Class",
"String",
"Fieldref",
"Methodref",
"InterfaceMethodref",
"NameAndType"
};
public static String tagName(byte tag) {
String name = null;
if ((tag & 0xFF) < TAG_NAMES.length)
name = TAG_NAMES[tag];
if (name == null)
name = "Unknown#"+(tag&0xFF);
return name;
}
}
/*
* Copyright (c) 1998, 2014, 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.
*
* 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.
*/
import java.nio.ByteBuffer;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
/**
* @test
* @bug 8048603
* @summary Checks if MAC algorithms work fine with empty buffer
* @author Alexander Fomin
* @build Utils
* @run main EmptyByteBufferTest
*/
public class EmptyByteBufferTest implements MacTest {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Utils.runTests(new EmptyByteBufferTest());
}
@Override
public void doTest(String alg) throws NoSuchAlgorithmException,
InvalidKeyException, NoSuchProviderException {
SecretKey key = Utils.getSecretKeySpec();
// instantiate Mac object and init it with a SecretKey
Mac mac = Mac.getInstance(alg, "SunJCE");
mac.init(key);
// prepare buffer
byte[] data = new byte[0];
ByteBuffer buf = ByteBuffer.wrap(data);
mac.update(buf);
mac.doFinal();
}
}
/*
* Copyright (c) 1998, 2014, 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.
*
* 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.
*/
import java.nio.ByteBuffer;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
/**
* @test
* @bug 8048603
* @summary Checks if PBE algorithms work fine with large buffer
* @author Alexander Fomin
* @build Utils
* @run main LargeByteBufferTest
*/
public class LargeByteBufferTest implements MacTest {
private static final int BUFFER_SIZE = 65535;
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Utils.runTests(new LargeByteBufferTest());
}
@Override
public void doTest(String alg) throws NoSuchAlgorithmException,
InvalidKeyException, NoSuchProviderException {
SecretKey key = Utils.getSecretKeySpec();
// instantiate Mac object and init it with a SecretKey
Mac mac = Mac.getInstance(alg, "SunJCE");
mac.init(key);
// prepare buffer
byte[] data = new byte[BUFFER_SIZE];
for (int i = 0; i < BUFFER_SIZE; i++) {
data[i] = (byte) (i % 256);
}
ByteBuffer buf = ByteBuffer.wrap(data);
int limitBefore = buf.limit();
mac.update(buf);
mac.doFinal();
int limitAfter = buf.limit();
int positonAfter = buf.position();
if (limitAfter != limitBefore) {
System.out.println("limit after = " + limitAfter);
System.out.println("limit before = " + limitBefore);
throw new RuntimeException("Test failed: "
+ "limit of buffer has been chenged.");
}
if (positonAfter != limitAfter) {
System.out.println("position after = " + positonAfter);
System.out.println("limit after = " + limitAfter);
throw new RuntimeException("Test failed: "
+ "position of buffer isn't equal to its limit");
}
}
}
/*
* Copyright (c) 1998, 2014, 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.
*
* 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.
*/
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
/**
* @test
* @bug 8048603
* @summary Check if doFinal and update operation result in same Mac
* @author Yu-Ching Valerie Peng, Bill Situ, Alexander Fomin
* @build Utils
* @run main MacSameTest
*/
public class MacSameTest implements MacTest {
private static final int MESSAGE_SIZE = 25;
private static final int OFFSET = 5;
private static final int KEY_SIZE = 70;
/**
* Initialize a message, instantiate a Mac object,
* initialize the object with a SecretKey,
* feed the message into the Mac object
* all at once and get the output MAC as result1.
* Reset the Mac object, chop the message into three pieces,
* feed into the Mac object sequentially, and get the output MAC as result2.
* Finally, compare result1 and result2 and see if they are the same.
*
* @param args the command line arguments
*/
public static void main(String[] args) {
Utils.runTests(new MacSameTest());
}
@Override
public void doTest(String algo) throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidKeyException {
Mac mac;
try {
mac = Mac.getInstance(algo, "SunJCE");
} catch (NoSuchAlgorithmException nsae) {
// depending on Solaris configuration,
// it can support HMAC or not with Mac
System.out.println("Expected NoSuchAlgorithmException thrown: "
+ nsae);
return;
}
byte[] plain = new byte[MESSAGE_SIZE];
for (int i = 0; i < MESSAGE_SIZE; i++) {
plain[i] = (byte) (i % 256);
}
byte[] tail = new byte[plain.length - OFFSET];
System.arraycopy(plain, OFFSET, tail, 0, tail.length);
SecureRandom srdm = new SecureRandom();
byte[] keyVal = new byte[KEY_SIZE];
srdm.nextBytes(keyVal);
SecretKeySpec keySpec = new SecretKeySpec(keyVal, "HMAC");
mac.init(keySpec);
byte[] result1 = mac.doFinal(plain);
mac.reset();
mac.update(plain[0]);
mac.update(plain, 1, OFFSET - 1);
byte[] result2 = mac.doFinal(tail);
if (!java.util.Arrays.equals(result1, result2)) {
throw new RuntimeException("result1 and result2 are not the same");
}
}
}
/*
* Copyright (c) 1998, 2014, 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.
*
* 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.
*/
import java.nio.ByteBuffer;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
/**
* @test
* @bug 8048603
* @summary Checks if PBE algorithms work fine with null buffer
* @author Alexander Fomin
* @build Utils
* @run main NullByteBufferTest
*/
public class NullByteBufferTest implements MacTest {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Utils.runTests(new NullByteBufferTest());
}
@Override
public void doTest(String alg) throws NoSuchAlgorithmException,
InvalidKeyException, NoSuchProviderException {
SecretKey key = Utils.getSecretKeySpec();
// instantiate Mac object and init it with a SecretKey
Mac mac = Mac.getInstance(alg, "SunJCE");
mac.init(key);
try {
ByteBuffer buf = null;
mac.update(buf);
mac.doFinal();
throw new RuntimeException(
"Expected IllegalArgumentException not thrown");
} catch (IllegalArgumentException e) {
System.out.println("Expected IllegalArgumentException thrown: "
+ e);
}
}
}
/*
* Copyright (c) 1998, 2014, 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.
*
* 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.
*/
import java.security.SecureRandom;
import javax.crypto.spec.SecretKeySpec;
/**
* Helper class.
*/
class Utils {
static final int KEY_SIZE = 70;
static final String[] MAC_ALGOS = {"HmacMD5", "HmacSHA1", "HmacSHA224",
"HmacSHA256", "HmacSHA384", "HmacSHA512"};
/**
* Get SecretKeySpec.
*/
static SecretKeySpec getSecretKeySpec() {
SecureRandom srdm = new SecureRandom();
byte[] keyVal = new byte[KEY_SIZE];
srdm.nextBytes(keyVal);
return new SecretKeySpec(keyVal, "HMAC");
}
static void runTests(MacTest... tests) {
boolean success = true;
for (MacTest test : tests) {
success &= runTest(test);
}
if (success) {
System.out.println("Test passed");
} else {
throw new RuntimeException("Test failed");
}
}
private static boolean runTest(MacTest test) {
boolean success = true;
for (String alg : MAC_ALGOS) {
try {
System.out.println("Test " + alg);
test.doTest(alg);
} catch (Exception e) {
System.out.println("Unexpected exception:");
e.printStackTrace();
success = false;
}
}
return success;
}
}
interface MacTest {
void doTest(String alg) throws Exception;
}
\ No newline at end of file
/*
* Copyright (c) 2015, 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.
*
* 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.
*/
import static java.lang.System.out;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.util.Random;
/**
* @test
* @bug 8050371
* @summary Check md.getDigestLength() equal digest output length with various
* algorithm/dataLen/(update,digest methods).
* @author Kevin Liu
*/
public class TestSameLength {
public static void main(String[] args) throws Exception {
TestSameLength test = new TestSameLength();
test.run();
}
private void run() throws Exception {
String[] algorithmArr = {
"SHA", "Sha", "SHA-1", "sha-1", "SHA1", "sha1", "MD5", "md5",
"SHA-224", "SHA-256", "SHA-384", "SHA-512"
};
int[] nUpdatesArr = {
0, 1, 2, 3
};
int[] dataLenArr = {
1, 50, 2500, 125000, 6250000
};
for (String algorithm: algorithmArr) {
for (UpdateMethod update: UpdateMethod.values()) {
for (int dataLen: dataLenArr) {
if (!runTest(algorithm, dataLen, update)) {
throw new RuntimeException(
"Test failed at algorithm/dataLen/numUpdate:"
+ algorithm + "/" + dataLen + "/"
+ update.toString());
}
}
}
}
out.println("All " + algorithmArr.length * nUpdatesArr.length
* dataLenArr.length + " tests Passed");
}
private boolean runTest(String algo, long dataLen,
UpdateMethod whichUpdate) throws Exception {
try {
// Do initialization
byte[] data = new byte[(int) dataLen];
new Random().nextBytes(data);
MessageDigest md = MessageDigest.getInstance(algo);
int outputLen = md.getDigestLength();
// Perform the update using all available/possible update methods
whichUpdate.updateDigest(data, md, dataLen);
// Get the output
byte[] output = md.digest();
// Compare input and output
return outputLen == output.length;
} catch (Exception ex) {
System.err.println("Testing: " + algo + "/" + dataLen + "/"
+ whichUpdate.toString()
+ " failed with unexpected exception");
ex.printStackTrace();
throw ex;
}
}
private static enum UpdateMethod {
UPDATE_BYTE {
@Override
public void updateDigest(byte[] data,
MessageDigest md, long dataLen) {
for (int i = 0; i < dataLen; i++) {
md.update(data[i]);
}
}
},
UPDATE_BUFFER {
@Override
public void updateDigest(byte[] data,
MessageDigest md, long dataLen) {
md.update(data);
}
},
UPDATE_BUFFER_LEN {
@Override
public void updateDigest(byte[] data,
MessageDigest md, long dataLen) {
for (int i = 0; i < dataLen; i++) {
md.update(data, i, 1);
}
}
},
UPDATE_BYTE_BUFFER {
@Override
public void updateDigest(byte[] data,
MessageDigest md, long dataLen) {
md.update(ByteBuffer.wrap(data));
}
};
public abstract void updateDigest(byte[] data,
MessageDigest md, long dataLen);
}
}
/*
* Copyright (c) 2015, 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.
*
* 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.
*/
import static java.lang.System.out;
import java.nio.ByteBuffer;
import java.security.DigestException;
import java.security.MessageDigest;
import java.util.Random;
/**
* @test
* @bug 8050371
* @summary Check md.digest(data) value whether same with digest output value
* with various update/digest methods.
* @author Kevin Liu
*/
public class TestSameValue {
public static void main(String[] args) throws Exception {
TestSameValue test1 = new TestSameValue();
test1.run();
}
private void run() throws Exception {
byte[] data = new byte[6706];
MessageDigest md = null;
// Initialize input data
new Random().nextBytes(data);
String[] providers = {
null, "SUN"
};
String[] algorithmArr = {
"SHA", "Sha", "MD5", "md5", "SHA-224", "SHA-256", "SHA-384",
"SHA-512"
};
for (String algorithm: algorithmArr) {
for (String provider: providers) {
if (provider != null) {
md = MessageDigest.getInstance(algorithm, provider);
} else {
md = MessageDigest.getInstance(algorithm);
}
for (UpdateDigestMethod updateMethod: UpdateDigestMethod
.values()) {
byte[] output = updateMethod.updateDigest(data, md);
// Get the output and the "correct" one
byte[] standard = md.digest(data);
// Compare input and output
if (!MessageDigest.isEqual(output, standard)) {
throw new RuntimeException(
"Test failed at algorithm/provider/numUpdate:"
+ algorithm + "/" + provider + "/"
+ updateMethod);
}
}
}
}
out.println("All " + algorithmArr.length
* UpdateDigestMethod.values().length * providers.length
+ " tests Passed");
}
private static enum UpdateDigestMethod {
/*
* update the data one by one using method update(byte input) then
* do digest (giving the output buffer, offset, and the number of
* bytes to put in the output buffer)
*/
UPDATE_DIGEST_BUFFER {
@Override
public byte[] updateDigest(byte[] data, MessageDigest md)
throws DigestException {
for (byte element: data) {
md.update(element);
}
byte[] output = new byte[md.getDigestLength()];
int len = md.digest(output, 0, output.length);
if (len != output.length) {
throw new RuntimeException(
"ERROR" + ": digest length differs!");
}
return output;
}
},
/*
* update the data one by one using method update(byte input)
* then do digest
*/
UPDATE_DIGEST {
@Override
public byte[] updateDigest(byte[] data, MessageDigest md) {
for (byte element: data) {
md.update(element);
}
return md.digest();
}
},
/*
* update all the data at once as a block, then do digest ( giving the
* output buffer, offset, and the number of bytes to put in the output
* buffer)
*/
UPDATE_BLOCK_DIGEST_BUFFER {
@Override
public byte[] updateDigest(byte[] data, MessageDigest md)
throws DigestException {
md.update(data);
byte[] output = new byte[md.getDigestLength()];
int len = md.digest(output, 0, output.length);
if (len != output.length) {
throw new RuntimeException(
"ERROR" + ": digest length differs!");
}
return output;
}
},
// update all the data at once as a block, then do digest
UPDATE_BLOCK_DIGEST {
@Override
public byte[] updateDigest(byte[] data, MessageDigest md) {
md.update(data);
return md.digest();
}
},
/*
* update the leading bytes (length is "data.length-LASTNBYTES")
* at once as a block, then do digest (do a final update using
* the left LASTNBYTES bytes which is passed as a parameter for
* the digest method, then complete the digest)
*/
UPDATE_LEADING_BLOCK_DIGEST_REMAIN {
@Override
public byte[] updateDigest(byte[] data, MessageDigest md) {
byte[] mainPart = new byte[data.length - LASTNBYTES];
for (int i = 0; i < mainPart.length; i++) {
mainPart[i] = data[i];
}
for (int j = 0; j < LASTNBYTES; j++) {
REMAIN[j] = data[data.length - LASTNBYTES + j];
}
md.update(mainPart);
return md.digest(REMAIN);
}
},
/*
* update the data 2 bytes each time, after finishing updating,
* do digest (giving the output buffer, offset, and the number
* of bytes to put in the output buffer)
*/
UPDATE_BYTES_DIGEST_BUFFER {
@Override
public byte[] updateDigest(byte[] data, MessageDigest md)
throws DigestException {
for (int i = 0; i < data.length / 2; i++) {
md.update(data, i * 2, 2);
}
byte[] output = new byte[md.getDigestLength()];
int len = md.digest(output, 0, output.length);
if (len != output.length) {
throw new RuntimeException(
"ERROR" + ": digest length differs!");
}
return output;
}
},
/*
* update the data 2 bytes each time, after finishing updating,
* do digest
*/
UPDATE_BYTES_DIGEST {
@Override
public byte[] updateDigest(byte[] data, MessageDigest md) {
for (int i=0;i<data.length/2;i++){
md.update(data,i*2,2);
}
return md.digest();
}
},
/*
* update the data one by one using method update(byte[] input,
* int offset, int len) for the leading bytes (length is
* "data.length-LASTNBYTES"), then do digest (do a final
* update using the left LASTNBYTES bytes which is passed
* as a parameter for digest method then complete the digest)
*/
UPDATE_BUFFER_LEADING_DIGEST_REMAIN {
@Override
public byte[] updateDigest(byte[] data, MessageDigest md) {
for (int i = 0; i < data.length - LASTNBYTES; i++) {
md.update(data, i, 1);
}
for (int j = 0; j < LASTNBYTES; j++) {
REMAIN[j] = data[data.length - LASTNBYTES + j];
}
return md.digest(REMAIN);
}
},
/*
* update the data one by one using method update(byte input)
* for the leading bytes (length is "data.length-LASTNBYTES"),
* then do digest (do a final update using the left LASTNBYTES
* bytes which is passed as a parameter for digest method,
* then complete the digest)
*/
UPDATE_LEADING_DIGEST_REMAIN {
@Override
public byte[] updateDigest(byte[] data, MessageDigest md) {
for (int i = 0; i < data.length - LASTNBYTES; i++) {
md.update(data[i]);
}
for (int j = 0; j < LASTNBYTES; j++) {
REMAIN[j] = data[data.length - LASTNBYTES + j];
}
return md.digest(REMAIN);
}
},
/*
* update all the data at once as a ByteBuffer, then do digest
* (giving the output buffer, offset, and the number of bytes
* to put in the output buffer)
*/
UPDATE_BYTE_BUFFER_DIGEST_BUFFER {
@Override
public byte[] updateDigest(byte[] data, MessageDigest md)
throws DigestException {
md.update(ByteBuffer.wrap(data));
byte[] output = new byte[md.getDigestLength()];
int len = md.digest(output, 0, output.length);
if (len != output.length) {
throw new RuntimeException(
"ERROR" + ": digest length differs!");
}
return output;
}
},
// update all the data at once as a ByteBuffer, then do digest
UPDATE_BYTE_BUFFER_DIGEST {
@Override
public byte[] updateDigest(byte[] data, MessageDigest md) {
md.update(ByteBuffer.wrap(data));
return md.digest();
}
},
/*
* update the leading bytes (length is "data.length-LASTNBYTES")
* at once as a ByteBuffer, then do digest (do a final update
* using the left LASTNBYTES bytes which is passed as a parameter
* for the digest method, then complete the digest)
*/
UPDATE_BYTE_BUFFER_LEADING_DIGEST_REMAIN {
@Override
public byte[] updateDigest(byte[] data, MessageDigest md) {
byte[] mainPart = new byte[data.length - LASTNBYTES];
for (int i = 0; i < mainPart.length; i++) {
mainPart[i] = data[i];
}
for (int j = 0; j < LASTNBYTES; j++) {
REMAIN[j] = data[data.length - LASTNBYTES + j];
}
md.update(ByteBuffer.wrap(mainPart));
return md.digest(REMAIN);
}
};
private static final int LASTNBYTES = 5;
private static final byte[] REMAIN = new byte[LASTNBYTES];
public abstract byte[] updateDigest(byte[] data, MessageDigest md)
throws DigestException;
}
}
/*
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 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.
* 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
......@@ -23,23 +21,30 @@
* questions.
*/
package sun.invoke.anon;
/** Exception used when there is an error in the constant pool
* format.
/*
* @test
* @bug 8151431
* @summary Make sure that clone() of a DateFormatSymbols subclass is not
* called from DateFormatSymbols constructor.
*/
public class InvalidConstantPoolFormatException extends Exception {
private static final long serialVersionUID=-6103888330523770949L;
import java.text.DateFormatSymbols;
public class DateFormatSymbolsCloneTest extends DateFormatSymbols {
private int value;
public InvalidConstantPoolFormatException(String message,Throwable cause) {
super(message,cause);
public DateFormatSymbolsCloneTest() {
value = 1;
}
public InvalidConstantPoolFormatException(String message) {
super(message);
@Override
public Object clone() {
if (this.value == 0) {
throw new RuntimeException("clone() should not be called from a DateFormatSymbols constructor");
}
return super.clone();
}
public InvalidConstantPoolFormatException(Throwable cause) {
super(cause);
public static void main(String[] args) {
new DateFormatSymbolsCloneTest();
}
}
/*
* Copyright (c) 2015, 2016, 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.
*
* 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.
*/
/*
* @test
* @bug 8048357
* @summary test DER encoding of PKCS10 attributes
* @compile -XDignore.symbol.file PKCS10AttrEncoding.java
* @run main PKCS10AttrEncoding
*/
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.Signature;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.HashMap;
import sun.security.pkcs.PKCS9Attribute;
import sun.security.pkcs10.PKCS10;
import sun.security.pkcs10.PKCS10Attribute;
import sun.security.pkcs10.PKCS10Attributes;
import sun.security.util.ObjectIdentifier;
import sun.security.x509.X500Name;
import sun.security.x509.X509Key;
public class PKCS10AttrEncoding {
static final ObjectIdentifier[] ids = {
PKCS9Attribute.CONTENT_TYPE_OID, // ContentType
PKCS9Attribute.SIGNING_TIME_OID, // SigningTime
PKCS9Attribute.CHALLENGE_PASSWORD_OID // ChallengePassword
};
static int failedCount = 0;
static HashMap<ObjectIdentifier, Object> constructedMap = new HashMap<>();
public static void main(String[] args) throws Exception {
// initializations
int len = ids.length;
Object[] values = {
new ObjectIdentifier("1.2.3.4"),
new GregorianCalendar(1970, 1, 25, 8, 56, 7).getTime(),
"challenging"
};
for (int j = 0; j < len; j++) {
constructedMap.put(ids[j], values[j]);
}
X500Name subject = new X500Name("cn=Test");
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
String sigAlg = "DSA";
keyGen.initialize(512);
KeyPair pair = keyGen.generateKeyPair();
X509Key publicKey = (X509Key) pair.getPublic();
PrivateKey privateKey = pair.getPrivate();
Signature signature = Signature.getInstance(sigAlg);
signature.initSign(privateKey);
// Create the PKCS10 request
PKCS10Attribute[] attrs = new PKCS10Attribute[len];
for (int j = 0; j < len; j++) {
attrs[j] = new PKCS10Attribute(ids[j], values[j]);
}
PKCS10 req = new PKCS10(publicKey, new PKCS10Attributes(attrs));
System.out.println("List of attributes in constructed PKCS10 "
+ "request: ");
checkAttributes(req.getAttributes().getElements());
// Encode the PKCS10 request and generate another PKCS10 request from
// the encoded byte array
req.encodeAndSign(subject, signature);
PKCS10 resp = new PKCS10(req.getEncoded());
System.out.println("List of attributes in DER encoded PKCS10 Request:");
checkAttributes(resp.getAttributes().getElements());
if (failedCount > 0) {
throw new RuntimeException("Attributes Compared : Failed");
}
System.out.println("Attributes Compared : Pass");
}
static void checkAttributes(Enumeration attrs) {
int numOfAttrs = 0;
while (attrs.hasMoreElements()) {
numOfAttrs ++;
PKCS10Attribute attr = (PKCS10Attribute) attrs.nextElement();
if (constructedMap.containsKey(attr.getAttributeId())) {
if (constructedMap.get(attr.getAttributeId()).
equals(attr.getAttributeValue())) {
System.out.print("AttributeId: " + attr.getAttributeId());
System.out.println(" AttributeValue: "
+ attr.getAttributeValue());
} else {
failedCount++;
System.out.print("< AttributeId: " + attr.getAttributeId());
System.out.println(" AttributeValue: " + constructedMap.
get(attr.getAttributeId()));
System.out.print("< AttributeId: " + attr.getAttributeId());
System.out.println(" AttributeValue: "
+ attr.getAttributeValue());
}
} else {
failedCount++;
System.out.println("No " + attr.getAttributeId()
+ " in DER encoded PKCS10 Request");
}
}
if(numOfAttrs != constructedMap.size()){
failedCount++;
System.out.println("Incorrect number of attributes.");
}
System.out.println();
}
}
/*
* Copyright (c) 2015, 2016, 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.
*
* 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.
*/
/*
* @test
* @bug 8048357
* @summary Read in a file containing a DER encoded PKCS10 certificate request,
* flanked with "begin" and "end" lines.
* @compile -XDignore.symbol.file PKCS10AttributeReader.java
* @run main PKCS10AttributeReader
*/
import java.util.Base64;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Date;
import sun.security.pkcs.PKCS9Attribute;
import sun.security.pkcs10.PKCS10Attribute;
import sun.security.pkcs10.PKCS10Attributes;
import sun.security.util.DerInputStream;
import sun.security.util.ObjectIdentifier;
/*
Tests only reads DER encoding files, contents of corresponding asn.1 files
are copied below for reference.
# An attribute set for testing with PKCS10.
{A0 # implicit tag
{SEQ # Content Type
{OID 1.2.840.113549.1.9.3}
{SET
{OID "1234"}
}
}
{SEQ # Challenge Password
{OID 1.2.840.113549.1.9.7}
{SET
{T61String "GuessWhoAmI"}
}
}
{SEQ # Signing Time
{OID 1.2.840.113549.1.9.5}
{SET
{UTCTime "970422145010Z"}
}
}
}
*/
public class PKCS10AttributeReader {
// DER encoded files are binary files, to avoid attaching binary files,
// DER files were encoded in base64
static final String ATTRIBS = "oE8wEwYJKoZIhvcNAQkDMQYGBDEyMzQwGgYJKoZIhv"
+ "cNAQkHMQ0UC0d1ZXNzV2hv\nQW1JMBwGCSqGSIb3DQEJBTEPFw05NzA0MjIxND"
+ "UwMTBa";
public static void main(String[] args) throws Exception {
// Decode base64 encoded DER file
byte[] pkcs10Bytes = Base64.getMimeDecoder().decode(ATTRIBS.getBytes());
HashMap<ObjectIdentifier, Object> RequestStander = new HashMap() {
{
put(PKCS9Attribute.CHALLENGE_PASSWORD_OID, "GuessWhoAmI");
put(PKCS9Attribute.SIGNING_TIME_OID, new Date(861720610000L));
put(PKCS9Attribute.CONTENT_TYPE_OID,
new ObjectIdentifier("1.9.50.51.52"));
}
};
int invalidNum = 0;
PKCS10Attributes resp = new PKCS10Attributes(
new DerInputStream(pkcs10Bytes));
Enumeration eReq = resp.getElements();
int numOfAttrs = 0;
while (eReq.hasMoreElements()) {
numOfAttrs++;
PKCS10Attribute attr = (PKCS10Attribute) eReq.nextElement();
if (RequestStander.containsKey(attr.getAttributeId())) {
if (RequestStander.get(attr.getAttributeId())
.equals(attr.getAttributeValue())) {
System.out.println(attr.getAttributeId() + " "
+ attr.getAttributeValue());
} else {
invalidNum++;
System.out.println("< " + attr.getAttributeId() + " "
+ attr.getAttributeValue());
System.out.println("< " + attr.getAttributeId() + " "
+ RequestStander.get(attr.getAttributeId()));
}
} else {
invalidNum++;
System.out.println("No" + attr.getAttributeId()
+ "in Certificate Request list");
}
}
if (numOfAttrs != RequestStander.size()) {
invalidNum++;
System.out.println("Incorrect number of attributes.");
}
System.out.println();
if (invalidNum > 0) {
throw new RuntimeException(
"Attributes Compared with Stander :" + " Failed");
}
System.out.println("Attributes Compared with Stander: Pass");
}
}
/*
* Copyright (c) 2015, 2016, 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.
*
* 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.
*/
/*
* @test
* @bug 8048357
* @summary Read signed data in one or more PKCS7 objects from individual files,
* verify SignerInfos and certificate chain.
* @run main PKCS7VerifyTest PKCS7TEST.DSA.base64
* @run main PKCS7VerifyTest PKCS7TEST.DSA.base64 PKCS7TEST.SF
*/
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
public class PKCS7VerifyTest {
static final String TESTSRC = System.getProperty("test.src", ".");
static final String FS = File.separator;
static final String FILEPATH = TESTSRC + FS + "jarsigner" + FS + "META-INF"
+ FS;
public static void main(String[] args) throws Exception {
if (args.length == 0) {
throw new RuntimeException("usage: java JarVerify <file1> <file2>");
}
// The command " java PKCS7VerifyTest file1 [file2] "
// treats file1 as containing the DER encoding of a PKCS7 signed data
// object. If file2 is absent, the program verifies that some signature
// (SignerInfo) file1 correctly signs the data contained in the
// ContentInfo component of the PKCS7 object encoded by file1. If file2
// is present, the program verifies file1 contains a correct signature
// for the contents of file2.
PKCS7 pkcs7;
byte[] data;
// to avoid attaching binary DSA file, the DSA file was encoded
// in Base64, decode encoded Base64 DSA file below
byte[] base64Bytes = Files.readAllBytes(Paths.get(FILEPATH + args[0]));
pkcs7 = new PKCS7(new ByteArrayInputStream(
Base64.getMimeDecoder().decode(base64Bytes)));
if (args.length < 2) {
data = null;
} else {
data = Files.readAllBytes(Paths.get(FILEPATH + args[1]));
}
SignerInfo[] signerInfos = pkcs7.verify(data);
if (signerInfos == null) {
throw new RuntimeException("no signers verify");
}
System.out.println("Verifying SignerInfos:");
for (SignerInfo signerInfo : signerInfos) {
System.out.println(signerInfo.toString());
}
X509Certificate certs[] = pkcs7.getCertificates();
HashMap<String, X509Certificate> certTable = new HashMap(certs.length);
for (X509Certificate cert : certs) {
certTable.put(cert.getSubjectDN().toString(), cert);
}
// try to verify all the certs
for (Map.Entry<String, X509Certificate> entry : certTable.entrySet()) {
X509Certificate cert = entry.getValue();
X509Certificate issuerCert = certTable
.get(cert.getIssuerDN().toString());
System.out.println("Subject: " + cert.getSubjectDN());
if (issuerCert == null) {
System.out.println("Issuer certificate not found");
} else {
System.out.println("Issuer: " + cert.getIssuerDN());
cert.verify(issuerCert.getPublicKey());
System.out.println("Cert verifies.");
}
System.out.println();
}
}
}
/*
* Copyright (c) 2015, 2016, 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.
*
* 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.
*/
/*
* @test
* @bug 8048357
* @summary test PKCS7 data signing, encoding and verification
* @run main SignerOrder
*/
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.X509Certificate;
import java.util.Date;
import sun.misc.HexDumpEncoder;
import sun.security.pkcs.ContentInfo;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
import sun.security.util.DerOutputStream;
import sun.security.x509.AlgorithmId;
import sun.security.x509.CertificateAlgorithmId;
import sun.security.x509.CertificateSerialNumber;
import sun.security.x509.CertificateValidity;
import sun.security.x509.CertificateVersion;
import sun.security.x509.CertificateX509Key;
import sun.security.x509.X500Name;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CertInfo;
import sun.security.x509.X509Key;
public class SignerOrder {
static final HexDumpEncoder hexDump = new HexDumpEncoder();
//signer infos
static final byte[] data1 = "12345".getBytes();
static final byte[] data2 = "abcde".getBytes();
public static void main(String[] argv) throws Exception {
SignerInfo[] signerInfos = new SignerInfo[9];
SimpleSigner signer1 = new SimpleSigner(null, null, null, null);
signerInfos[8] = signer1.genSignerInfo(data1);
signerInfos[7] = signer1.genSignerInfo(new byte[]{});
signerInfos[6] = signer1.genSignerInfo(data2);
SimpleSigner signer2 = new SimpleSigner(null, null, null, null);
signerInfos[5] = signer2.genSignerInfo(data1);
signerInfos[4] = signer2.genSignerInfo(new byte[]{});
signerInfos[3] = signer2.genSignerInfo(data2);
SimpleSigner signer3 = new SimpleSigner(null, null, null, null);
signerInfos[2] = signer3.genSignerInfo(data1);
signerInfos[1] = signer3.genSignerInfo(new byte[]{});
signerInfos[0] = signer3.genSignerInfo(data2);
ContentInfo contentInfo = new ContentInfo(data1);
AlgorithmId[] algIds = {new AlgorithmId(AlgorithmId.SHA256_oid)};
X509Certificate[] certs = {signer3.getCert(), signer2.getCert(),
signer1.getCert()};
PKCS7 pkcs71 = new PKCS7(algIds, contentInfo,
certs,
signerInfos);
System.out.println("SignerInfos in original.");
printSignerInfos(pkcs71.getSignerInfos());
DerOutputStream out = new DerOutputStream();
pkcs71.encodeSignedData(out);
PKCS7 pkcs72 = new PKCS7(out.toByteArray());
System.out.println("\nSignerInfos read back in:");
printSignerInfos(pkcs72.getSignerInfos());
System.out.println("Verified signers of original:");
SignerInfo[] verifs1 = pkcs71.verify();
System.out.println("Verified signers of after read-in:");
SignerInfo[] verifs2 = pkcs72.verify();
if (verifs1.length != verifs2.length) {
throw new RuntimeException("Length or Original vs read-in "
+ "should be same");
}
}
static void printSignerInfos(SignerInfo signerInfo) throws IOException {
ByteArrayOutputStream strm = new ByteArrayOutputStream();
signerInfo.derEncode(strm);
System.out.println("SignerInfo, length: "
+ strm.toByteArray().length);
System.out.println(hexDump.encode(strm.toByteArray()));
System.out.println("\n");
strm.reset();
}
static void printSignerInfos(SignerInfo[] signerInfos) throws IOException {
ByteArrayOutputStream strm = new ByteArrayOutputStream();
for (int i = 0; i < signerInfos.length; i++) {
signerInfos[i].derEncode(strm);
System.out.println("SignerInfo[" + i + "], length: "
+ strm.toByteArray().length);
System.out.println(hexDump.encode(strm.toByteArray()));
System.out.println("\n");
strm.reset();
}
}
}
/**
* A simple extension of sun.security.x509.X500Signer that adds a no-fuss
* signing algorithm.
*/
class SimpleSigner {
private final Signature sig;
private final X500Name agent;
private final AlgorithmId digestAlgId;
private final AlgorithmId encryptionAlgId;
private final AlgorithmId algId; // signature algid;
//combines digest + encryption
private final X509Key publicKey;
private final PrivateKey privateKey;
private final X509Certificate cert;
public SimpleSigner(String digestAlg,
String encryptionAlg,
KeyPair keyPair,
X500Name agent) throws Exception {
if (agent == null) {
agent = new X500Name("cn=test");
}
if (digestAlg == null) {
digestAlg = "SHA";
}
if (encryptionAlg == null) {
encryptionAlg = "DSA";
}
if (keyPair == null) {
KeyPairGenerator keyGen =
KeyPairGenerator.getInstance(encryptionAlg);
keyGen.initialize(1024);
keyPair = keyGen.generateKeyPair();
}
publicKey = (X509Key) keyPair.getPublic();
privateKey = keyPair.getPrivate();
if ("DSA".equals(encryptionAlg)) {
this.sig = Signature.getInstance(encryptionAlg);
} else { // RSA
this.sig = Signature.getInstance(digestAlg + "/" + encryptionAlg);
}
this.sig.initSign(privateKey);
this.agent = agent;
this.digestAlgId = AlgorithmId.get(digestAlg);
this.encryptionAlgId = AlgorithmId.get(encryptionAlg);
this.algId = AlgorithmId.get(this.sig.getAlgorithm());
this.cert = getSelfCert();
}
/**
* Take the data and sign it.
*
* @param buf buffer holding the next chunk of the data to be signed
* @param offset starting point of to-be-signed data
* @param len how many bytes of data are to be signed
* @return the signature for the input data.
* @exception SignatureException on errors.
*/
public byte[] simpleSign(byte[] buf, int offset, int len)
throws SignatureException {
sig.update(buf, offset, len);
return sig.sign();
}
/**
* Returns the digest algorithm used to sign.
*/
public AlgorithmId getDigestAlgId() {
return digestAlgId;
}
/**
* Returns the encryption algorithm used to sign.
*/
public AlgorithmId getEncryptionAlgId() {
return encryptionAlgId;
}
/**
* Returns the name of the signing agent.
*/
public X500Name getSigner() {
return agent;
}
public X509Certificate getCert() {
return cert;
}
private X509Certificate getSelfCert() throws Exception {
long validity = 1000;
X509CertImpl certLocal;
Date firstDate, lastDate;
firstDate = new Date();
lastDate = new Date();
lastDate.setTime(lastDate.getTime() + validity + 1000);
CertificateValidity interval = new CertificateValidity(firstDate,
lastDate);
X509CertInfo info = new X509CertInfo();
// Add all mandatory attributes
info.set(X509CertInfo.VERSION,
new CertificateVersion(CertificateVersion.V1));
info.set(X509CertInfo.SERIAL_NUMBER,
new CertificateSerialNumber(
(int) (firstDate.getTime() / 1000)));
info.set(X509CertInfo.ALGORITHM_ID,
new CertificateAlgorithmId(algId));
info.set(X509CertInfo.SUBJECT, agent);
info.set(X509CertInfo.KEY, new CertificateX509Key(publicKey));
info.set(X509CertInfo.VALIDITY, interval);
info.set(X509CertInfo.ISSUER, agent);
certLocal = new X509CertImpl(info);
certLocal.sign(privateKey, algId.getName());
return certLocal;
}
public SignerInfo genSignerInfo(byte[] data) throws SignatureException {
return new SignerInfo((X500Name) cert.getIssuerDN(),
new BigInteger("" + cert.getSerialNumber()),
getDigestAlgId(), algId,
simpleSign(data, 0, data.length));
}
}
Manifest-Version: 1.0
Name: CheckCerts.class
Digest-Algorithms: SHA
SHA-Digest: xLygljhRro6990piIVEilVI8szQ=
Name: ContentInfoTest.class
Digest-Algorithms: SHA
SHA-Digest: TSVdEMQW2gdFi6qeba+UixdHSdo=
Name: JarVerify.class
Digest-Algorithms: SHA
SHA-Digest: Wg+PiDzunNGH4KrWAp00/okp39s=
Name: JarVerify2.class
Digest-Algorithms: SHA
SHA-Digest: 5uYBQxwGWgYmNBwhnWRbymeXmWM=
Name: PKCS7Read.class
Digest-Algorithms: SHA
SHA-Digest: JPIxttHBfRpQaFyiQJ2Wfkvj/ls=
Name: PKCS7Test.class
Digest-Algorithms: SHA
SHA-Digest: R64SXXgZrOvGiO/eMsfG/T1Vn30=
Name: PKCS7Test10.class
Digest-Algorithms: SHA
SHA-Digest: 2R0yxuxRHTPqdAzJJcrvqkpbQgo=
Name: PKCS7Test11.class
Digest-Algorithms: SHA
SHA-Digest: /0HcwnpQi0hwJsJtvt5peWFGvtc=
Name: PKCS7Test12.class
Digest-Algorithms: SHA
SHA-Digest: s5CcqimfRqR9CW25tFBY0JK3RVU=
Name: PKCS7Test2.class
Digest-Algorithms: SHA
SHA-Digest: 71VkFEMUle5sjXNFbSW31F1ZJ58=
Name: PKCS7Test3.class
Digest-Algorithms: SHA
SHA-Digest: mU/D5C6SgPRmwoLQzwF5VnN3aqM=
Name: PKCS7Test4.class
Digest-Algorithms: SHA
SHA-Digest: ss9NFvxF8emaEjdKdvtzWXfs0/E=
Name: PKCS7Test5.class
Digest-Algorithms: SHA
SHA-Digest: DHvQ20UAXoYgfCPAOeCOrglsJwU=
Name: PKCS7Test6.class
Digest-Algorithms: SHA
SHA-Digest: aiCb8chroH7XDaNfAz6wr57lXsA=
Name: PKCS7Test7.class
Digest-Algorithms: SHA
SHA-Digest: UoieXLC68alFgfD/Q1NW9/r2kaY=
Name: PKCS7Test8.class
Digest-Algorithms: SHA
SHA-Digest: eMW7mq5b/KVB1M5L76wcV1+uFQs=
Name: PKCS7Test9.class
Digest-Algorithms: SHA
SHA-Digest: EEWCZG1creWjqVZVIEgr0on3y6A=
Name: SignerInfoTest.class
Digest-Algorithms: SHA
SHA-Digest: l6SNfpnFipGg8gy4XqY3HhA0RrY=
Name: SignerInfoTest2.class
Digest-Algorithms: SHA
SHA-Digest: 5jbzlkZqXKNmmmE+pcjQka8D6WE=
Name: SimpleSigner.class
Digest-Algorithms: SHA
SHA-Digest: l9ODQHY4wxhIvLw4/B0qe9NjwxQ=
MIILKAYJKoZIhvcNAQcCoIILGTCCCxUCAQExCzAJBgUrDgMCGgUAMIIHbQYJKoZI
hvcNAQcBoIIHXgSCB1pTaWduYXR1cmUtVmVyc2lvbjogMS4wDQoNCk5hbWU6IENo
ZWNrQ2VydHMuY2xhc3MNCkRpZ2VzdC1BbGdvcml0aG1zOiBTSEENClNIQS1EaWdl
c3Q6IHlhMXh3dnNRTytEUnBRYnczRmgyblJCMkpRYz0NCg0KTmFtZTogQ29udGVu
dEluZm9UZXN0LmNsYXNzDQpEaWdlc3QtQWxnb3JpdGhtczogU0hBDQpTSEEtRGln
ZXN0OiBDYStFSmFrVTZ6dzRLQWhvcWNuQ3BOcWsyTEk9DQoNCk5hbWU6IEphclZl
cmlmeS5jbGFzcw0KRGlnZXN0LUFsZ29yaXRobXM6IFNIQQ0KU0hBLURpZ2VzdDog
K0RHYVdXa25md2U0Wk9wc29NVEZ6ZldSdmhRPQ0KDQpOYW1lOiBKYXJWZXJpZnky
LmNsYXNzDQpEaWdlc3QtQWxnb3JpdGhtczogU0hBDQpTSEEtRGlnZXN0OiBHcUR6
WXlZNFAvV0g1SEt2aVdxWHR0UGc1ckU9DQoNCk5hbWU6IFBLQ1M3UmVhZC5jbGFz
cw0KRGlnZXN0LUFsZ29yaXRobXM6IFNIQQ0KU0hBLURpZ2VzdDogUW1mOEs5aFhW
bHdJZFBZNm52MmpGUGZHcWtBPQ0KDQpOYW1lOiBQS0NTN1Rlc3QuY2xhc3MNCkRp
Z2VzdC1BbGdvcml0aG1zOiBTSEENClNIQS1EaWdlc3Q6IEdiZS9nenl2MkY1OGY2
RUVoU1oxQnFHWHRsbz0NCg0KTmFtZTogUEtDUzdUZXN0MTAuY2xhc3MNCkRpZ2Vz
dC1BbGdvcml0aG1zOiBTSEENClNIQS1EaWdlc3Q6IDh3QnFXLy9lVzJzTlJJOTFi
TFlFT29kY2dhRT0NCg0KTmFtZTogUEtDUzdUZXN0MTEuY2xhc3MNCkRpZ2VzdC1B
bGdvcml0aG1zOiBTSEENClNIQS1EaWdlc3Q6IGJYaExLRXNsY3VFWGk0dS9haGdU
MnE2dGNFVT0NCg0KTmFtZTogUEtDUzdUZXN0MTIuY2xhc3MNCkRpZ2VzdC1BbGdv
cml0aG1zOiBTSEENClNIQS1EaWdlc3Q6IDlLRVkxYjUyUUxtTjBxei81ejB3QkZy
T216MD0NCg0KTmFtZTogUEtDUzdUZXN0Mi5jbGFzcw0KRGlnZXN0LUFsZ29yaXRo
bXM6IFNIQQ0KU0hBLURpZ2VzdDogK1VhMzIvMlE4RjJiclFRbVNYWCtYUytNL2g0
PQ0KDQpOYW1lOiBQS0NTN1Rlc3QzLmNsYXNzDQpEaWdlc3QtQWxnb3JpdGhtczog
U0hBDQpTSEEtRGlnZXN0OiAwSFhVWnlhU2ZkZUtlZThuWnpFalJTeXJldTQ9DQoN
Ck5hbWU6IFBLQ1M3VGVzdDQuY2xhc3MNCkRpZ2VzdC1BbGdvcml0aG1zOiBTSEEN
ClNIQS1EaWdlc3Q6IEo3eXJTMjRvS3VTZ2F1dHZkemhxQmo3ZGJjUT0NCg0KTmFt
ZTogUEtDUzdUZXN0NS5jbGFzcw0KRGlnZXN0LUFsZ29yaXRobXM6IFNIQQ0KU0hB
LURpZ2VzdDogSlR2OVdTb3gxTEVTUjJMcTdzMFVxU2x0RFNRPQ0KDQpOYW1lOiBQ
S0NTN1Rlc3Q2LmNsYXNzDQpEaWdlc3QtQWxnb3JpdGhtczogU0hBDQpTSEEtRGln
ZXN0OiBnR3Yra05oK3UzSFExdHp4bGNBVzdTcEZUS2s9DQoNCk5hbWU6IFBLQ1M3
VGVzdDcuY2xhc3MNCkRpZ2VzdC1BbGdvcml0aG1zOiBTSEENClNIQS1EaWdlc3Q6
IGZpSEYxYUExYWN6czFPd0V5OEc3VkMrcjdMST0NCg0KTmFtZTogUEtDUzdUZXN0
OC5jbGFzcw0KRGlnZXN0LUFsZ29yaXRobXM6IFNIQQ0KU0hBLURpZ2VzdDogNzRU
VzdJOVZPdzVWZ0x2aFJtRGZxRVd2ZkFRPQ0KDQpOYW1lOiBQS0NTN1Rlc3Q5LmNs
YXNzDQpEaWdlc3QtQWxnb3JpdGhtczogU0hBDQpTSEEtRGlnZXN0OiAxY0JJbkdU
Y08xQVFaKy8wdmhGa2laV3dsQTA9DQoNCk5hbWU6IFNpZ25lckluZm9UZXN0LmNs
YXNzDQpEaWdlc3QtQWxnb3JpdGhtczogU0hBDQpTSEEtRGlnZXN0OiBjRlk0Q3RT
anphMUErV2pBS05TVnF1cGpSWUU9DQoNCk5hbWU6IFNpZ25lckluZm9UZXN0Mi5j
bGFzcw0KRGlnZXN0LUFsZ29yaXRobXM6IFNIQQ0KU0hBLURpZ2VzdDogYU5NMEZQ
MHpFelF6eGxYeDZxQ0J4dWtta0hRPQ0KDQpOYW1lOiBTaW1wbGVTaWduZXIuY2xh
c3MNCkRpZ2VzdC1BbGdvcml0aG1zOiBTSEENClNIQS1EaWdlc3Q6IC9MV0NzbkM3
TVpNUjZHb3czeTJjdnA3STBTTT0NCg0KoIICvzCCArswggJ3AgUA59UzNDALBgcq
hkjOOAQDBQAwdTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlD
dXBlcnRpbm8xGTAXBgNVBAoTEFN1biBNaWNyb3N5c3RlbXMxETAPBgNVBAsTCEph
dmFTb2Z0MRcwFQYDVQQDEw5Eb3VnbGFzIEhvb3ZlcjAeFw05NzEwMDIxODEyMDda
Fw05NzEyMzExNzEyMDdaMHUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTESMBAG
A1UEBxMJQ3VwZXJ0aW5vMRkwFwYDVQQKExBTdW4gTWljcm9zeXN0ZW1zMREwDwYD
VQQLEwhKYXZhU29mdDEXMBUGA1UEAxMORG91Z2xhcyBIb292ZXIwggFRMIHoBgcq
hkjOOAQBMIHcAmEA6eZCWZ01XzfJf/01ZxILjiXJzUPpJ7OpZw++xdiQFBki0sOz
rSSACTeZhp0ehGqrSfqwrSbSzmoiIZ1HC859d31KIfvpwnC1f2BwAvPO+Dk2lM9F
7jaIwRqMVqsSej2vAhUAnNvYTJ8awvOND4D0KrlS5zOL9RECYDBHCtWgBfsUzi2d
zYfji8fRscX6y67L6V8ZCqejHSPE27y+BhdFREAaWywCCWXYwr0hcdNmhEV3H3S6
CE0gKdg8HBWFR/Op8aJxW+I9Ua5NPlofanBk8xaTOjRtP1KSUgNkAAJhAMN5uB+B
ZJ0W2UjXMyKoFUFXRYiLpnaSw63kl9tKnR9R5rEreiyHQ5IelPxjwCHGgTbYK0y+
xKTGHVWiQN/YJmHLbSrcSSM/d89aR/sVbGoAwQOyYraFGUNIOTQjjXcXCjALBgcq
hkjOOAQDBQADMQAwLgIVAJxmL029GLXDJVbk72d4cSPQ4/rvAhUAll9UPl8aOMEg
V4egANhwbynMGSgxgc4wgcsCAQEwfjB1MQswCQYDVQQGEwJVUzELMAkGA1UECBMC
Q0ExEjAQBgNVBAcTCUN1cGVydGlubzEZMBcGA1UEChMQU3VuIE1pY3Jvc3lzdGVt
czERMA8GA1UECxMISmF2YVNvZnQxFzAVBgNVBAMTDkRvdWdsYXMgSG9vdmVyAgUA
59UzNDAJBgUrDgMCGgUAMAsGByqGSM44BAMFAAQuMCwCFDmry17kzDD6Y5X1BqIS
lq6swckPAhRtiXvBHa5CRGjbwk8yqf9hGgZfFA==
Signature-Version: 1.0
Name: CheckCerts.class
Digest-Algorithms: SHA
SHA-Digest: ya1xwvsQO+DRpQbw3Fh2nRB2JQc=
Name: ContentInfoTest.class
Digest-Algorithms: SHA
SHA-Digest: Ca+EJakU6zw4KAhoqcnCpNqk2LI=
Name: JarVerify.class
Digest-Algorithms: SHA
SHA-Digest: +DGaWWknfwe4ZOpsoMTFzfWRvhQ=
Name: JarVerify2.class
Digest-Algorithms: SHA
SHA-Digest: GqDzYyY4P/WH5HKviWqXttPg5rE=
Name: PKCS7Read.class
Digest-Algorithms: SHA
SHA-Digest: Qmf8K9hXVlwIdPY6nv2jFPfGqkA=
Name: PKCS7Test.class
Digest-Algorithms: SHA
SHA-Digest: Gbe/gzyv2F58f6EEhSZ1BqGXtlo=
Name: PKCS7Test10.class
Digest-Algorithms: SHA
SHA-Digest: 8wBqW//eW2sNRI91bLYEOodcgaE=
Name: PKCS7Test11.class
Digest-Algorithms: SHA
SHA-Digest: bXhLKEslcuEXi4u/ahgT2q6tcEU=
Name: PKCS7Test12.class
Digest-Algorithms: SHA
SHA-Digest: 9KEY1b52QLmN0qz/5z0wBFrOmz0=
Name: PKCS7Test2.class
Digest-Algorithms: SHA
SHA-Digest: +Ua32/2Q8F2brQQmSXX+XS+M/h4=
Name: PKCS7Test3.class
Digest-Algorithms: SHA
SHA-Digest: 0HXUZyaSfdeKee8nZzEjRSyreu4=
Name: PKCS7Test4.class
Digest-Algorithms: SHA
SHA-Digest: J7yrS24oKuSgautvdzhqBj7dbcQ=
Name: PKCS7Test5.class
Digest-Algorithms: SHA
SHA-Digest: JTv9WSox1LESR2Lq7s0UqSltDSQ=
Name: PKCS7Test6.class
Digest-Algorithms: SHA
SHA-Digest: gGv+kNh+u3HQ1tzxlcAW7SpFTKk=
Name: PKCS7Test7.class
Digest-Algorithms: SHA
SHA-Digest: fiHF1aA1aczs1OwEy8G7VC+r7LI=
Name: PKCS7Test8.class
Digest-Algorithms: SHA
SHA-Digest: 74TW7I9VOw5VgLvhRmDfqEWvfAQ=
Name: PKCS7Test9.class
Digest-Algorithms: SHA
SHA-Digest: 1cBInGTcO1AQZ+/0vhFkiZWwlA0=
Name: SignerInfoTest.class
Digest-Algorithms: SHA
SHA-Digest: cFY4CtSjza1A+WjAKNSVqupjRYE=
Name: SignerInfoTest2.class
Digest-Algorithms: SHA
SHA-Digest: aNM0FP0zEzQzxlXx6qCBxukmkHQ=
Name: SimpleSigner.class
Digest-Algorithms: SHA
SHA-Digest: /LWCsnC7MZMR6Gow3y2cvp7I0SM=
/*
* Copyright (c) 2015, 2016, 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.
*
* 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.
*/
/*
* @test
* @bug 8048357
* @summary PKCS8 Standards Conformance Tests
* @requires (os.family != "solaris")
* @compile -XDignore.symbol.file PKCS8Test.java
* @run main PKCS8Test
*/
/*
* Skip Solaris since the DSAPrivateKeys returned by
* SunPKCS11 Provider are not subclasses of PKCS8Key
*/
import java.io.IOException;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.util.Arrays;
import sun.misc.HexDumpEncoder;
import sun.security.pkcs.PKCS8Key;
import sun.security.provider.DSAPrivateKey;
import sun.security.util.DerOutputStream;
import sun.security.util.DerValue;
import sun.security.x509.AlgorithmId;
import static java.lang.System.out;
public class PKCS8Test {
static final HexDumpEncoder hexDump = new HexDumpEncoder();
static final DerOutputStream derOutput = new DerOutputStream();
static final String FORMAT = "PKCS#8";
static final String EXPECTED_ALG_ID_CHRS = "DSA\n\tp: 02\n\tq: 03\n"
+ "\tg: 04\n";
static final String ALGORITHM = "DSA";
static final String EXCEPTION_MESSAGE = "version mismatch: (supported: "
+ "00, parsed: 01";
// test second branch in byte[] encode()
// DER encoding,include (empty) set of attributes
static final int[] NEW_ENCODED_KEY_INTS = { 0x30,
// length 30 = 0x1e
0x1e,
// first element
// version Version (= INTEGER)
0x02,
// length 1
0x01,
// value 0
0x00,
// second element
// privateKeyAlgorithmIdentifier PrivateKeyAlgorithmIdentifier
// (sequence)
// (an object identifier?)
0x30,
// length 18
0x12,
// contents
// object identifier, 5 bytes
0x06, 0x05,
// { 1 3 14 3 2 12 }
0x2b, 0x0e, 0x03, 0x02, 0x0c,
// sequence, 9 bytes
0x30, 0x09,
// integer 2
0x02, 0x01, 0x02,
// integer 3
0x02, 0x01, 0x03,
// integer 4
0x02, 0x01, 0x04,
// third element
// privateKey PrivateKey (= OCTET STRING)
0x04,
// length
0x03,
// privateKey contents
0x02, 0x01, 0x01,
// 4th (optional) element -- attributes [0] IMPLICIT Attributes
// OPTIONAL
// (Attributes = SET OF Attribute) Here, it will be empty.
0xA0,
// length
0x00 };
// encoding originally created, but with the version changed
static final int[] NEW_ENCODED_KEY_INTS_2 = {
// sequence
0x30,
// length 28 = 0x1c
0x1c,
// first element
// version Version (= INTEGER)
0x02,
// length 1
0x01,
// value 1 (illegal)
0x01,
// second element
// privateKeyAlgorithmIdentifier PrivateKeyAlgorithmIdentifier
// (sequence)
// (an object identifier?)
0x30,
// length 18
0x12,
// contents
// object identifier, 5 bytes
0x06, 0x05,
// { 1 3 14 3 2 12 }
0x2b, 0x0e, 0x03, 0x02, 0x0c,
// sequence, 9 bytes
0x30, 0x09,
// integer 2
0x02, 0x01, 0x02,
// integer 3
0x02, 0x01, 0x03,
// integer 4
0x02, 0x01, 0x04,
// third element
// privateKey PrivateKey (= OCTET STRING)
0x04,
// length
0x03,
// privateKey contents
0x02, 0x01, 0x01 };
// 0000: 30 1E 02 01 00 30 14 06 07 2A 86 48 CE 38 04 01 0....0...*.H.8..
// 0010: 30 09 02 01 02 02 01 03 02 01 04 04 03 02 01 01 0...............
static final int[] EXPECTED = { 0x30,
// length 30 = 0x1e
0x1e,
// first element
// version Version (= INTEGER)
0x02,
// length 1
0x01,
// value 0
0x00,
// second element
// privateKeyAlgorithmIdentifier PrivateKeyAlgorithmIdentifier
// (sequence)
// (an object identifier?)
0x30, 0x14, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x01,
// integer 2
0x30, 0x09, 0x02,
// integer 3
0x01, 0x02, 0x02,
// integer 4
0x01, 0x03, 0x02,
// third element
// privateKey PrivateKey (= OCTET STRING)
0x01,
// length
0x04,
// privateKey contents
0x04, 0x03, 0x02,
// 4th (optional) element -- attributes [0] IMPLICIT Attributes
// OPTIONAL
// (Attributes = SET OF Attribute) Here, it will be empty.
0x01,
// length
0x01 };
static void raiseException(String expected, String received) {
throw new RuntimeException(
"Expected " + expected + "; Received " + received);
}
public static void main(String[] args)
throws IOException, InvalidKeyException {
BigInteger p = BigInteger.valueOf(1);
BigInteger q = BigInteger.valueOf(2);
BigInteger g = BigInteger.valueOf(3);
BigInteger x = BigInteger.valueOf(4);
DSAPrivateKey priv = new DSAPrivateKey(p, q, g, x);
byte[] encodedKey = priv.getEncoded();
byte[] expectedBytes = new byte[EXPECTED.length];
for (int i = 0; i < EXPECTED.length; i++) {
expectedBytes[i] = (byte) EXPECTED[i];
}
dumpByteArray("encodedKey :", encodedKey);
if (!Arrays.equals(encodedKey, expectedBytes)) {
raiseException(new String(expectedBytes), new String(encodedKey));
}
PKCS8Key decodedKey = PKCS8Key.parse(new DerValue(encodedKey));
String alg = decodedKey.getAlgorithm();
AlgorithmId algId = decodedKey.getAlgorithmId();
out.println("Algorithm :" + alg);
out.println("AlgorithmId: " + algId);
if (!ALGORITHM.equals(alg)) {
raiseException(ALGORITHM, alg);
}
if (!EXPECTED_ALG_ID_CHRS.equalsIgnoreCase(algId.toString())) {
raiseException(EXPECTED_ALG_ID_CHRS, algId.toString());
}
decodedKey.encode(derOutput);
dumpByteArray("Stream encode: ", derOutput.toByteArray());
if (!Arrays.equals(derOutput.toByteArray(), expectedBytes)) {
raiseException(new String(expectedBytes), derOutput.toString());
}
dumpByteArray("byte[] encoding: ", decodedKey.getEncoded());
if (!Arrays.equals(decodedKey.getEncoded(), expectedBytes)) {
raiseException(new String(expectedBytes),
new String(decodedKey.getEncoded()));
}
if (!FORMAT.equals(decodedKey.getFormat())) {
raiseException(FORMAT, decodedKey.getFormat());
}
try {
byte[] newEncodedKey = new byte[NEW_ENCODED_KEY_INTS.length];
for (int i = 0; i < newEncodedKey.length; i++) {
newEncodedKey[i] = (byte) NEW_ENCODED_KEY_INTS[i];
}
PKCS8Key newDecodedKey = PKCS8Key
.parse(new DerValue(newEncodedKey));
throw new RuntimeException(
"key1: Expected an IOException during " + "parsing");
} catch (IOException e) {
System.out.println("newEncodedKey: should have excess data due to "
+ "attributes, which are not supported");
}
try {
byte[] newEncodedKey2 = new byte[NEW_ENCODED_KEY_INTS_2.length];
for (int i = 0; i < newEncodedKey2.length; i++) {
newEncodedKey2[i] = (byte) NEW_ENCODED_KEY_INTS_2[i];
}
PKCS8Key newDecodedKey2 = PKCS8Key
.parse(new DerValue(newEncodedKey2));
throw new RuntimeException(
"key2: Expected an IOException during " + "parsing");
} catch (IOException e) {
out.println("Key 2: should be illegal version");
out.println(e.getMessage());
if (!EXCEPTION_MESSAGE.equals(e.getMessage())) {
throw new RuntimeException("Key2: expected: "
+ EXCEPTION_MESSAGE + " get: " + e.getMessage());
}
}
}
static void dumpByteArray(String nm, byte[] bytes) throws IOException {
out.println(nm + " length: " + bytes.length);
hexDump.encodeBuffer(bytes, out);
}
}
/*
* Copyright (c) 2003, 2014, 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.
*
* 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.
*/
import java.io.UnsupportedEncodingException;
import java.security.Provider;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
/**
* @test
* @bug 4846410 6313661 4963723
* @summary Basic known-answer-test for Hmac algorithms
* @author Andreas Sterbenz
* @library ..
* @run main MacKAT
*/
public class MacKAT extends PKCS11Test {
private final static byte[] ALONG, BLONG, BKEY, BKEY_20, DDDATA_50,
AAKEY_20, CDDATA_50, AAKEY_131;
static {
ALONG = new byte[1024 * 128];
Arrays.fill(ALONG, (byte)'a');
BLONG = new byte[1024 * 128];
Random random = new Random(12345678);
random.nextBytes(BLONG);
BKEY = new byte[128];
random.nextBytes(BKEY);
BKEY_20 = new byte[20];
Arrays.fill(BKEY_20, (byte) 0x0b);
DDDATA_50 = new byte[50];
Arrays.fill(DDDATA_50, (byte) 0xdd);
AAKEY_20 = new byte[20];
Arrays.fill(AAKEY_20, (byte) 0xaa);
CDDATA_50 = new byte[50];
Arrays.fill(CDDATA_50, (byte) 0xcd);
AAKEY_131 = new byte[131];
Arrays.fill(AAKEY_131, (byte) 0xaa);
}
private final static Test[] tests = {
newMacTest("SslMacMD5",
ALONG,
"f4:ad:01:71:51:f6:89:56:72:a3:32:bf:d9:2a:f2:a5",
"1b:34:61:29:05:0d:73:db:25:d0:dd:64:06:29:f6:8a"),
newMacTest("SslMacMD5",
BLONG,
"34:1c:ad:a0:95:57:32:f8:8e:80:8f:ee:b2:d8:23:e5",
"76:00:4a:72:98:9b:65:ec:2e:f1:43:c4:65:4a:13:71"),
newMacTest("SslMacSHA1",
ALONG,
"11:c1:71:2e:61:be:4b:cf:bc:6d:e2:4c:58:ae:27:30:0b:24:a4:87",
"23:ae:dd:61:87:6c:7a:45:47:2f:2c:8f:ea:64:99:3e:27:5f:97:a5"),
newMacTest("SslMacSHA1",
BLONG,
"84:af:57:0a:af:ef:16:93:90:50:da:88:f8:ad:1a:c5:66:6c:94:d0",
"9b:bb:e2:aa:9b:28:1c:95:0e:ea:30:21:98:a5:7e:31:9e:bf:5f:51"),
newMacTest("HmacMD5",
ALONG,
"76:00:4a:72:98:9b:65:ec:2e:f1:43:c4:65:4a:13:71",
"1b:34:61:29:05:0d:73:db:25:d0:dd:64:06:29:f6:8a"),
newMacTest("HmacMD5",
BLONG,
"6c:22:79:bb:34:9e:da:f4:f5:cf:df:0c:62:3d:59:e0",
"76:00:4a:72:98:9b:65:ec:2e:f1:43:c4:65:4a:13:71"),
newMacTest("HmacMD5",
BLONG,
"e6:ad:00:c9:49:6b:98:fe:53:a2:b9:2d:7d:41:a2:03",
BKEY),
newMacTest("HmacSHA1",
ALONG,
"9e:b3:6e:35:fa:fb:17:2e:2b:f3:b0:4a:9d:38:83:c4:5f:6d:d9:00",
"1b:34:61:29:05:0d:73:db:25:d0:dd:64:06:29:f6:8a"),
newMacTest("HmacSHA1",
BLONG,
"80:2d:5b:ea:08:df:a4:1f:e5:3e:1c:fa:fc:ad:dd:31:da:15:60:2c",
"76:00:4a:72:98:9b:65:ec:2e:f1:43:c4:65:4a:13:71"),
newMacTest("HmacSHA1",
BLONG,
"a2:fa:2a:85:18:0e:94:b2:a5:e2:17:8b:2a:29:7a:95:cd:e8:aa:82",
BKEY),
newMacTest("HmacSHA256",
ALONG,
"3f:6d:08:df:0c:90:b0:e9:ed:13:4a:2e:c3:48:1d:3d:3e:61:2e:f1:"
+ "30:c2:63:c4:58:57:03:c2:cb:87:15:07",
"1b:34:61:29:05:0d:73:db:25:d0:dd:64:06:29:f6:8a"),
newMacTest("HmacSHA256",
BLONG,
"e2:4e:a3:b9:0b:b8:99:e4:71:cf:ca:9f:f8:4e:f0:34:8b:19:9f:33:"
+ "4b:1a:b7:13:f7:c8:57:92:e3:03:74:78",
BKEY),
newMacTest("HmacSHA384",
ALONG,
"d0:f0:d4:54:1c:0a:6d:81:ed:15:20:d7:0c:96:06:61:a0:ff:c9:ff:"
+ "91:e9:a0:cd:e2:45:64:9d:93:4c:a9:fa:89:ae:c0:90:e6:"
+ "0b:a1:a0:56:80:57:3b:ed:4b:b0:71",
"1b:34:61:29:05:0d:73:db:25:d0:dd:64:06:29:f6:8a"),
newMacTest("HmacSHA384",
BLONG,
"75:c4:ca:c7:f7:58:9d:d3:23:b1:1b:5c:93:2d:ec:7a:03:dc:8c:eb:"
+ "8d:fe:79:46:4f:30:e7:99:62:de:44:e2:38:95:0e:79:91:"
+ "78:2f:a4:05:0a:f0:17:10:38:a1:8e",
BKEY),
newMacTest("HmacSHA512",
ALONG,
"41:ea:4c:e5:31:3f:7c:18:0e:5e:95:a9:25:0a:10:58:e6:40:53:88:"
+ "82:4f:5a:da:6f:29:de:04:7b:8e:d7:ed:7c:4d:b8:2a:48:"
+ "2d:17:2a:2d:59:bb:81:9c:bf:33:40:04:77:44:fb:45:25:"
+ "1f:fd:b9:29:f4:a6:69:a3:43:6f",
"1b:34:61:29:05:0d:73:db:25:d0:dd:64:06:29:f6:8a"),
newMacTest("HmacSHA512",
BLONG,
"fb:cf:4b:c6:d5:49:5a:5b:0b:d9:2a:32:f5:fa:68:d2:68:a4:0f:ae:"
+ "53:fc:49:12:e6:1d:53:cf:b2:cb:c5:c5:f2:2d:86:bd:14:"
+ "61:30:c3:a6:6f:44:1f:77:9b:aa:a1:22:48:a9:dd:d0:45:"
+ "86:d1:a1:82:53:13:c4:03:06:a3",
BKEY),
// Test vectors From RFC 4231
newMacTest("HmacSHA224",
bytes("Hi There"),
"89:6f:b1:12:8a:bb:df:19:68:32:10:7c:d4:9d:f3:3f:47:b4:b1:16:"
+ "99:12:ba:4f:53:68:4b:22",
BKEY_20),
newMacTest("HmacSHA224",
bytes("what do ya want for nothing?"),
"a3:0e:01:09:8b:c6:db:bf:45:69:0f:3a:7e:9e:6d:0f:8b:be:a2:a3:"
+ "9e:61:48:00:8f:d0:5e:44",
bytes("Jefe")),
newMacTest("HmacSHA224",
DDDATA_50,
"7f:b3:cb:35:88:c6:c1:f6:ff:a9:69:4d:7d:6a:d2:64:93:65:b0:c1:"
+ "f6:5d:69:d1:ec:83:33:ea",
AAKEY_20),
newMacTest("HmacSHA224",
CDDATA_50,
"6c:11:50:68:74:01:3c:ac:6a:2a:bc:1b:b3:82:62:7c:ec:6a:90:d8:"
+ "6e:fc:01:2d:e7:af:ec:5a",
"01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13:14:"
+ "15:16:17:18:19"),
newMacTest("HmacSHA224",
bytes("Test Using Larger Than Block-Size Key - Hash Key First"),
"95:e9:a0:db:96:20:95:ad:ae:be:9b:2d:6f:0d:bc:e2:d4:99:f1:12:"
+ "f2:d2:b7:27:3f:a6:87:0e",
AAKEY_131),
newMacTest("HmacSHA224",
bytes("This is a test using a larger than block-size key and "
+ "a larger than block-size data. The key needs to be "
+ "hashed before being used by the HMAC algorithm."),
"3a:85:41:66:ac:5d:9f:02:3f:54:d5:17:d0:b3:9d:bd:94:67:70:db:"
+ "9c:2b:95:c9:f6:f5:65:d1",
AAKEY_131),
};
public static void main(String[] args) throws Exception {
main(new MacKAT());
}
@Override
public void main(Provider p) throws Exception {
long start = System.currentTimeMillis();
List<String> algorithms = getSupportedAlgorithms("Mac", "", p);
for (Test test : tests) {
if(!algorithms.contains(test.getAlg())) {
continue;
}
test.run(p);
}
System.out.println("All tests passed");
long stop = System.currentTimeMillis();
System.out.println("Done (" + (stop - start) + " ms).");
}
private static byte[] bytes(String s) {
try {
return s.getBytes("UTF8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
private static Test newMacTest(String alg, byte[] input, String macvalue,
String key) {
return new MacTest(alg, input, parse(macvalue), parse(key));
}
private static Test newMacTest(String alg, byte[] input, String macvalue,
byte[] key) {
return new MacTest(alg, input, parse(macvalue), key);
}
interface Test {
void run(Provider p) throws Exception;
String getAlg();
}
static class MacTest implements Test {
private final String alg;
private final byte[] input;
private final byte[] macvalue;
private final byte[] key;
MacTest(String alg, byte[] input, byte[] macvalue, byte[] key) {
this.alg = alg;
this.input = input;
this.macvalue = macvalue;
this.key = key;
}
@Override
public String getAlg() {
return alg;
}
@Override
public void run(Provider p) throws Exception {
Mac mac = Mac.getInstance(alg, p);
SecretKey keySpec = new SecretKeySpec(key, alg);
mac.init(keySpec);
mac.update(input);
byte[] macv = mac.doFinal();
if (Arrays.equals(macvalue, macv) == false) {
System.out.println("Mac test for " + alg + " failed:");
if (input.length < 256) {
System.out.println("input: "
+ PKCS11Test.toString(input));
}
System.out.println("key: " + PKCS11Test.toString(key));
System.out.println("macvalue: "
+ PKCS11Test.toString(macvalue));
System.out.println("calculated: " + PKCS11Test.toString(macv));
throw new Exception("Mac test for " + alg + " failed");
}
System.out.println("passed: " + alg);
}
}
}
/*
* Copyright (c) 1998, 2014, 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.
*
* 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.
*/
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Provider;
import java.security.SecureRandom;
import java.util.List;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
/**
* @test
* @bug 8048603
* @summary Check if doFinal and update operation result in same Mac
* @author Yu-Ching Valerie Peng, Bill Situ, Alexander Fomin
* @library ..
* @run main MacSameTest
*/
public class MacSameTest extends PKCS11Test {
private static final int MESSAGE_SIZE = 25;
private static final int OFFSET = 5;
private static final int KEY_SIZE = 70;
/**
* Initialize a message, instantiate a Mac object,
* initialize the object with a SecretKey,
* feed the message into the Mac object
* all at once and get the output MAC as result1.
* Reset the Mac object, chop the message into three pieces,
* feed into the Mac object sequentially, and get the output MAC as result2.
* Finally, compare result1 and result2 and see if they are the same.
*
* @param args the command line arguments
*/
public static void main(String[] args) throws Exception {
main(new MacSameTest());
}
@Override
public void main(Provider p) {
List<String> algorithms = getSupportedAlgorithms("Mac", "Hmac", p);
boolean success = true;
for (String alg : algorithms) {
try {
doTest(alg, p);
} catch (Exception e) {
System.out.println("Unexpected exception: " + e);
e.printStackTrace();
success = false;
}
}
if (!success) {
throw new RuntimeException("Test failed");
}
}
private void doTest(String algo, Provider provider)
throws NoSuchAlgorithmException, NoSuchProviderException,
InvalidKeyException {
System.out.println("Test " + algo);
Mac mac;
try {
mac = Mac.getInstance(algo, provider);
} catch (NoSuchAlgorithmException nsae) {
if ("SunPKCS11-Solaris".equals(provider.getName())) {
// depending on Solaris configuration,
// it can support HMAC or not with Mac
System.out.println("Expected NoSuchAlgorithmException thrown: "
+ nsae);
return;
}
throw nsae;
}
byte[] plain = new byte[MESSAGE_SIZE];
for (int i = 0; i < MESSAGE_SIZE; i++) {
plain[i] = (byte) (i % 256);
}
byte[] tail = new byte[plain.length - OFFSET];
System.arraycopy(plain, OFFSET, tail, 0, tail.length);
SecureRandom srdm = new SecureRandom();
byte[] keyVal = new byte[KEY_SIZE];
srdm.nextBytes(keyVal);
SecretKeySpec keySpec = new SecretKeySpec(keyVal, "HMAC");
mac.init(keySpec);
byte[] result1 = mac.doFinal(plain);
mac.reset();
mac.update(plain[0]);
mac.update(plain, 1, OFFSET - 1);
byte[] result2 = mac.doFinal(tail);
if (!java.util.Arrays.equals(result1, result2)) {
throw new RuntimeException("result1 and result2 are not the same");
}
}
}
......@@ -578,4 +578,21 @@ public abstract class PKCS11Test {
return r;
}
/**
* Returns supported algorithms of specified type.
*/
static List<String> getSupportedAlgorithms(String type, String alg,
Provider p) {
// prepare a list of supported algorithms
List<String> algorithms = new ArrayList<>();
Set<Provider.Service> services = p.getServices();
for (Provider.Service service : services) {
if (service.getType().equals(type)
&& service.getAlgorithm().startsWith(alg)) {
algorithms.add(service.getAlgorithm());
}
}
return algorithms;
}
}
/*
* Copyright (c) 2015, 2016, 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.
*
* 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.
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import static java.lang.System.out;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import sun.misc.BASE64Encoder;
import sun.security.util.BitArray;
import sun.security.util.ObjectIdentifier;
import sun.security.x509.*;
/**
* @test
* @bug 8049237
* @summary This test generates V3 certificate with all the supported
* extensions. Writes back the generated certificate in to a file and checks for
* equality with the original certificate.
*/
public class V3Certificate {
public static final String V3_FILE = "certV3";
public static final String V3_B64_FILE = "certV3.b64";
public static void main(String[] args) throws IOException,
NoSuchAlgorithmException, InvalidKeyException, CertificateException,
NoSuchProviderException, SignatureException {
boolean success = true;
success &= test("RSA", "SHA256withRSA", 2048);
success &= test("DSA", "SHA256withDSA", 2048);
success &= test("EC", "SHA256withECDSA", 384);
if (!success) {
throw new RuntimeException("At least one test case failed");
}
}
public static boolean test(String algorithm, String sigAlg, int keyLength)
throws IOException,
NoSuchAlgorithmException,
InvalidKeyException,
CertificateException,
NoSuchProviderException,
SignatureException {
byte[] issuerId = {1, 2, 3, 4, 5};
byte[] subjectId = {6, 7, 8, 9, 10};
boolean testResult = true;
// Subject and Issuer
X500Name subject = new X500Name("test", "Oracle", "Santa Clara",
"US");
X500Name issuer = subject;
// Generate keys and sign
KeyPairGenerator keyGen = KeyPairGenerator.getInstance(algorithm);
keyGen.initialize(keyLength);
KeyPair pair = keyGen.generateKeyPair();
PublicKey publicKey = pair.getPublic();
PrivateKey privateKey = pair.getPrivate();
MessageDigest md = MessageDigest.getInstance("SHA");
byte[] keyId = md.digest(publicKey.getEncoded());
Signature signature = Signature.getInstance(sigAlg);
signature.initSign(privateKey);
// Validity interval
Date firstDate = new Date();
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("PST"));
cal.set(2014, 03, 10, 12, 30, 30);
Date lastDate = cal.getTime();
CertificateValidity interval = new CertificateValidity(firstDate,
lastDate);
// Certificate Info
X509CertInfo cert = new X509CertInfo();
cert.set(X509CertInfo.VERSION,
new CertificateVersion(CertificateVersion.V3));
cert.set(X509CertInfo.SERIAL_NUMBER,
new CertificateSerialNumber((int) (firstDate.getTime() / 1000)));
cert.set(X509CertInfo.ALGORITHM_ID,
new CertificateAlgorithmId(AlgorithmId.get(sigAlg)));
cert.set(X509CertInfo.SUBJECT, subject);
cert.set(X509CertInfo.KEY, new CertificateX509Key(publicKey));
cert.set(X509CertInfo.VALIDITY, interval);
cert.set(X509CertInfo.ISSUER, issuer);
cert.set(X509CertInfo.ISSUER_ID,
new UniqueIdentity(
new BitArray(issuerId.length * 8 - 2, issuerId)));
cert.set(X509CertInfo.SUBJECT_ID, new UniqueIdentity(subjectId));
// Create Extensions
CertificateExtensions exts = new CertificateExtensions();
GeneralNameInterface mailInf = new RFC822Name("test@Oracle.com");
GeneralName mail = new GeneralName(mailInf);
GeneralNameInterface dnsInf = new DNSName("Oracle.com");
GeneralName dns = new GeneralName(dnsInf);
GeneralNameInterface uriInf = new URIName("http://www.Oracle.com");
GeneralName uri = new GeneralName(uriInf);
// localhost
byte[] address = new byte[]{127, 0, 0, 1};
GeneralNameInterface ipInf = new IPAddressName(address);
GeneralName ip = new GeneralName(ipInf);
int[] oidData = new int[]{1, 2, 3, 4};
GeneralNameInterface oidInf = new OIDName(new ObjectIdentifier(oidData));
GeneralName oid = new GeneralName(oidInf);
SubjectAlternativeNameExtension subjectName
= new SubjectAlternativeNameExtension();
IssuerAlternativeNameExtension issuerName
= new IssuerAlternativeNameExtension();
GeneralNames subjectNames
= (GeneralNames) subjectName.
get(SubjectAlternativeNameExtension.SUBJECT_NAME);
GeneralNames issuerNames
= (GeneralNames) issuerName.
get(IssuerAlternativeNameExtension.ISSUER_NAME);
subjectNames.add(mail);
subjectNames.add(dns);
subjectNames.add(uri);
issuerNames.add(ip);
issuerNames.add(oid);
cal.set(2000, 11, 15, 12, 30, 30);
lastDate = cal.getTime();
PrivateKeyUsageExtension pkusage
= new PrivateKeyUsageExtension(firstDate, lastDate);
KeyUsageExtension usage = new KeyUsageExtension();
usage.set(KeyUsageExtension.CRL_SIGN, true);
usage.set(KeyUsageExtension.DIGITAL_SIGNATURE, true);
usage.set(KeyUsageExtension.NON_REPUDIATION, true);
KeyIdentifier kid = new KeyIdentifier(keyId);
SerialNumber sn = new SerialNumber(42);
AuthorityKeyIdentifierExtension aki
= new AuthorityKeyIdentifierExtension(kid, subjectNames, sn);
SubjectKeyIdentifierExtension ski
= new SubjectKeyIdentifierExtension(keyId);
BasicConstraintsExtension cons
= new BasicConstraintsExtension(true, 10);
PolicyConstraintsExtension pce = new PolicyConstraintsExtension(2, 4);
exts.set(SubjectAlternativeNameExtension.NAME, subjectName);
exts.set(IssuerAlternativeNameExtension.NAME, issuerName);
exts.set(PrivateKeyUsageExtension.NAME, pkusage);
exts.set(KeyUsageExtension.NAME, usage);
exts.set(AuthorityKeyIdentifierExtension.NAME, aki);
exts.set(SubjectKeyIdentifierExtension.NAME, ski);
exts.set(BasicConstraintsExtension.NAME, cons);
exts.set(PolicyConstraintsExtension.NAME, pce);
cert.set(X509CertInfo.EXTENSIONS, exts);
// Generate and sign X509CertImpl
X509CertImpl crt = new X509CertImpl(cert);
crt.sign(privateKey, sigAlg);
crt.verify(publicKey);
try (FileOutputStream fos = new FileOutputStream(new File(V3_FILE));
FileOutputStream fos_b64
= new FileOutputStream(new File(V3_B64_FILE));
PrintWriter pw = new PrintWriter(fos_b64)) {
crt.encode((OutputStream) fos);
fos.flush();
// Certificate boundaries/
pw.println("-----BEGIN CERTIFICATE-----");
pw.flush();
new BASE64Encoder().encodeBuffer(crt.getEncoded(), fos_b64);
fos_b64.flush();
pw.println("-----END CERTIFICATE-----");
}
out.println("*** Certificate ***");
out.println(crt);
out.println("*** End Certificate ***");
X509Certificate x2 = generateCertificate(V3_FILE);
if (!x2.equals(crt)) {
out.println("*** Certificate mismatch ***");
testResult = false;
}
X509Certificate x3 = generateCertificate(V3_B64_FILE);
if (!x3.equals(crt)) {
out.println("*** Certificate mismatch ***");
testResult = false;
}
return testResult;
}
static X509Certificate generateCertificate(String certFile) {
try (InputStream inStrm = new FileInputStream(certFile)) {
CertificateFactory cf = CertificateFactory.getInstance("X509");
X509Certificate x2
= (X509Certificate) cf.generateCertificate(inStrm);
return x2;
} catch (CertificateException | IOException e) {
throw new RuntimeException("Exception while "
+ "genrating certificate for " + certFile, e);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册