if (value != null) { data = new byte[value.length() / 2 + 1]; int pos = 0; for (char c: value.toCharArray()) { int hex; if (c >= '0' && c <= '9') { hex = c - '0' ; } else if (c >= 'A' && c <= 'F') { hex = c - 'A' + 10; } else if (c >= 'a' && c <= 'f') { hex = c - 'a' + 10; } else { continue; } if (pos % 2 == 0) { data[pos/2] = (byte)(hex << 4); } else { data[pos/2] += hex; } pos++; } if (pos % 2 != 0) { throw new Exception(rb.getString( "Odd.number.of.hex.digits.found.") + extstr); } data = Arrays.copyOf(data, pos/2); } else { data = new byte[0]; } ext.set(oid.toString(), new Extension(oid, isCritical, new DerValue(DerValue.tag_OctetString, data) .toByteArray())); break; default: throw new Exception(rb.getString( "Unknown.extension.type.") + extstr); } } // always non-critical ext.set(SubjectKeyIdentifierExtension.NAME, new SubjectKeyIdentifierExtension( new KeyIdentifier(pkey).getIdentifier())); if (akey != null && !pkey.equals(akey)) { ext.set(AuthorityKeyIdentifierExtension.NAME, new AuthorityKeyIdentifierExtension( new KeyIdentifier(akey), null, null)); } } catch(IOException e) { throw new RuntimeException(e); } return ext; } /** * Prints the usage of this tool. */ private void usage() { if (command != null) { System.err.println("keytool " + command + rb.getString(".OPTION.")); System.err.println(); System.err.println(rb.getString(command.description)); System.err.println(); System.err.println(rb.getString("Options.")); System.err.println(); // Left and right sides of the options list String[] left = new String[command.options.length]; String[] right = new String[command.options.length]; // Check if there's an unknown option boolean found = false; // Length of left side of options list int lenLeft = 0; for (int j=0; j<left.length; j++) { Option opt = command.options[j]; left[j] = opt.toString(); if (opt.arg != null) left[j] += " " + opt.arg; if (left[j].length() > lenLeft) { lenLeft = left[j].length(); } right[j] = rb.getString(opt.description); } for (int j=0; j<left.length; j++) { System.err.printf(" %-" + lenLeft + "s %s\n", left[j], right[j]); } System.err.println(); System.err.println(rb.getString( "Use.keytool.help.for.all.available.commands")); } else { System.err.println(rb.getString( "Key.and.Certificate.Management.Tool")); System.err.println(); System.err.println(rb.getString("Commands.")); System.err.println(); for (Command c: Command.values()) { if (c == KEYCLONE) break; System.err.printf(" %-20s%s\n", c, rb.getString(c.description)); } System.err.println(); System.err.println(rb.getString( "Use.keytool.command.name.help.for.usage.of.command.name")); } } private void tinyHelp() { usage(); if (debug) { throw new RuntimeException("NO BIG ERROR, SORRY"); } else { System.exit(1); } } private void errorNeedArgument(String flag) { Object[] source = {flag}; System.err.println(new MessageFormat( rb.getString("Command.option.flag.needs.an.argument.")).format(source)); tinyHelp(); } private char[] getPass(String modifier, String arg) { char[] output = getPassWithModifier(modifier, arg); if (output != null) return output; tinyHelp(); return null; // Useless, tinyHelp() already exits. } // This method also used by JarSigner public static char[] getPassWithModifier(String modifier, String arg) { if (modifier == null) { return arg.toCharArray(); } else if (collator.compare(modifier, "env") == 0) { String value = System.getenv(arg); if (value == null) { System.err.println(rb.getString( "Cannot.find.environment.variable.") + arg); return null; } else { return value.toCharArray(); } } else if (collator.compare(modifier, "file") == 0) { try { URL url = null; try { url = new URL(arg); } catch (java.net.MalformedURLException mue) { File f = new File(arg); if (f.exists()) { url = f.toURI().toURL(); } else { System.err.println(rb.getString( "Cannot.find.file.") + arg); return null; } } BufferedReader br = new BufferedReader(new InputStreamReader( url.openStream())); String value = br.readLine(); br.close(); if (value == null) { return new char[0]; } else { return value.toCharArray(); } } catch (IOException ioe) { System.err.println(ioe); return null; } } else { System.err.println(rb.getString("Unknown.password.type.") + modifier); return null; } }} // This class is exactly the same as com.sun.tools.javac.util.Pair,// it's copied here since the original one is not included in JRE.class Pair<A, B> { public final A fst; public final B snd; public Pair(A fst, B snd) { this.fst = fst; this.snd = snd; } public String toString() { return "Pair[" + fst + "," + snd + "]"; } private static boolean equals(Object x, Object y) { return (x == null && y == null) || (x != null && x.equals(y)); } public boolean equals(Object other) { return other instanceof Pair && equals(fst, ((Pair)other).fst) && equals(snd, ((Pair)other).snd); } public int hashCode() { if (fst == null) return (snd == null) ? 0 : snd.hashCode() + 1; else if (snd == null) return fst.hashCode() + 2; else return fst.hashCode() * 17 + snd.hashCode(); } public static <A,B> Pair<A,B> of(A a, B b) { return new Pair<>(a,b); }} Lines 4001–4217 of 4217. Previous lines
if (value != null) { data = new byte[value.length() / 2 + 1]; int pos = 0; for (char c: value.toCharArray()) { int hex; if (c >= '0' && c <= '9') { hex = c - '0' ; } else if (c >= 'A' && c <= 'F') { hex = c - 'A' + 10; } else if (c >= 'a' && c <= 'f') { hex = c - 'a' + 10; } else { continue; } if (pos % 2 == 0) { data[pos/2] = (byte)(hex << 4); } else { data[pos/2] += hex; } pos++; } if (pos % 2 != 0) { throw new Exception(rb.getString( "Odd.number.of.hex.digits.found.") + extstr); } data = Arrays.copyOf(data, pos/2); } else { data = new byte[0]; } ext.set(oid.toString(), new Extension(oid, isCritical, new DerValue(DerValue.tag_OctetString, data) .toByteArray())); break; default: throw new Exception(rb.getString( "Unknown.extension.type.") + extstr); } } // always non-critical ext.set(SubjectKeyIdentifierExtension.NAME, new SubjectKeyIdentifierExtension( new KeyIdentifier(pkey).getIdentifier())); if (akey != null && !pkey.equals(akey)) { ext.set(AuthorityKeyIdentifierExtension.NAME, new AuthorityKeyIdentifierExtension( new KeyIdentifier(akey), null, null)); } } catch(IOException e) { throw new RuntimeException(e); } return ext; } /** * Prints the usage of this tool. */ private void usage() { if (command != null) { System.err.println("keytool " + command + rb.getString(".OPTION.")); System.err.println(); System.err.println(rb.getString(command.description)); System.err.println(); System.err.println(rb.getString("Options.")); System.err.println(); // Left and right sides of the options list String[] left = new String[command.options.length]; String[] right = new String[command.options.length]; // Check if there's an unknown option boolean found = false; // Length of left side of options list int lenLeft = 0; for (int j=0; j<left.length; j++) { Option opt = command.options[j]; left[j] = opt.toString(); if (opt.arg != null) left[j] += " " + opt.arg; if (left[j].length() > lenLeft) { lenLeft = left[j].length(); } right[j] = rb.getString(opt.description); } for (int j=0; j<left.length; j++) { System.err.printf(" %-" + lenLeft + "s %s\n", left[j], right[j]); } System.err.println(); System.err.println(rb.getString( "Use.keytool.help.for.all.available.commands")); } else { System.err.println(rb.getString( "Key.and.Certificate.Management.Tool")); System.err.println(); System.err.println(rb.getString("Commands.")); System.err.println(); for (Command c: Command.values()) { if (c == KEYCLONE) break; System.err.printf(" %-20s%s\n", c, rb.getString(c.description)); } System.err.println(); System.err.println(rb.getString( "Use.keytool.command.name.help.for.usage.of.command.name")); } } private void tinyHelp() { usage(); if (debug) { throw new RuntimeException("NO BIG ERROR, SORRY"); } else { System.exit(1); } } private void errorNeedArgument(String flag) { Object[] source = {flag}; System.err.println(new MessageFormat( rb.getString("Command.option.flag.needs.an.argument.")).format(source)); tinyHelp(); } private char[] getPass(String modifier, String arg) { char[] output = getPassWithModifier(modifier, arg); if (output != null) return output; tinyHelp(); return null; // Useless, tinyHelp() already exits. } // This method also used by JarSigner public static char[] getPassWithModifier(String modifier, String arg) { if (modifier == null) { return arg.toCharArray(); } else if (collator.compare(modifier, "env") == 0) { String value = System.getenv(arg); if (value == null) { System.err.println(rb.getString( "Cannot.find.environment.variable.") + arg); return null; } else { return value.toCharArray(); } } else if (collator.compare(modifier, "file") == 0) { try { URL url = null; try { url = new URL(arg); } catch (java.net.MalformedURLException mue) { File f = new File(arg); if (f.exists()) { url = f.toURI().toURL(); } else { System.err.println(rb.getString( "Cannot.find.file.") + arg); return null; } } BufferedReader br = new BufferedReader(new InputStreamReader( url.openStream())); String value = br.readLine(); br.close(); if (value == null) { return new char[0]; } else { return value.toCharArray(); } } catch (IOException ioe) { System.err.println(ioe); return null; } } else { System.err.println(rb.getString("Unknown.password.type.") + modifier); return null; } } } // This class is exactly the same as com.sun.tools.javac.util.Pair, // it's copied here since the original one is not included in JRE. class Pair<A, B> { public final A fst; public final B snd; public Pair(A fst, B snd) { this.fst = fst; this.snd = snd; } public String toString() { return "Pair[" + fst + "," + snd + "]"; } private static boolean equals(Object x, Object y) { return (x == null && y == null) || (x != null && x.equals(y)); } public boolean equals(Object other) { return other instanceof Pair && equals(fst, ((Pair)other).fst) && equals(snd, ((Pair)other).snd); } public int hashCode() { if (fst == null) return (snd == null) ? 0 : snd.hashCode() + 1; else if (snd == null) return fst.hashCode() + 2; else return fst.hashCode() * 17 + snd.hashCode(); } public static <A,B> Pair<A,B> of(A a, B b) { return new Pair<>(a,b); } }