From 19cf8787d8fe6ec0f585a4c14ebe62b6ed3e2f5e Mon Sep 17 00:00:00 2001 From: zzz Date: Wed, 18 Sep 2013 16:53:38 +0000 Subject: [PATCH] - Allow getRawAlgo() for public keys - SU3File better arg processing, implement content type arg - Type checking of Java private key vs. type when signing - Add unknown content type, make default --- core/java/src/net/i2p/crypto/DSAEngine.java | 20 +-- core/java/src/net/i2p/crypto/SU3File.java | 128 ++++++++++++-------- 2 files changed, 88 insertions(+), 60 deletions(-) diff --git a/core/java/src/net/i2p/crypto/DSAEngine.java b/core/java/src/net/i2p/crypto/DSAEngine.java index fb09fd62e..de7a2b553 100644 --- a/core/java/src/net/i2p/crypto/DSAEngine.java +++ b/core/java/src/net/i2p/crypto/DSAEngine.java @@ -34,13 +34,14 @@ import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; import java.security.GeneralSecurityException; +import java.security.Key; import java.security.KeyFactory; import java.security.MessageDigest; import java.security.PrivateKey; import java.security.PublicKey; -import java.security.interfaces.DSAPrivateKey; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.DSAKey; +import java.security.interfaces.ECKey; +import java.security.interfaces.RSAKey; import net.i2p.I2PAppContext; import net.i2p.data.Hash; @@ -364,8 +365,11 @@ public class DSAEngine { * @since 0.9.9 */ public Signature sign(SimpleDataStructure hash, PrivateKey privKey, SigType type) { + String algo = getRawAlgo(privKey); + String talgo = getRawAlgo(type); + if (!algo.equals(talgo)) + throw new IllegalArgumentException("type mismatch type=" + type + " key=" + privKey.getClass().getSimpleName()); try { - String algo = getRawAlgo(privKey); return altSignRaw(algo, hash, privKey, type); } catch (GeneralSecurityException gse) { if (_log.shouldLog(Log.WARN)) @@ -646,12 +650,12 @@ public class DSAEngine { } /** @since 0.9.9 */ - private static String getRawAlgo(PrivateKey privKey) { - if (privKey instanceof DSAPrivateKey) + private static String getRawAlgo(Key key) { + if (key instanceof DSAKey) return "NONEwithDSA"; - if (privKey instanceof ECPrivateKey) + if (key instanceof ECKey) return "NONEwithECDSA"; - if (privKey instanceof RSAPrivateKey) + if (key instanceof RSAKey) return "NONEwithRSA"; throw new IllegalArgumentException(); } diff --git a/core/java/src/net/i2p/crypto/SU3File.java b/core/java/src/net/i2p/crypto/SU3File.java index 630ca2a03..2a81c0952 100644 --- a/core/java/src/net/i2p/crypto/SU3File.java +++ b/core/java/src/net/i2p/crypto/SU3File.java @@ -15,10 +15,15 @@ import java.security.GeneralSecurityException; import java.security.MessageDigest; import java.security.PrivateKey; import java.security.PublicKey; +import java.util.ArrayList; +import java.util.Arrays; import java.util.EnumSet; import java.util.HashMap; +import java.util.Iterator; +import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.NoSuchElementException; import net.i2p.I2PAppContext; import net.i2p.data.DataFormatException; @@ -58,15 +63,11 @@ public class SU3File { private static final int TYPE_ZIP = 0; - private static final int CONTENT_ROUTER = 0; - private static final int CONTENT_ROUTER_P200 = 1; - private static final int CONTENT_PLUGIN = 2; - private static final int CONTENT_RESEED = 3; - private enum ContentType { - ROUTER(0, "update"), - PLUGIN(1, "plugin"), - RESEED(2, "reseed") + UNKNOWN(0, "unknown"), + ROUTER(1, "router"), + PLUGIN(2, "plugin"), + RESEED(3, "reseed") ; private final int code; @@ -78,6 +79,11 @@ public class SU3File { } public int getCode() { return code; } public String getName() { return name; } + + /** @return null if not supported */ + public static ContentType getByCode(int code) { + return BY_CODE.get(Integer.valueOf(code)); + } } private static final Map BY_CODE = new HashMap(); @@ -88,11 +94,8 @@ public class SU3File { } } - /** @return null if not supported */ - public static ContentType getByCode(int code) { - return BY_CODE.get(Integer.valueOf(code)); - } - private static final SigType DEFAULT_TYPE = SigType.DSA_SHA1; + private static final ContentType DEFAULT_CONTENT_TYPE = ContentType.UNKNOWN; + private static final SigType DEFAULT_SIG_TYPE = SigType.DSA_SHA1; /** * @@ -412,27 +415,40 @@ public class SU3File { */ public static void main(String[] args) { boolean ok = false; + List a = new ArrayList(Arrays.asList(args)); try { - if ("showversion".equals(args[0])) { - ok = showVersionCLI(args[1]); - } else if ("sign".equals(args[0])) { - if (args[1].equals("-t")) - ok = signCLI(args[2], args[3], args[4], args[5], args[6], args[7]); - else - ok = signCLI(args[1], args[2], args[3], args[4], args[5]); - } else if ("verifysig".equals(args[0])) { - ok = verifySigCLI(args[1]); - } else if ("keygen".equals(args[0])) { - if (args[1].equals("-t")) - ok = genKeysCLI(args[2], args[3], args[4], args[5]); - else - ok = genKeysCLI(args[1], args[2], args[3]); - } else if ("extract".equals(args[0])) { - ok = extractCLI(args[1], args[2]); + // defaults + String stype = null; + String ctype = null; + Iterator iter = a.iterator(); + String cmd = iter.next(); + iter.remove(); + for ( ; iter.hasNext(); ) { + String arg = iter.next(); + if (arg.equals("-t")) { + iter.remove(); + stype = iter.next(); + } else if (arg.equals("-c")) { + iter.remove(); + ctype = iter.next(); + } + } + if ("showversion".equals(cmd)) { + ok = showVersionCLI(a.get(0)); + } else if ("sign".equals(cmd)) { + ok = signCLI(stype, ctype, a.get(0), a.get(1), a.get(2), a.get(3), a.get(4)); + } else if ("verifysig".equals(cmd)) { + ok = verifySigCLI(a.get(0)); + } else if ("keygen".equals(cmd)) { + ok = genKeysCLI(stype, a.get(0), a.get(1), a.get(2)); + } else if ("extract".equals(cmd)) { + ok = extractCLI(a.get(0), a.get(1)); } else { showUsageCLI(); } - } catch (ArrayIndexOutOfBoundsException aioobe) { + } catch (NoSuchElementException nsee) { + showUsageCLI(); + } catch (IndexOutOfBoundsException ioobe) { showUsageCLI(); } if (!ok) @@ -454,14 +470,14 @@ public class SU3File { buf.append("Available signature types:\n"); for (SigType t : EnumSet.allOf(SigType.class)) { buf.append(" ").append(t).append("\t(code: ").append(t.getCode()).append(')'); - if (t == SigType.DSA_SHA1) + if (t == DEFAULT_SIG_TYPE) buf.append(" DEFAULT"); buf.append('\n'); } buf.append("Available content types:\n"); for (ContentType t : EnumSet.allOf(ContentType.class)) { buf.append(" ").append(t).append("\t(code: ").append(t.getCode()).append(')'); - if (t == ContentType.ROUTER) + if (t == DEFAULT_CONTENT_TYPE) buf.append(" DEFAULT"); buf.append('\n'); } @@ -485,6 +501,23 @@ public class SU3File { } } } + /** + * @param stype number or name + * @return null if not found + * @since 0.9.9 + */ + private static ContentType parseContentType(String ctype) { + try { + return ContentType.valueOf(ctype.toUpperCase(Locale.US)); + } catch (IllegalArgumentException iae) { + try { + int code = Integer.parseInt(ctype); + return ContentType.getByCode(code); + } catch (NumberFormatException nfe) { + return null; + } + } + } /** @return success */ private static final boolean showVersionCLI(String signedFile) { @@ -509,31 +542,30 @@ public class SU3File { } } - /** @return success */ - private static final boolean signCLI(String inputFile, String signedFile, - String privateKeyFile, String version, String signerName) { - return signCLI(DEFAULT_TYPE, inputFile, signedFile, privateKeyFile, version, signerName); - } - /** * @return success * @since 0.9.9 */ - private static final boolean signCLI(String stype, String inputFile, String signedFile, + private static final boolean signCLI(String stype, String ctype, String inputFile, String signedFile, String privateKeyFile, String version, String signerName) { - SigType type = parseSigType(stype); + SigType type = stype == null ? DEFAULT_SIG_TYPE : parseSigType(stype); if (type == null) { System.out.println("Signature type " + stype + " is not supported"); return false; } - return signCLI(type, inputFile, signedFile, privateKeyFile, version, signerName); + ContentType ct = ctype == null ? DEFAULT_CONTENT_TYPE : parseContentType(stype); + if (ct == null) { + System.out.println("Content type " + ctype + " is not supported"); + return false; + } + return signCLI(type, ct, inputFile, signedFile, privateKeyFile, version, signerName); } /** * @return success * @since 0.9.9 */ - private static final boolean signCLI(SigType type, String inputFile, String signedFile, + private static final boolean signCLI(SigType type, ContentType ctype, String inputFile, String signedFile, String privateKeyFile, String version, String signerName) { try { String keypw = ""; @@ -550,7 +582,7 @@ public class SU3File { return false; } SU3File file = new SU3File(signedFile); - file.write(new File(inputFile), CONTENT_ROUTER, version, signerName, pk, type); + file.write(new File(inputFile), ctype.getCode(), version, signerName, pk, type); System.out.println("Input file '" + inputFile + "' signed and written to '" + signedFile + "'"); return true; } catch (GeneralSecurityException gse) { @@ -604,20 +636,12 @@ public class SU3File { } } - /** - * @return success - * @since 0.9.9 - */ - private static final boolean genKeysCLI(String publicKeyFile, String privateKeyFile, String alias) { - return genKeysCLI(DEFAULT_TYPE, publicKeyFile, privateKeyFile, alias); - } - /** * @return success * @since 0.9.9 */ private static final boolean genKeysCLI(String stype, String publicKeyFile, String privateKeyFile, String alias) { - SigType type = parseSigType(stype); + SigType type = stype == null ? DEFAULT_SIG_TYPE : parseSigType(stype); if (type == null) { System.out.println("Signature type " + stype + " is not supported"); return false;