Changes in / [a1c8e3e:6bb1505d]
- Files:
-
- 20 added
- 11 deleted
- 40 edited
Legend:
- Unmodified
- Added
- Removed
-
apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java
ra1c8e3e r6bb1505d 194 194 _uhandler = new UpdateHandler(_context, _umgr, SnarkManager.this); 195 195 _umgr.register(_uhandler, UpdateType.ROUTER_SIGNED, UpdateMethod.TORRENT, 10); 196 _umgr.register(_uhandler, UpdateType.ROUTER_SIGNED_SU3, UpdateMethod.TORRENT, 10); 196 197 _log.warn("Registering with update manager"); 197 198 } else { … … 211 212 //_uhandler.shutdown(); 212 213 _umgr.unregister(_uhandler, UpdateType.ROUTER_SIGNED, UpdateMethod.TORRENT); 214 _umgr.unregister(_uhandler, UpdateType.ROUTER_SIGNED_SU3, UpdateMethod.TORRENT); 213 215 } 214 216 _running = false; -
apps/i2psnark/java/src/org/klomp/snark/UpdateHandler.java
ra1c8e3e r6bb1505d 43 43 public UpdateTask update(UpdateType type, UpdateMethod method, List<URI> updateSources, 44 44 String id, String newVersion, long maxTime) { 45 if ( type != UpdateType.ROUTER_SIGNED||45 if ((type != UpdateType.ROUTER_SIGNED && type != UpdateType.ROUTER_SIGNED_SU3) || 46 46 method != UpdateMethod.TORRENT || updateSources.isEmpty()) 47 47 return null; 48 UpdateRunner update = new UpdateRunner(_context, _umgr, _smgr, updateSources, newVersion);48 UpdateRunner update = new UpdateRunner(_context, _umgr, _smgr, type, updateSources, newVersion); 49 49 _umgr.notifyProgress(update, "<b>" + _smgr.util().getString("Updating") + "</b>"); 50 50 return update; -
apps/i2psnark/java/src/org/klomp/snark/UpdateRunner.java
ra1c8e3e r6bb1505d 23 23 private final UpdateManager _umgr; 24 24 private final SnarkManager _smgr; 25 private final UpdateType _type; 25 26 private final List<URI> _urls; 26 27 private volatile boolean _isRunning; … … 37 38 38 39 public UpdateRunner(I2PAppContext ctx, UpdateManager umgr, SnarkManager smgr, 39 List<URI> uris, String newVersion) {40 UpdateType type, List<URI> uris, String newVersion) { 40 41 _context = ctx; 41 42 _log = ctx.logManager().getLog(getClass()); 42 43 _umgr = umgr; 43 44 _smgr = smgr; 45 _type = type; 44 46 _urls = uris; 45 47 _newVersion = newVersion; … … 57 59 } 58 60 59 public UpdateType getType() { return UpdateType.ROUTER_SIGNED; }61 public UpdateType getType() { return _type; } 60 62 61 63 public UpdateMethod getMethod() { return UpdateMethod.TORRENT; } -
apps/i2psnark/mime.properties
ra1c8e3e r6bb1505d 19 19 rar = application/x-rar-compressed 20 20 su2 = application/zip 21 su3 = application/zip 21 22 sud = application/zip 22 23 tbz = application/x-bzip2 -
apps/routerconsole/java/src/net/i2p/router/update/ConsoleUpdateManager.java
ra1c8e3e r6bb1505d 20 20 21 21 import net.i2p.I2PAppContext; 22 import net.i2p.crypto.SU3File; 22 23 import net.i2p.crypto.TrustedUpdate; 23 24 import net.i2p.data.DataHelper; … … 70 71 /** downloaded AND installed */ 71 72 private final Map<UpdateItem, Version> _installed; 73 private final boolean _allowTorrent; 72 74 private static final DecimalFormat _pct = new DecimalFormat("0.0%"); 73 75 … … 91 93 _installed = new ConcurrentHashMap(); 92 94 _status = ""; 95 // DEBUG slow start for snark updates 96 // For 0.9.4 update, only for dev builds 97 // For 0.9.5 update, only for dev builds and 1% more 98 // For 0.9.6 update, only for dev builds and 3% more 99 // For 0.9.8 update, only for dev builds and 30% more 100 // Remove this for 100% 101 _allowTorrent = RouterVersion.BUILD != 0 || _context.random().nextInt(100) < 30; 93 102 } 94 103 … … 100 109 notifyInstalled(NEWS, "", Long.toString(NewsHelper.lastUpdated(_context))); 101 110 notifyInstalled(ROUTER_SIGNED, "", RouterVersion.VERSION); 111 notifyInstalled(ROUTER_SIGNED_SU3, "", RouterVersion.VERSION); 102 112 // hack to init from the current news file... do this before we register Updaters 103 113 // This will not kick off any Updaters as none are yet registered … … 123 133 Updater u = new UpdateHandler(_context, this); 124 134 register(u, ROUTER_SIGNED, HTTP, 0); 135 if (ConfigUpdateHandler.USE_SU3_UPDATE) { 136 register(c, ROUTER_SIGNED_SU3, HTTP, 0); 137 register(u, ROUTER_SIGNED_SU3, HTTP, 0); 138 // todo 139 //register(c, ROUTER_SIGNED_SU3, HTTPS_CLEARNET, 0); 140 //register(u, ROUTER_SIGNED_SU3, HTTPS_CLEARNET, -10); 141 //register(c, ROUTER_SIGNED_SU3, HTTP_CLEARNET, 0); 142 //register(u, ROUTER_SIGNED_SU3, HTTP_CLEARNET, -20); 143 } 125 144 // TODO see NewsFetcher 126 145 //register(u, ROUTER_SIGNED, HTTPS_CLEARNET, -5); … … 559 578 */ 560 579 public void register(Updater updater, UpdateType type, UpdateMethod method, int priority) { 561 if ((type == ROUTER_SIGNED || type == ROUTER_UNSIGNED) && NewsHelper.dontInstall(_context)) { 580 if ((type == ROUTER_SIGNED || type == ROUTER_UNSIGNED || type == ROUTER_SIGNED_SU3) && 581 NewsHelper.dontInstall(_context)) { 562 582 if (_log.shouldLog(Log.WARN)) 563 583 _log.warn("Ignoring registration for " + type + ", router updates disabled"); 564 584 return; 565 585 } 566 // DEBUG slow start for snark updates 567 // For 0.9.4 update, only for dev builds 568 // For 0.9.5 update, only for dev builds and 1% more 569 // For 0.9.6 update, only for dev builds and 3% more 570 // For 0.9.8 update, only for dev builds and 30% more 571 // Remove this for 100% 572 if (method == TORRENT && RouterVersion.BUILD == 0 && _context.random().nextInt(100) > 29) { 586 if (type == ROUTER_SIGNED_SU3 && !ConfigUpdateHandler.USE_SU3_UPDATE) { 587 if (_log.shouldLog(Log.WARN)) 588 _log.warn("Ignoring registration for " + type + ", SU3 updates disabled"); 589 return; 590 } 591 if (method == TORRENT && !_allowTorrent) { 573 592 if (_log.shouldLog(Log.WARN)) 574 593 _log.warn("Ignoring torrent registration"); … … 724 743 725 744 case ROUTER_SIGNED: 745 case ROUTER_SIGNED_SU3: 726 746 if (shouldInstall() && 727 747 !(isUpdateInProgress(ROUTER_SIGNED) || 748 isUpdateInProgress(ROUTER_SIGNED_SU3) || 728 749 isUpdateInProgress(ROUTER_UNSIGNED))) { 729 750 if (_log.shouldLog(Log.INFO)) … … 762 783 case NEWS: 763 784 case ROUTER_SIGNED: 785 case ROUTER_SIGNED_SU3: 764 786 case ROUTER_UNSIGNED: 765 787 // ConfigUpdateHandler, SummaryHelper, SummaryBarRenderer handle status display … … 878 900 break; 879 901 902 case ROUTER_SIGNED_SU3: 903 rv = handleSu3File(task.getURI(), actualVersion, file); 904 if (rv) 905 notifyDownloaded(task.getType(), task.getID(), actualVersion); 906 break; 907 880 908 case ROUTER_UNSIGNED: 881 909 rv = handleUnsignedFile(task.getURI(), actualVersion, file); … … 933 961 _downloaded.put(ui, ver); 934 962 // one trumps the other 935 if (type == ROUTER_SIGNED) 963 if (type == ROUTER_SIGNED) { 936 964 _downloaded.remove(new UpdateItem(ROUTER_UNSIGNED, "")); 937 else if (type == ROUTER_UNSIGNED) 965 _downloaded.remove(new UpdateItem(ROUTER_SIGNED_SU3, "")); 966 // remove available from other type 967 UpdateItem altui = new UpdateItem(ROUTER_SIGNED_SU3, id); 968 Version old = _available.get(altui); 969 if (old != null && old.compareTo(ver) <= 0) 970 _available.remove(altui); 971 // ... and declare the alt downloaded as well 972 _downloaded.put(altui, ver); 973 } else if (type == ROUTER_SIGNED_SU3) { 938 974 _downloaded.remove(new UpdateItem(ROUTER_SIGNED, "")); 975 _downloaded.remove(new UpdateItem(ROUTER_UNSIGNED, "")); 976 // remove available from other type 977 UpdateItem altui = new UpdateItem(ROUTER_SIGNED, id); 978 Version old = _available.get(altui); 979 if (old != null && old.compareTo(ver) <= 0) 980 _available.remove(altui); 981 // ... and declare the alt downloaded as well 982 _downloaded.put(altui, ver); 983 } else if (type == ROUTER_UNSIGNED) { 984 _downloaded.remove(new UpdateItem(ROUTER_SIGNED, "")); 985 _downloaded.remove(new UpdateItem(ROUTER_SIGNED_SU3, "")); 986 } 939 987 Version old = _available.get(ui); 940 988 if (old != null && old.compareTo(ver) <= 0) … … 970 1018 971 1019 case ROUTER_SIGNED: 1020 { // avoid dup variables in next case 972 1021 String URLs = _context.getProperty(ConfigUpdateHandler.PROP_UPDATE_URL, ConfigUpdateHandler.DEFAULT_UPDATE_URL); 973 1022 StringTokenizer tok = new StringTokenizer(URLs, " ,\r\n"); … … 980 1029 Collections.shuffle(rv, _context.random()); 981 1030 return rv; 1031 } 1032 1033 case ROUTER_SIGNED_SU3: 1034 { 1035 String URLs = ConfigUpdateHandler.SU3_UPDATE_URLS; 1036 StringTokenizer tok = new StringTokenizer(URLs, " ,\r\n"); 1037 List<URI> rv = new ArrayList(); 1038 while (tok.hasMoreTokens()) { 1039 try { 1040 rv.add(new URI(tok.nextToken().trim())); 1041 } catch (URISyntaxException use) {} 1042 } 1043 Collections.shuffle(rv, _context.random()); 1044 return rv; 1045 } 982 1046 983 1047 case ROUTER_UNSIGNED: … … 1012 1076 */ 1013 1077 private boolean handleSudFile(URI uri, String actualVersion, File f) { 1078 return handleRouterFile(uri, actualVersion, f, false); 1079 } 1080 1081 /** 1082 * @return success 1083 * @since 0.9.9 1084 */ 1085 private boolean handleSu3File(URI uri, String actualVersion, File f) { 1086 return handleRouterFile(uri, actualVersion, f, true); 1087 } 1088 1089 /** 1090 * Process sud, su2, or su3 1091 * @return success 1092 * @since 0.9.9 1093 */ 1094 private boolean handleRouterFile(URI uri, String actualVersion, File f, boolean isSU3) { 1014 1095 String url = uri.toString(); 1015 // Process the .sud/.su2 file1016 1096 updateStatus("<b>" + _("Update downloaded") + "</b>"); 1017 TrustedUpdate up = new TrustedUpdate(_context);1018 1097 File to = new File(_context.getRouterDir(), Router.UPDATE_FILE); 1019 String err = up.migrateVerified(RouterVersion.VERSION, f, to); 1020 /////////// 1021 // caller must delete now.. why? 1098 String err; 1099 // Process the file 1100 if (isSU3) { 1101 SU3File up = new SU3File(_context, f); 1102 File temp = new File(_context.getTempDir(), "su3out-" + _context.random().nextLong() + ".zip"); 1103 try { 1104 if (up.verifyAndMigrate(temp)) { 1105 String ver = up.getVersionString(); 1106 int type = up.getContentType(); 1107 if (ver == null || VersionComparator.comp(RouterVersion.VERSION, ver) >= 0) 1108 err = "Old version " + ver; 1109 else if (type != SU3File.CONTENT_ROUTER) 1110 err = "Bad su3 content type " + type; 1111 else if (!FileUtil.copy(temp, to, true, false)) 1112 err = "Failed copy to " + to; 1113 else 1114 err = null; // success 1115 } else { 1116 err = "Signature failed, signer " + DataHelper.stripHTML(up.getSignerString()) + 1117 ' ' + up.getSigType(); 1118 } 1119 } catch (IOException ioe) { 1120 _log.error("SU3 extract error", ioe); 1121 err = DataHelper.stripHTML(ioe.toString()); 1122 } finally { 1123 temp.delete(); 1124 } 1125 } else { 1126 TrustedUpdate up = new TrustedUpdate(_context); 1127 err = up.migrateVerified(RouterVersion.VERSION, f, to); 1128 } 1129 1130 // caller must delete.. could be an active torrent 1022 1131 //f.delete(); 1023 1132 if (err == null) { … … 1278 1387 @Override 1279 1388 public String toString() { 1389 if ("".equals(id)) 1390 return "UpdateItem " + type; 1280 1391 return "UpdateItem " + type + ' ' + id; 1281 1392 } -
apps/routerconsole/java/src/net/i2p/router/update/DummyHandler.java
ra1c8e3e r6bb1505d 49 49 50 50 public DummyRunner(RouterContext ctx, ConsoleUpdateManager mgr, long maxTime) { 51 super(ctx, mgr, Collections.EMPTY_LIST);51 super(ctx, mgr, UpdateType.TYPE_DUMMY, Collections.EMPTY_LIST); 52 52 _delay = maxTime; 53 53 } 54 55 @Override56 public UpdateType getType() { return UpdateType.TYPE_DUMMY; }57 54 58 55 @Override -
apps/routerconsole/java/src/net/i2p/router/update/NewsFetcher.java
ra1c8e3e r6bb1505d 32 32 import net.i2p.util.FileUtil; 33 33 import net.i2p.util.Log; 34 import net.i2p.util.SSLEepGet; 34 35 35 36 /** … … 50 51 51 52 public NewsFetcher(RouterContext ctx, ConsoleUpdateManager mgr, List<URI> uris) { 52 super(ctx, mgr, uris);53 super(ctx, mgr, NEWS, uris); 53 54 _newsFile = new File(ctx.getRouterDir(), NewsHelper.NEWS_FILE); 54 55 _tempFile = new File(ctx.getTempDir(), "tmp-" + ctx.random().nextLong() + TEMP_NEWS_FILE); … … 57 58 _lastModified = RFC822Date.to822Date(lastMod); 58 59 } 59 60 @Override61 public UpdateType getType() { return NEWS; }62 60 63 61 private boolean dontInstall() { … … 77 75 78 76 public void fetchNews() { 79 boolean shouldProxy = Boolean.valueOf(_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY)).booleanValue();77 boolean shouldProxy = _context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY_NEWS, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY_NEWS); 80 78 String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST); 81 79 int proxyPort = ConfigUpdateHandler.proxyPort(_context); … … 92 90 if (shouldProxy) 93 91 get = new EepGet(_context, true, proxyHost, proxyPort, 0, _tempFile.getAbsolutePath(), newsURL, true, null, _lastModified); 92 else if ("https".equals(uri.getScheme())) 93 // no constructor w/ last mod check 94 get = new SSLEepGet(_context, _tempFile.getAbsolutePath(), newsURL); 94 95 else 95 96 get = new EepGet(_context, false, null, 0, 0, _tempFile.getAbsolutePath(), newsURL, true, null, _lastModified); … … 115 116 private static final String SUD_KEY = "sudtorrent"; 116 117 private static final String SU2_KEY = "su2torrent"; 118 private static final String SU3_KEY = "su3torrent"; 117 119 private static final String CLEARNET_SUD_KEY = "sudclearnet"; 118 120 private static final String CLEARNET_SU2_KEY = "su2clearnet"; 121 private static final String CLEARNET_HTTP_SU3_KEY = "su3clearnet"; 122 private static final String CLEARNET_HTTPS_SU3_KEY = "su3ssl"; 119 123 private static final String I2P_SUD_KEY = "sudi2p"; 120 124 private static final String I2P_SU2_KEY = "su2i2p"; … … 150 154 // TODO clearnet URLs, notify with HTTP_CLEARNET and/or HTTPS_CLEARNET 151 155 Map<UpdateMethod, List<URI>> sourceMap = new HashMap(4); 156 // Must do su3 first 157 if (ConfigUpdateHandler.USE_SU3_UPDATE) { 158 sourceMap.put(HTTP, _mgr.getUpdateURLs(ROUTER_SIGNED_SU3, "", HTTP)); 159 addMethod(TORRENT, args.get(SU3_KEY), sourceMap); 160 addMethod(HTTP_CLEARNET, args.get(CLEARNET_HTTP_SU3_KEY), sourceMap); 161 addMethod(HTTPS_CLEARNET, args.get(CLEARNET_HTTPS_SU3_KEY), sourceMap); 162 // notify about all sources at once 163 _mgr.notifyVersionAvailable(this, _currentURI, ROUTER_SIGNED_SU3, 164 "", sourceMap, ver, ""); 165 sourceMap.clear(); 166 } 167 // now do sud/su2 152 168 sourceMap.put(HTTP, _mgr.getUpdateURLs(ROUTER_SIGNED, "", HTTP)); 153 169 String key = FileUtil.isPack200Supported() ? SU2_KEY : SUD_KEY; 154 String murl = args.get(key); 155 if (murl != null) { 156 List<URI> uris = tokenize(murl); 157 if (!uris.isEmpty()) { 158 Collections.shuffle(uris, _context.random()); 159 sourceMap.put(TORRENT, uris); 160 } 161 } 170 addMethod(TORRENT, args.get(key), sourceMap); 162 171 // notify about all sources at once 163 _mgr.notifyVersionAvailable(this, _currentURI, 164 ROUTER_SIGNED, "", sourceMap, 165 ver, ""); 172 _mgr.notifyVersionAvailable(this, _currentURI, ROUTER_SIGNED, 173 "", sourceMap, ver, ""); 166 174 } else { 167 175 if (_log.shouldLog(Log.DEBUG)) … … 267 275 } 268 276 277 /** 278 * Parse URLs and add to the map 279 * @param urls may be null 280 * @since 0.9.9 281 */ 282 private void addMethod(UpdateMethod method, String urls, Map<UpdateMethod, List<URI>> map) { 283 if (urls != null) { 284 List<URI> uris = tokenize(urls); 285 if (!uris.isEmpty()) { 286 Collections.shuffle(uris, _context.random()); 287 map.put(method, uris); 288 } 289 } 290 } 291 269 292 /** override to prevent status update */ 270 293 @Override -
apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateChecker.java
ra1c8e3e r6bb1505d 36 36 public PluginUpdateChecker(RouterContext ctx, ConsoleUpdateManager mgr, 37 37 List<URI> uris, String appName, String oldVersion ) { 38 super(ctx, mgr, uris, oldVersion);38 super(ctx, mgr, UpdateType.PLUGIN, uris, oldVersion); 39 39 if (!uris.isEmpty()) 40 40 _currentURI = uris.get(0); … … 42 42 _oldVersion = oldVersion; 43 43 } 44 45 @Override46 public UpdateType getType() { return UpdateType.PLUGIN; }47 44 48 45 @Override -
apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java
ra1c8e3e r6bb1505d 61 61 public PluginUpdateRunner(RouterContext ctx, ConsoleUpdateManager mgr, List<URI> uris, 62 62 String appName, String oldVersion ) { 63 super(ctx, mgr, uris);63 super(ctx, mgr, UpdateType.PLUGIN, uris); 64 64 if (uris.isEmpty()) 65 65 throw new IllegalArgumentException("uri cannot be empty"); … … 69 69 _appName = appName; 70 70 _oldVersion = oldVersion; 71 }72 73 74 @Override75 public UpdateType getType() {76 return UpdateType.PLUGIN;77 71 } 78 72 … … 105 99 updateStatus("<b>" + _("Downloading plugin from {0}", _xpi2pURL) + "</b>"); 106 100 // use the same settings as for updater 107 boolean shouldProxy = Boolean.valueOf(_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY)).booleanValue();101 boolean shouldProxy = _context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY); 108 102 String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST); 109 103 int proxyPort = ConfigUpdateHandler.proxyPort(_context); -
apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateChecker.java
ra1c8e3e r6bb1505d 29 29 public UnsignedUpdateChecker(RouterContext ctx, ConsoleUpdateManager mgr, 30 30 List<URI> uris, long lastUpdateTime) { 31 super(ctx, mgr, uris);31 super(ctx, mgr, UpdateType.ROUTER_UNSIGNED, uris); 32 32 _ms = lastUpdateTime; 33 33 } 34 35 //////// begin UpdateTask methods36 37 @Override38 public UpdateType getType() { return UpdateType.ROUTER_UNSIGNED; }39 40 //////// end UpdateTask methods41 34 42 35 @Override -
apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateRunner.java
ra1c8e3e r6bb1505d 26 26 27 27 public UnsignedUpdateRunner(RouterContext ctx, ConsoleUpdateManager mgr, List<URI> uris) { 28 super(ctx, mgr, uris);28 super(ctx, mgr, ROUTER_UNSIGNED, uris); 29 29 if (!uris.isEmpty()) 30 30 _currentURI = uris.get(0); 31 31 } 32 33 34 @Override35 public UpdateType getType() { return ROUTER_UNSIGNED; }36 32 37 33 -
apps/routerconsole/java/src/net/i2p/router/update/UpdateHandler.java
ra1c8e3e r6bb1505d 5 5 6 6 import net.i2p.router.RouterContext; 7 import net.i2p.router.web.ConfigUpdateHandler; 7 8 import net.i2p.update.*; 9 import static net.i2p.update.UpdateType.*; 10 import static net.i2p.update.UpdateMethod.*; 8 11 9 12 /** … … 39 42 public UpdateTask update(UpdateType type, UpdateMethod method, List<URI> updateSources, 40 43 String id, String newVersion, long maxTime) { 41 if (type != UpdateType.ROUTER_SIGNED || 42 method != UpdateMethod.HTTP || updateSources.isEmpty()) 44 boolean shouldProxy = _context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY); 45 if ((type != ROUTER_SIGNED && type != ROUTER_SIGNED_SU3) || 46 (shouldProxy && method != HTTP) || 47 ((!shouldProxy) && method != HTTP_CLEARNET && method != HTTPS_CLEARNET) || 48 updateSources.isEmpty()) 43 49 return null; 44 UpdateRunner update = new UpdateRunner(_context, _mgr, updateSources);50 UpdateRunner update = new UpdateRunner(_context, _mgr, type, method, updateSources); 45 51 // set status before thread to ensure UI feedback 46 52 _mgr.notifyProgress(update, "<b>" + _mgr._("Updating") + "</b>"); -
apps/routerconsole/java/src/net/i2p/router/update/UpdateRunner.java
ra1c8e3e r6bb1505d 6 6 import java.net.URI; 7 7 import java.util.List; 8 import java.util.Locale; 8 9 import java.util.StringTokenizer; 9 10 … … 14 15 import net.i2p.router.web.ConfigUpdateHandler; 15 16 import net.i2p.update.*; 17 import static net.i2p.update.UpdateMethod.*; 16 18 import net.i2p.util.EepGet; 17 19 import net.i2p.util.I2PAppThread; 18 20 import net.i2p.util.Log; 19 21 import net.i2p.util.PartialEepGet; 22 import net.i2p.util.SSLEepGet; 20 23 import net.i2p.util.VersionComparator; 21 24 … … 31 34 protected final Log _log; 32 35 protected final ConsoleUpdateManager _mgr; 36 protected final UpdateType _type; 37 protected final UpdateMethod _method; 33 38 protected final List<URI> _urls; 34 39 protected final String _updateFile; … … 54 59 * Uses router version for partial checks 55 60 */ 56 public UpdateRunner(RouterContext ctx, ConsoleUpdateManager mgr, List<URI> uris) { 57 this(ctx, mgr, uris, RouterVersion.VERSION); 61 public UpdateRunner(RouterContext ctx, ConsoleUpdateManager mgr, UpdateType type, List<URI> uris) { 62 this(ctx, mgr, type, uris, RouterVersion.VERSION); 63 } 64 65 /** 66 * Uses router version for partial checks 67 * @since 0.9.9 68 */ 69 public UpdateRunner(RouterContext ctx, ConsoleUpdateManager mgr, UpdateType type, 70 UpdateMethod method, List<URI> uris) { 71 this(ctx, mgr, type, method, uris, RouterVersion.VERSION); 58 72 } 59 73 … … 62 76 * @since 0.9.7 63 77 */ 64 public UpdateRunner(RouterContext ctx, ConsoleUpdateManager mgr, List<URI> uris, String currentVersion) { 78 public UpdateRunner(RouterContext ctx, ConsoleUpdateManager mgr, UpdateType type, 79 List<URI> uris, String currentVersion) { 80 this(ctx, mgr, type, HTTP, uris, currentVersion); 81 } 82 83 /** 84 * @param method HTTP, HTTP_CLEARNET, or HTTPS_CLEARNET 85 * @param currentVersion used for partial checks 86 * @since 0.9.9 87 */ 88 public UpdateRunner(RouterContext ctx, ConsoleUpdateManager mgr, UpdateType type, 89 UpdateMethod method, List<URI> uris, String currentVersion) { 65 90 super("Update Runner"); 66 91 setDaemon(true); … … 68 93 _log = ctx.logManager().getLog(getClass()); 69 94 _mgr = mgr; 95 _type = type; 96 _method = method; 70 97 _urls = uris; 71 98 _baos = new ByteArrayOutputStream(TrustedUpdate.HEADER_BYTES); … … 83 110 } 84 111 85 public UpdateType getType() { return UpdateType.ROUTER_SIGNED; }86 87 public UpdateMethod getMethod() { return UpdateMethod.HTTP; }112 public UpdateType getType() { return _type; } 113 114 public UpdateMethod getMethod() { return _method; } 88 115 89 116 public URI getURI() { return _currentURI; } … … 118 145 // we've received at least 56 bytes. Need a cancel() method in EepGet ? 119 146 120 boolean shouldProxy = Boolean.valueOf(_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY)).booleanValue(); 121 String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST); 122 int proxyPort = ConfigUpdateHandler.proxyPort(_context); 147 boolean shouldProxy; 148 String proxyHost; 149 int proxyPort; 150 boolean isSSL = false; 151 if (_method == HTTP) { 152 shouldProxy = _context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY); 153 if (shouldProxy) { 154 proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST); 155 proxyPort = ConfigUpdateHandler.proxyPort(_context); 156 } else { 157 // TODO, wrong method, fail 158 proxyHost = null; 159 proxyPort = 0; 160 } 161 } else if (_method == HTTP_CLEARNET) { 162 shouldProxy = false; 163 proxyHost = null; 164 proxyPort = 0; 165 } else if (_method == HTTPS_CLEARNET) { 166 shouldProxy = false; 167 proxyHost = null; 168 proxyPort = 0; 169 isSSL = true; 170 } else { 171 throw new IllegalArgumentException(); 172 } 123 173 124 174 if (_urls.isEmpty()) { … … 133 183 _currentURI = uri; 134 184 String updateURL = uri.toString(); 185 if ((_method == HTTP && !"http".equals(uri.getScheme())) || 186 (_method == HTTP_CLEARNET && !"http".equals(uri.getScheme())) || 187 (_method == HTTPS_CLEARNET && !"https".equals(uri.getScheme())) || 188 uri.getHost() == null || 189 (_method != HTTP && uri.getHost().toLowerCase(Locale.US).endsWith(".i2p"))) { 190 if (_log.shouldLog(Log.WARN)) 191 _log.warn("Bad update URI " + uri + " for method " + _method); 192 continue; 193 } 194 135 195 updateStatus("<b>" + _("Updating from {0}", linkify(updateURL)) + "</b>"); 136 196 if (_log.shouldLog(Log.DEBUG)) … … 138 198 139 199 // Check the first 56 bytes for the version 140 if (shouldProxy) { 200 // FIXME PartialEepGet works with clearnet but not with SSL 201 _newVersion = null; 202 if (!isSSL) { 141 203 _isPartial = true; 142 204 _baos.reset(); … … 158 220 // 40 retries!! 159 221 _get = new EepGet(_context, proxyHost, proxyPort, 40, _updateFile, updateURL, false); 222 else if (isSSL) 223 _get = new SSLEepGet(_context, _updateFile, updateURL); 160 224 else 161 225 _get = new EepGet(_context, 1, _updateFile, updateURL, false); … … 209 273 } 210 274 275 // FIXME if we didn't do a partial, we don't know 276 if (_newVersion == null) 277 _newVersion = "unknown"; 211 278 File tmp = new File(_updateFile); 212 279 if (_mgr.notifyComplete(this, _newVersion, tmp)) -
apps/routerconsole/java/src/net/i2p/router/web/ConfigTunnelsHelper.java
ra1c8e3e r6bb1505d 14 14 private static final String HOPS = ngettext("1 hop", "{0} hops"); 15 15 private static final String TUNNELS = ngettext("1 tunnel", "{0} tunnels"); 16 17 static final String PROP_ADVANCED = "routerconsole.advanced";18 16 19 17 public String getForm() { … … 70 68 private void renderForm(StringBuilder buf, int index, String prefix, String name, TunnelPoolSettings in, TunnelPoolSettings out) { 71 69 72 boolean advanced = _context.getBooleanProperty(PROP_ADVANCED);70 boolean advanced = isAdvanced(); 73 71 74 72 buf.append("<tr><th colspan=\"3\"><a name=\"").append(prefix).append("\">"); -
apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHandler.java
ra1c8e3e r6bb1505d 1 1 package net.i2p.router.web; 2 2 3 import java.io.File; 3 4 import java.util.HashMap; 4 5 import java.util.Map; … … 23 24 private String _proxyPort; 24 25 private boolean _updateThroughProxy; 26 private boolean _newsThroughProxy; 25 27 private String _trustedKeys; 26 28 private boolean _updateUnsigned; … … 37 39 public static final String DEFAULT_UPDATE_POLICY = "download"; 38 40 public static final String PROP_SHOULD_PROXY = "router.updateThroughProxy"; 39 public static final String DEFAULT_SHOULD_PROXY = Boolean.TRUE.toString(); 41 public static final boolean DEFAULT_SHOULD_PROXY = true; 42 /** @since 0.9.9 */ 43 public static final String PROP_SHOULD_PROXY_NEWS = "router.fetchNewsThroughProxy"; 44 /** @since 0.9.9 */ 45 public static final boolean DEFAULT_SHOULD_PROXY_NEWS = true; 40 46 public static final String PROP_PROXY_HOST = "router.updateProxyHost"; 41 47 public static final String DEFAULT_PROXY_HOST = "127.0.0.1"; … … 51 57 52 58 public static final String PROP_UPDATE_URL = "router.updateURL"; 59 53 60 /** 54 61 * Changed as of release 0.8 to support both .sud and .su2 … … 76 83 "http://update.postman.i2p/i2pupdate.sud" ; 77 84 85 /** 86 * These are only for .sud and .su2. 87 * Do NOT use this for .su3 88 */ 78 89 public static final String DEFAULT_UPDATE_URL; 79 90 static { … … 83 94 DEFAULT_UPDATE_URL = NO_PACK200_URLS; 84 95 } 96 97 private static final String SU3_CERT_DIR = "certificates/router"; 98 99 /** 100 * Only enabled if we have pack200 and trusted public key certificates installed 101 * @since 0.9.9 102 */ 103 public static final boolean USE_SU3_UPDATE; 104 static { 105 String[] files = (new File(I2PAppContext.getGlobalContext().getBaseDir(), SU3_CERT_DIR)).list(); 106 USE_SU3_UPDATE = FileUtil.isPack200Supported() && files != null && files.length > 0; 107 } 108 109 private static final String DEFAULT_SU3_UPDATE_URLS = 110 "http://echelon.i2p/i2p/i2pupdate.su3\r\n" + 111 "http://inr.i2p/i2p/i2pupdate.su3\r\n" + 112 "http://meeh.i2p/i2pupdate/i2pupdate.su3\r\n" + 113 "http://stats.i2p/i2p/i2pupdate.su3\r\n" + 114 "http://www.i2p2.i2p/_static/i2pupdate.su3\r\n" + 115 "http://update.dg.i2p/files/i2pupdate.su3\r\n" + 116 "http://update.killyourtv.i2p/i2pupdate.su3\r\n" + 117 "http://update.postman.i2p/i2pupdate.su3" ; 118 119 /** 120 * Empty string if disabled. Cannot be overridden by config. 121 * @since 0.9.9 122 */ 123 public static final String SU3_UPDATE_URLS = USE_SU3_UPDATE ? DEFAULT_SU3_UPDATE_URLS : ""; 85 124 86 125 public static final String PROP_TRUSTED_KEYS = "router.trustedUpdateKeys"; … … 131 170 132 171 if ( (_newsURL != null) && (_newsURL.length() > 0) ) { 172 if (_newsURL.startsWith("https")) 173 _newsThroughProxy = false; 133 174 String oldURL = ConfigUpdateHelper.getNewsURL(_context); 134 175 if ( (oldURL == null) || (!_newsURL.equals(oldURL)) ) { … … 156 197 } 157 198 158 changes.put(PROP_SHOULD_PROXY, "" + _updateThroughProxy); 159 changes.put(PROP_UPDATE_UNSIGNED, "" + _updateUnsigned); 199 changes.put(PROP_SHOULD_PROXY, Boolean.toString(_updateThroughProxy)); 200 changes.put(PROP_SHOULD_PROXY_NEWS, Boolean.toString(_newsThroughProxy)); 201 changes.put(PROP_UPDATE_UNSIGNED, Boolean.toString(_updateUnsigned)); 160 202 161 203 String oldFreqStr = _context.getProperty(PROP_REFRESH_FREQUENCY, DEFAULT_REFRESH_FREQUENCY); … … 219 261 public void setUpdateUnsigned(String foo) { _updateUnsigned = true; } 220 262 public void setZipURL(String url) { _zipURL = url; } 263 /** @since 0.9.9 */ 264 public void setNewsThroughProxy(String foo) { _newsThroughProxy = true; } 221 265 } -
apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHelper.java
ra1c8e3e r6bb1505d 74 74 75 75 public String getUpdateThroughProxy() { 76 String proxy = _context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY); 77 if (Boolean.parseBoolean(proxy)) 76 if (_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY)) 78 77 return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateThroughProxy\" checked=\"checked\" >"; 79 78 else 80 79 return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateThroughProxy\" >"; 80 } 81 82 /** @since 0.9.9 */ 83 public String getNewsThroughProxy() { 84 if (_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY_NEWS, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY_NEWS)) 85 return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"newsThroughProxy\" checked=\"checked\" >"; 86 else 87 return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"newsThroughProxy\" >"; 81 88 } 82 89 -
apps/routerconsole/java/src/net/i2p/router/web/HelperBase.java
ra1c8e3e r6bb1505d 12 12 protected Writer _out; 13 13 14 static final String PROP_ADVANCED = "routerconsole.advanced"; 15 14 16 /** 15 17 * Configure this bean to query a particular router context … … 24 26 t.printStackTrace(); 25 27 } 28 } 29 30 /** @since 0.9.9 */ 31 public boolean isAdvanced() { 32 return _context.getBooleanProperty(PROP_ADVANCED); 26 33 } 27 34 -
apps/routerconsole/java/src/net/i2p/router/web/NewsHelper.java
ra1c8e3e r6bb1505d 50 50 if (mgr == null) return false; 51 51 return mgr.isUpdateInProgress(ROUTER_SIGNED) || 52 mgr.isUpdateInProgress(ROUTER_SIGNED_SU3) || 52 53 mgr.isUpdateInProgress(ROUTER_UNSIGNED) || 53 54 mgr.isUpdateInProgress(TYPE_DUMMY); … … 61 62 ConsoleUpdateManager mgr = ConsoleUpdateManager.getInstance(); 62 63 if (mgr == null) return false; 63 return mgr.getUpdateAvailable(ROUTER_SIGNED) != null; 64 return mgr.getUpdateAvailable(ROUTER_SIGNED) != null || 65 mgr.getUpdateAvailable(ROUTER_SIGNED_SU3) != null; 64 66 } 65 67 … … 72 74 ConsoleUpdateManager mgr = ConsoleUpdateManager.getInstance(); 73 75 if (mgr == null) return null; 76 String rv = mgr.getUpdateAvailable(ROUTER_SIGNED_SU3); 77 if (rv != null) 78 return rv; 74 79 return mgr.getUpdateAvailable(ROUTER_SIGNED); 75 80 } … … 83 88 ConsoleUpdateManager mgr = ConsoleUpdateManager.getInstance(); 84 89 if (mgr == null) return null; 90 String rv = mgr.getUpdateDownloaded(ROUTER_SIGNED_SU3); 91 if (rv != null) 92 return rv; 85 93 return mgr.getUpdateDownloaded(ROUTER_SIGNED); 86 94 } -
apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java
ra1c8e3e r6bb1505d 28 28 import static net.i2p.app.ClientAppState.*; 29 29 import net.i2p.apps.systray.SysTray; 30 import net.i2p.crypto.KeyStoreUtil; 30 31 import net.i2p.data.Base32; 31 32 import net.i2p.data.DataHelper; … … 39 40 import net.i2p.util.PortMapper; 40 41 import net.i2p.util.SecureDirectory; 41 import net.i2p.util.SecureFileOutputStream;42 import net.i2p.util.ShellCommand;43 42 import net.i2p.util.SystemVersion; 44 43 import net.i2p.util.VersionComparator; … … 676 675 return rv; 677 676 } 678 File dir = ks.getParentFile();679 if (!dir.exists()) {680 File sdir = new SecureDirectory(dir.getAbsolutePath());681 if (!sdir.mkdir())682 return false;683 }684 677 return createKeyStore(ks); 685 678 } … … 696 689 private boolean createKeyStore(File ks) { 697 690 // make a random 48 character password (30 * 8 / 5) 698 byte[] rand = new byte[30]; 699 _context.random().nextBytes(rand); 700 String keyPassword = Base32.encode(rand); 691 String keyPassword = KeyStoreUtil.randomString(); 701 692 // and one for the cname 702 _context.random().nextBytes(rand); 703 String cname = Base32.encode(rand) + ".console.i2p.net"; 704 705 String keytool = (new File(System.getProperty("java.home"), "bin/keytool")).getAbsolutePath(); 706 String[] args = new String[] { 707 keytool, 708 "-genkey", // -genkeypair preferred in newer keytools, but this works with more 709 "-storetype", KeyStore.getDefaultType(), 710 "-keystore", ks.getAbsolutePath(), 711 "-storepass", DEFAULT_KEYSTORE_PASSWORD, 712 "-alias", "console", 713 "-dname", "CN=" + cname + ",OU=Console,O=I2P Anonymous Network,L=XX,ST=XX,C=XX", 714 "-validity", "3652", // 10 years 715 "-keyalg", "DSA", 716 "-keysize", "1024", 717 "-keypass", keyPassword}; 718 boolean success = (new ShellCommand()).executeSilentAndWaitTimed(args, 30); // 30 secs 693 String cname = KeyStoreUtil.randomString() + ".console.i2p.net"; 694 boolean success = KeyStoreUtil.createKeys(ks, "console", cname, "Console", keyPassword); 719 695 if (success) { 720 696 success = ks.exists(); 721 697 if (success) { 722 SecureFileOutputStream.setPerms(ks);723 698 try { 724 699 Map<String, String> changes = new HashMap(); … … 734 709 "IP address, host name, router identity, or destination keys."); 735 710 } else { 736 System.err.println("Failed to create console SSL keystore using command line:"); 737 StringBuilder buf = new StringBuilder(256); 738 for (int i = 0; i < args.length; i++) { 739 buf.append('"').append(args[i]).append("\" "); 740 } 741 System.err.println(buf.toString()); 742 System.err.println("This is for the Sun/Oracle keytool, others may be incompatible.\n" + 711 System.err.println("Failed to create console SSL keystore.\n" + 712 "This is for the Sun/Oracle keytool, others may be incompatible.\n" + 743 713 "If you create the keystore manually, you must add " + PROP_KEYSTORE_PASSWORD + " and " + PROP_KEY_PASSWORD + 744 714 " to " + (new File(_context.getConfigDir(), "router.config")).getAbsolutePath()); -
apps/routerconsole/java/src/net/i2p/router/web/TunnelRenderer.java
ra1c8e3e r6bb1505d 40 40 Map<Hash, TunnelPool> clientOutboundPools = _context.tunnelManager().getOutboundClientPools(); 41 41 destinations = new ArrayList(clientInboundPools.keySet()); 42 boolean debug = _context.getBooleanProperty( ConfigTunnelsHelper.PROP_ADVANCED);42 boolean debug = _context.getBooleanProperty(HelperBase.PROP_ADVANCED); 43 43 for (int i = 0; i < destinations.size(); i++) { 44 44 Hash client = destinations.get(i); -
apps/routerconsole/java/src/net/i2p/router/web/UpdateHandler.java
ra1c8e3e r6bb1505d 67 67 if (_action.contains("Unsigned")) { 68 68 update(ROUTER_UNSIGNED); 69 } else if (ConfigUpdateHandler.USE_SU3_UPDATE) { 70 update(ROUTER_SIGNED_SU3); 69 71 } else { 70 72 update(ROUTER_SIGNED); … … 77 79 if (mgr == null) 78 80 return; 79 if (mgr.isUpdateInProgress(ROUTER_SIGNED) || mgr.isUpdateInProgress(ROUTER_UNSIGNED)) { 81 if (mgr.isUpdateInProgress(ROUTER_SIGNED) || mgr.isUpdateInProgress(ROUTER_UNSIGNED) || 82 mgr.isUpdateInProgress(ROUTER_SIGNED_SU3)) { 80 83 _log.error("Update already running"); 81 84 return; -
apps/routerconsole/jsp/configupdate.jsp
ra1c8e3e r6bb1505d 49 49 <td><jsp:getProperty name="updatehelper" property="updatePolicySelectBox" /></td></tr> 50 50 <% } // if canInstall %> 51 <tr><td class="mediumtags" align="right"><b><%=intl._("Fetch news through the eepProxy?")%></b></td> 52 <td><jsp:getProperty name="updatehelper" property="newsThroughProxy" /></td></tr> 51 53 <tr><td class="mediumtags" align="right"><b><%=intl._("Update through the eepProxy?")%></b></td> 52 <td><jsp:getProperty name="updatehelper" property="updateThroughProxy" /></td> 53 </tr><tr><td class="mediumtags" align="right"><b><%=intl._("eepProxy host")%>:</b></td> 54 <td><jsp:getProperty name="updatehelper" property="updateThroughProxy" /></td></tr> 55 <% if (updatehelper.isAdvanced()) { %> 56 <tr><td class="mediumtags" align="right"><b><%=intl._("eepProxy host")%>:</b></td> 54 57 <td><input type="text" size="10" name="proxyHost" value="<jsp:getProperty name="updatehelper" property="proxyHost" />" /></td> 55 58 </tr><tr><td class="mediumtags" align="right"><b><%=intl._("eepProxy port")%>:</b></td> 56 59 <td><input type="text" size="10" name="proxyPort" value="<jsp:getProperty name="updatehelper" property="proxyPort" />" /></td></tr> 60 <% } // if isAdvanced %> 57 61 <% if (updatehelper.canInstall()) { %> 62 <% if (updatehelper.isAdvanced()) { %> 58 63 <tr><td class="mediumtags" align="right"><b><%=intl._("Update URLs")%>:</b></td> 59 64 <td><textarea cols="60" rows="6" name="updateURL" wrap="off" spellcheck="false"><jsp:getProperty name="updatehelper" property="updateURL" /></textarea></td> 60 65 </tr><tr><td class="mediumtags" align="right"><b><%=intl._("Trusted keys")%>:</b></td> 61 <td><textarea cols="60" rows="6" name="trustedKeys" wrap="off" spellcheck="false"><jsp:getProperty name="updatehelper" property="trustedKeys" /></textarea></td> 62 </tr><tr><td id="unsignedbuild" class="mediumtags" align="right"><b><%=intl._("Update with unsigned development builds?")%></b></td> 66 <td><textarea cols="60" rows="6" name="trustedKeys" wrap="off" spellcheck="false"><jsp:getProperty name="updatehelper" property="trustedKeys" /></textarea></td></tr> 67 <% } // if isAdvanced %> 68 <tr><td id="unsignedbuild" class="mediumtags" align="right"><b><%=intl._("Update with unsigned development builds?")%></b></td> 63 69 <td><jsp:getProperty name="updatehelper" property="updateUnsigned" /></td> 64 70 </tr><tr><td class="mediumtags" align="right"><b><%=intl._("Unsigned Build URL")%>:</b></td> -
build.xml
ra1c8e3e r6bb1505d 1498 1498 </fail> 1499 1499 <echo message="Key file is ${release.privkey}" /> 1500 <!-- now build and verify the unpacked sud from the unpacked zip --> 1500 1501 <java classname="net.i2p.crypto.TrustedUpdate" fork="true" failonerror="true"> 1501 1502 <classpath> … … 1530 1531 <arg value="i2pupdate.sud" /> 1531 1532 </java> 1532 <!-- now build and verify the packed su dfrom the packed zip -->1533 <!-- now build and verify the packed su2 from the packed zip --> 1533 1534 <java classname="net.i2p.crypto.TrustedUpdate" fork="true" failonerror="true"> 1534 1535 <classpath> … … 1563 1564 <arg value="i2pupdate.su2" /> 1564 1565 </java> 1566 <!-- now build and verify the packed su3 from the packed zip --> 1567 <input message="Enter su3 private signing key store:" addproperty="release.privkey.su3" /> 1568 <fail message="You must enter a path." > 1569 <condition> 1570 <equals arg1="${release.privkey.su3}" arg2=""/> 1571 </condition> 1572 </fail> 1573 <input message="Enter key name (you@mail.i2p):" addproperty="release.signer.su3" /> 1574 <fail message="You must enter a name." > 1575 <condition> 1576 <equals arg1="${release.signer.su3}" arg2=""/> 1577 </condition> 1578 </fail> 1579 <input message="Enter key password for ${release.signer.su3}:" addproperty="release.password.su3" /> 1580 <fail message="You must enter a password." > 1581 <condition> 1582 <equals arg1="${release.password.su3}" arg2=""/> 1583 </condition> 1584 </fail> 1585 <java classname="net.i2p.crypto.SU3File" inputstring="${release.password.su3}" fork="true" failonerror="true"> 1586 <classpath> 1587 <pathelement location="build/i2p.jar" /> 1588 </classpath> 1589 <arg value="sign" /> 1590 <arg value="-c" /> 1591 <arg value="ROUTER" /> 1592 <arg value="-t" /> 1593 <arg value="RSA_SHA512_4096" /> 1594 <arg value="i2pupdate200.zip" /> 1595 <arg value="i2pupdate.su3" /> 1596 <arg value="${release.privkey.su3}" /> 1597 <arg value="${release.number}" /> 1598 <arg value="${release.signer.su3}" /> 1599 </java> 1600 <echo message="Verify version and VALID signature:" /> 1601 <java classname="net.i2p.crypto.SU3File" fork="true" failonerror="true"> 1602 <classpath> 1603 <pathelement location="build/i2p.jar" /> 1604 </classpath> 1605 <!-- set base dir so it can find the pubkey cert --> 1606 <jvmarg value="-Di2p.dir.base=installer/resources" /> 1607 <arg value="verifysig" /> 1608 <arg value="i2pupdate.su3" /> 1609 </java> 1610 <java classname="net.i2p.crypto.SU3File" fork="true" failonerror="true"> 1611 <classpath> 1612 <pathelement location="build/i2p.jar" /> 1613 </classpath> 1614 <!-- set base dir so it can find the pubkey cert --> 1615 <jvmarg value="-Di2p.dir.base=installer/resources" /> 1616 <arg value="showversion" /> 1617 <arg value="i2pupdate.su3" /> 1618 </java> 1565 1619 <!-- will this use the monotonerc file in the current workspace? --> 1566 1620 <echo message="Checking out fresh copy into ../i2p-${release.number} for tarballing:" /> … … 1610 1664 <arg value="i2pupdate_${release.number}.zip" /> 1611 1665 <arg value="i2pupdate.su2" /> 1666 <arg value="i2pupdate.su3" /> 1612 1667 <arg value="i2pupdate.sud" /> 1613 1668 <arg value="i2pinstall_${release.number}_windows.exe.sig" /> … … 1624 1679 <arg value="i2pupdate_${release.number}.zip" /> 1625 1680 <arg value="i2pupdate.su2" /> 1681 <arg value="i2pupdate.su3" /> 1626 1682 <arg value="i2pupdate.sud" /> 1627 1683 <arg value="i2pinstall_${release.number}_windows.exe.sig" /> … … 1637 1693 <arg value="i2pupdate_${release.number}.zip" /> 1638 1694 <arg value="i2pupdate.su2" /> 1695 <arg value="i2pupdate.su3" /> 1639 1696 <arg value="i2pupdate.sud" /> 1640 1697 </exec> … … 1656 1713 </classpath> 1657 1714 <arg value="i2pupdate-${release.number}.su2" /> 1715 <arg value="http://tracker2.postman.i2p/announce.php" /> 1716 </java> 1717 <copy file="i2pupdate.su3" tofile="i2pupdate-${release.number}.su3" /> 1718 <java classname="org.klomp.snark.Storage" fork="true" failonerror="true"> 1719 <classpath> 1720 <pathelement location="build/i2p.jar" /> 1721 <pathelement location="build/i2psnark.jar" /> 1722 </classpath> 1723 <arg value="i2pupdate-${release.number}.su3" /> 1658 1724 <arg value="http://tracker2.postman.i2p/announce.php" /> 1659 1725 </java> -
core/java/src/net/i2p/client/I2CPSSLSocketFactory.java
ra1c8e3e r6bb1505d 8 8 import java.security.KeyStore; 9 9 import java.security.GeneralSecurityException; 10 import java.security.cert.CertificateExpiredException;11 import java.security.cert.CertificateNotYetValidException;12 import java.security.cert.CertificateFactory;13 import java.security.cert.X509Certificate;14 import java.util.Locale;15 10 16 11 import javax.net.ssl.SSLContext; … … 19 14 20 15 import net.i2p.I2PAppContext; 16 import net.i2p.crypto.KeyStoreUtil; 21 17 import net.i2p.util.Log; 22 18 … … 72 68 73 69 File dir = new File(context.getConfigDir(), CERT_DIR); 74 int adds = addCerts(dir, ks);70 int adds = KeyStoreUtil.addCerts(dir, ks); 75 71 int totalAdds = adds; 76 72 if (adds > 0) … … 79 75 File dir2 = new File(System.getProperty("user.dir"), CERT_DIR); 80 76 if (!dir.getAbsolutePath().equals(dir2.getAbsolutePath())) { 81 adds = addCerts(dir2, ks);77 adds = KeyStoreUtil.addCerts(dir2, ks); 82 78 totalAdds += adds; 83 79 if (adds > 0) … … 106 102 } 107 103 108 /**109 * Load all X509 Certs from a directory and add them to the110 * trusted set of certificates in the key store111 *112 * @return number successfully added113 */114 private static int addCerts(File dir, KeyStore ks) {115 info("Looking for X509 Certificates in " + dir.getAbsolutePath());116 int added = 0;117 if (dir.exists() && dir.isDirectory()) {118 File[] files = dir.listFiles();119 if (files != null) {120 for (int i = 0; i < files.length; i++) {121 File f = files[i];122 if (!f.isFile())123 continue;124 // use file name as alias125 String alias = f.getName().toLowerCase(Locale.US);126 boolean success = addCert(f, alias, ks);127 if (success)128 added++;129 }130 }131 }132 return added;133 }134 135 /**136 * Load an X509 Cert from a file and add it to the137 * trusted set of certificates in the key store138 *139 * @return success140 */141 private static boolean addCert(File file, String alias, KeyStore ks) {142 InputStream fis = null;143 try {144 fis = new FileInputStream(file);145 CertificateFactory cf = CertificateFactory.getInstance("X.509");146 X509Certificate cert = (X509Certificate)cf.generateCertificate(fis);147 info("Read X509 Certificate from " + file.getAbsolutePath() +148 " Issuer: " + cert.getIssuerX500Principal() +149 "; Valid From: " + cert.getNotBefore() +150 " To: " + cert.getNotAfter());151 try {152 cert.checkValidity();153 } catch (CertificateExpiredException cee) {154 error("Rejecting expired X509 Certificate: " + file.getAbsolutePath(), cee);155 return false;156 } catch (CertificateNotYetValidException cnyve) {157 error("Rejecting X509 Certificate not yet valid: " + file.getAbsolutePath(), cnyve);158 return false;159 }160 ks.setCertificateEntry(alias, cert);161 info("Now trusting X509 Certificate, Issuer: " + cert.getIssuerX500Principal());162 } catch (GeneralSecurityException gse) {163 error("Error reading X509 Certificate: " + file.getAbsolutePath(), gse);164 return false;165 } catch (IOException ioe) {166 error("Error reading X509 Certificate: " + file.getAbsolutePath(), ioe);167 return false;168 } finally {169 try { if (fis != null) fis.close(); } catch (IOException foo) {}170 }171 return true;172 }173 174 /** @since 0.9.8 */175 private static void info(String msg) {176 log(I2PAppContext.getGlobalContext(), Log.INFO, msg, null);177 }178 179 /** @since 0.9.8 */180 private static void error(String msg, Throwable t) {181 log(I2PAppContext.getGlobalContext(), Log.ERROR, msg, t);182 }183 184 104 /** @since 0.9.8 */ 185 105 private static void info(I2PAppContext ctx, String msg) { -
core/java/src/net/i2p/crypto/CryptoConstants.java
ra1c8e3e r6bb1505d 31 31 32 32 import java.math.BigInteger; 33 import java.security.spec.DSAParameterSpec; 33 34 34 35 import net.i2p.util.NativeBigInteger; … … 64 65 + "15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16); 65 66 public static final BigInteger elgg = new NativeBigInteger("2"); 67 68 /** 69 * @since 0.9.9 70 */ 71 public static final DSAParameterSpec DSA_SHA1_SPEC = new DSAParameterSpec(dsap, dsaq, dsag); 66 72 } -
core/java/src/net/i2p/crypto/DSAEngine.java
ra1c8e3e r6bb1505d 35 35 import java.math.BigInteger; 36 36 import java.security.GeneralSecurityException; 37 import java.security.Key; 37 38 import java.security.KeyFactory; 38 39 import java.security.MessageDigest; 39 40 import java.security.PrivateKey; 40 41 import java.security.PublicKey; 41 import java.security. spec.DSAPrivateKeySpec;42 import java.security. spec.DSAPublicKeySpec;43 import java.security. spec.KeySpec;42 import java.security.interfaces.DSAKey; 43 import java.security.interfaces.ECKey; 44 import java.security.interfaces.RSAKey; 44 45 45 46 import net.i2p.I2PAppContext; … … 63 64 * Params and rv's changed from Hash to SHA1Hash for version 0.8.1 64 65 * Hash variants of sign() and verifySignature() restored in 0.8.3, required by Syndie. 66 * 67 * As of 0.9.9, certain methods support ECDSA keys and signatures, i.e. all types 68 * specified in SigType. The type is specified by the getType() method in 69 * Signature, SigningPublicKey, and SigningPrivateKey. See Javadocs for individual 70 * methods for the supported types. Methods encountering an unsupported type 71 * will throw an IllegalArgumentException. 65 72 */ 66 73 public class DSAEngine { … … 81 88 82 89 /** 83 * Verify using DSA-SHA1 .84 * Uses TheCrypto code unless configured to use the java.security libraries.90 * Verify using DSA-SHA1 or ECDSA. 91 * Uses TheCrypto code for DSA-SHA1 unless configured to use the java.security libraries. 85 92 */ 86 93 public boolean verifySignature(Signature signature, byte signedData[], SigningPublicKey verifyingKey) { 87 94 boolean rv; 95 SigType type = signature.getType(); 96 if (type != verifyingKey.getType()) 97 throw new IllegalArgumentException("type mismatch sig=" + signature.getType() + " key=" + verifyingKey.getType()); 98 if (type != SigType.DSA_SHA1) { 99 try { 100 rv = altVerifySig(signature, signedData, verifyingKey); 101 if ((!rv) && _log.shouldLog(Log.WARN)) 102 _log.warn(type + " Sig Verify Fail"); 103 return rv; 104 } catch (GeneralSecurityException gse) { 105 if (_log.shouldLog(Log.WARN)) 106 _log.warn(type + " Sig Verify Fail", gse); 107 return false; 108 } 109 } 88 110 if (_useJavaLibs) { 89 111 try { … … 105 127 106 128 /** 107 * Verify using DSA-SHA1 129 * Verify using DSA-SHA1 ONLY 108 130 */ 109 131 public boolean verifySignature(Signature signature, byte signedData[], int offset, int size, SigningPublicKey verifyingKey) { … … 112 134 113 135 /** 114 * Verify using DSA-SHA1 136 * Verify using DSA-SHA1 ONLY 115 137 */ 116 138 public boolean verifySignature(Signature signature, InputStream in, SigningPublicKey verifyingKey) { … … 118 140 } 119 141 120 /** @param hash SHA-1 hash, NOT a SHA-256 hash */ 142 /** 143 * Verify using DSA-SHA1 ONLY 144 * @param hash SHA-1 hash, NOT a SHA-256 hash 145 */ 121 146 public boolean verifySignature(Signature signature, SHA1Hash hash, SigningPublicKey verifyingKey) { 122 147 return verifySig(signature, hash, verifyingKey); … … 124 149 125 150 /** 151 * Nonstandard. 126 152 * Used by Syndie. 127 153 * @since 0.8.3 (restored, was removed in 0.8.1 and 0.8.2) … … 132 158 133 159 /** 160 * Generic signature type. 161 * 162 * @param hash SHA1Hash, Hash, Hash384, or Hash512 163 * @since 0.9.9 164 */ 165 public boolean verifySignature(Signature signature, SimpleDataStructure hash, SigningPublicKey verifyingKey) { 166 SigType type = signature.getType(); 167 if (type != verifyingKey.getType()) 168 throw new IllegalArgumentException("type mismatch sig=" + type + " key=" + verifyingKey.getType()); 169 int hashlen = type.getHashLen(); 170 if (hash.length() != hashlen) 171 throw new IllegalArgumentException("type mismatch hash=" + hash.getClass() + " sig=" + type); 172 if (type == SigType.DSA_SHA1) 173 return verifySig(signature, hash, verifyingKey); 174 try { 175 return altVerifySigRaw(signature, hash, verifyingKey); 176 } catch (GeneralSecurityException gse) { 177 if (_log.shouldLog(Log.WARN)) 178 _log.warn(type + " Sig Verify Fail", gse); 179 return false; 180 } 181 } 182 183 /** 184 * Generic signature type. 185 * If you have a Java pubkey, use this, so you don't lose the key parameters, 186 * which may be different than the ones defined in SigType. 187 * 188 * @param hash SHA1Hash, Hash, Hash384, or Hash512 189 * @param pubKey Java key 190 * @since 0.9.9 191 */ 192 public boolean verifySignature(Signature signature, SimpleDataStructure hash, PublicKey pubKey) { 193 try { 194 return altVerifySigRaw(signature, hash, pubKey); 195 } catch (GeneralSecurityException gse) { 196 if (_log.shouldLog(Log.WARN)) 197 _log.warn(signature.getType() + " Sig Verify Fail", gse); 198 return false; 199 } 200 } 201 202 /** 203 * Verify using DSA-SHA1 or Syndie DSA-SHA256 ONLY. 134 204 * @param hash either a Hash or a SHA1Hash 135 205 * @since 0.8.3 136 206 */ 137 207 private boolean verifySig(Signature signature, SimpleDataStructure hash, SigningPublicKey verifyingKey) { 208 if (signature.getType() != SigType.DSA_SHA1) 209 throw new IllegalArgumentException("Bad sig type " + signature.getType()); 210 if (verifyingKey.getType() != SigType.DSA_SHA1) 211 throw new IllegalArgumentException("Bad key type " + verifyingKey.getType()); 138 212 long start = _context.clock().now(); 139 213 … … 185 259 186 260 /** 187 * Sign using DSA-SHA1 .261 * Sign using DSA-SHA1 or ECDSA. 188 262 * Uses TheCrypto code unless configured to use the java.security libraries. 263 * 264 * @return null on error 189 265 */ 190 266 public Signature sign(byte data[], SigningPrivateKey signingKey) { 267 SigType type = signingKey.getType(); 268 if (type != SigType.DSA_SHA1) { 269 try { 270 return altSign(data, signingKey); 271 } catch (GeneralSecurityException gse) { 272 if (_log.shouldLog(Log.WARN)) 273 _log.warn(type + " Sign Fail", gse); 274 return null; 275 } 276 } 191 277 if (_useJavaLibs) { 192 278 try { … … 202 288 203 289 /** 204 * Sign using DSA-SHA1 290 * Sign using DSA-SHA1 ONLY 291 * 292 * @return null on error 205 293 */ 206 294 public Signature sign(byte data[], int offset, int length, SigningPrivateKey signingKey) { … … 211 299 212 300 /** 213 * Sign using DSA-SHA1 .301 * Sign using DSA-SHA1 ONLY. 214 302 * Reads the stream until EOF. Does not close the stream. 303 * 304 * @return null on error 215 305 */ 216 306 public Signature sign(InputStream in, SigningPrivateKey signingKey) { … … 220 310 } 221 311 222 /** @param hash SHA-1 hash, NOT a SHA-256 hash */ 312 /** 313 * Sign using DSA-SHA1 ONLY. 314 * 315 * @param hash SHA-1 hash, NOT a SHA-256 hash 316 * @return null on error 317 */ 223 318 public Signature sign(SHA1Hash hash, SigningPrivateKey signingKey) { 224 319 return signIt(hash, signingKey); … … 226 321 227 322 /** 323 * Nonstandard. 228 324 * Used by Syndie. 325 * 326 * @return null on error 229 327 * @since 0.8.3 (restored, was removed in 0.8.1 and 0.8.2) 230 328 */ … … 234 332 235 333 /** 334 * Generic signature type. 335 * 336 * @param hash SHA1Hash, Hash, Hash384, or Hash512 337 * @return null on error 338 * @since 0.9.9 339 */ 340 public Signature sign(SimpleDataStructure hash, SigningPrivateKey signingKey) { 341 SigType type = signingKey.getType(); 342 int hashlen = type.getHashLen(); 343 if (hash.length() != hashlen) 344 throw new IllegalArgumentException("type mismatch hash=" + hash.getClass() + " key=" + type); 345 if (type == SigType.DSA_SHA1) 346 return signIt(hash, signingKey); 347 try { 348 return altSignRaw(hash, signingKey); 349 } catch (GeneralSecurityException gse) { 350 if (_log.shouldLog(Log.WARN)) 351 _log.warn(type + " Sign Fail", gse); 352 return null; 353 } 354 } 355 356 /** 357 * Generic signature type. 358 * If you have a Java privkey, use this, so you don't lose the key parameters, 359 * which may be different than the ones defined in SigType. 360 * 361 * @param hash SHA1Hash, Hash, Hash384, or Hash512 362 * @param privKey Java key 363 * @param type returns a Signature of this type 364 * @return null on error 365 * @since 0.9.9 366 */ 367 public Signature sign(SimpleDataStructure hash, PrivateKey privKey, SigType type) { 368 String algo = getRawAlgo(privKey); 369 String talgo = getRawAlgo(type); 370 if (!algo.equals(talgo)) 371 throw new IllegalArgumentException("type mismatch type=" + type + " key=" + privKey.getClass().getSimpleName()); 372 try { 373 return altSignRaw(algo, hash, privKey, type); 374 } catch (GeneralSecurityException gse) { 375 if (_log.shouldLog(Log.WARN)) 376 _log.warn(type + " Sign Fail", gse); 377 return null; 378 } 379 } 380 381 /** 382 * Sign using DSA-SHA1 or Syndie DSA-SHA256 ONLY. 383 * 236 384 * @param hash either a Hash or a SHA1Hash 385 * @return null on error 237 386 * @since 0.8.3 238 387 */ 239 388 private Signature signIt(SimpleDataStructure hash, SigningPrivateKey signingKey) { 240 389 if ((signingKey == null) || (hash == null)) return null; 390 if (signingKey.getType() != SigType.DSA_SHA1) 391 throw new IllegalArgumentException("Bad key type " + signingKey.getType()); 241 392 long start = _context.clock().now(); 242 393 … … 276 427 out[i] = rbytes[i + 1]; 277 428 } 429 } else if (rbytes.length > 21) { 430 _log.error("Bad R length " + rbytes.length); 431 return null; 278 432 } else { 279 if (_log.shouldLog(Log.DEBUG)) _log.debug("Using short rbytes.length [" + rbytes.length + "]");433 //if (_log.shouldLog(Log.DEBUG)) _log.debug("Using short rbytes.length [" + rbytes.length + "]"); 280 434 //System.arraycopy(rbytes, 0, out, 20 - rbytes.length, rbytes.length); 281 435 for (int i = 0; i < rbytes.length; i++) … … 292 446 out[i + 20] = sbytes[i + 1]; 293 447 } 448 } else if (sbytes.length > 21) { 449 _log.error("Bad S length " + sbytes.length); 450 return null; 294 451 } else { 295 if (_log.shouldLog(Log.DEBUG)) _log.debug("Using short sbytes.length [" + sbytes.length + "]");452 //if (_log.shouldLog(Log.DEBUG)) _log.debug("Using short sbytes.length [" + sbytes.length + "]"); 296 453 //System.arraycopy(sbytes, 0, out, 40 - sbytes.length, sbytes.length); 297 454 for (int i = 0; i < sbytes.length; i++) … … 339 496 340 497 /** 498 * Generic verify DSA_SHA1, ECDSA, or RSA 499 * @throws GeneralSecurityException if algorithm unvailable or on other errors 500 * @since 0.9.9 501 */ 502 private boolean altVerifySig(Signature signature, byte[] data, SigningPublicKey verifyingKey) 503 throws GeneralSecurityException { 504 SigType type = signature.getType(); 505 if (type != verifyingKey.getType()) 506 throw new IllegalArgumentException("type mismatch sig=" + type + " key=" + verifyingKey.getType()); 507 if (type == SigType.DSA_SHA1) 508 return altVerifySigSHA1(signature, data, verifyingKey); 509 510 java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName()); 511 PublicKey pubKey = SigUtil.toJavaKey(verifyingKey); 512 jsig.initVerify(pubKey); 513 jsig.update(data); 514 boolean rv = jsig.verify(SigUtil.toJavaSig(signature)); 515 return rv; 516 } 517 518 /** 519 * Generic raw verify any type 520 * @throws GeneralSecurityException if algorithm unvailable or on other errors 521 * @since 0.9.9 522 */ 523 private boolean altVerifySigRaw(Signature signature, SimpleDataStructure hash, SigningPublicKey verifyingKey) 524 throws GeneralSecurityException { 525 SigType type = signature.getType(); 526 if (type != verifyingKey.getType()) 527 throw new IllegalArgumentException("type mismatch sig=" + type + " key=" + verifyingKey.getType()); 528 529 PublicKey pubKey = SigUtil.toJavaKey(verifyingKey); 530 return verifySignature(signature, hash, pubKey); 531 } 532 533 /** 534 * Generic raw verify any type. 535 * If you have a Java pubkey, use this, so you don't lose the key parameters, 536 * which may be different than the ones defined in SigType. 537 * 538 * @throws GeneralSecurityException if algorithm unvailable or on other errors 539 * @param verifyingKey Java key 540 * @since 0.9.9 541 */ 542 private boolean altVerifySigRaw(Signature signature, SimpleDataStructure hash, PublicKey pubKey) 543 throws GeneralSecurityException { 544 SigType type = signature.getType(); 545 int hashlen = hash.length(); 546 if (type.getHashLen() != hashlen) 547 throw new IllegalArgumentException("type mismatch hash=" + hash.getClass() + " key=" + type); 548 549 String algo = getRawAlgo(type); 550 java.security.Signature jsig = java.security.Signature.getInstance(algo); 551 jsig.initVerify(pubKey); 552 jsig.update(hash.getData()); 553 boolean rv = jsig.verify(SigUtil.toJavaSig(signature)); 554 return rv; 555 } 556 557 /** 341 558 * Alternate to verifySignature() using java.security libraries. 342 559 * @throws GeneralSecurityException if algorithm unvailable or on other errors … … 345 562 private boolean altVerifySigSHA1(Signature signature, byte[] data, SigningPublicKey verifyingKey) throws GeneralSecurityException { 346 563 java.security.Signature jsig = java.security.Signature.getInstance("SHA1withDSA"); 347 KeyFactory keyFact = KeyFactory.getInstance("DSA"); 348 // y p q g 349 KeySpec spec = new DSAPublicKeySpec(new NativeBigInteger(1, verifyingKey.getData()), 350 CryptoConstants.dsap, 351 CryptoConstants.dsaq, 352 CryptoConstants.dsag); 353 PublicKey pubKey = keyFact.generatePublic(spec); 564 PublicKey pubKey = SigUtil.toJavaDSAKey(verifyingKey); 354 565 jsig.initVerify(pubKey); 355 566 jsig.update(data); 356 boolean rv = jsig.verify( sigBytesToASN1(signature.getData()));567 boolean rv = jsig.verify(SigUtil.toJavaSig(signature)); 357 568 //if (!rv) { 358 569 // System.out.println("BAD SIG\n" + net.i2p.util.HexDump.dump(signature.getData())); … … 363 574 364 575 /** 576 * Generic sign DSA_SHA1, ECDSA, or RSA 577 * @throws GeneralSecurityException if algorithm unvailable or on other errors 578 * @since 0.9.9 579 */ 580 private Signature altSign(byte[] data, SigningPrivateKey privateKey) throws GeneralSecurityException { 581 SigType type = privateKey.getType(); 582 if (type == SigType.DSA_SHA1) 583 return altSignSHA1(data, privateKey); 584 585 java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName()); 586 PrivateKey privKey = SigUtil.toJavaKey(privateKey); 587 jsig.initSign(privKey, _context.random()); 588 jsig.update(data); 589 return SigUtil.fromJavaSig(jsig.sign(), type); 590 } 591 592 /** 593 * Generic raw verify any type 594 * @param hash SHA1Hash, Hash, Hash384, or Hash512 595 * @throws GeneralSecurityException if algorithm unvailable or on other errors 596 * @since 0.9.9 597 */ 598 private Signature altSignRaw(SimpleDataStructure hash, SigningPrivateKey privateKey) throws GeneralSecurityException { 599 SigType type = privateKey.getType(); 600 String algo = getRawAlgo(type); 601 java.security.Signature jsig = java.security.Signature.getInstance(algo); 602 PrivateKey privKey = SigUtil.toJavaKey(privateKey); 603 return altSignRaw(algo, hash, privKey, type); 604 } 605 606 /** 607 * Generic raw verify any type 608 * @param hash SHA1Hash, Hash, Hash384, or Hash512 609 * @param type returns a Signature of this type 610 * @throws GeneralSecurityException if algorithm unvailable or on other errors 611 * @since 0.9.9 612 */ 613 private Signature altSignRaw(String algo, SimpleDataStructure hash, PrivateKey privKey, SigType type) 614 throws GeneralSecurityException { 615 int hashlen = hash.length(); 616 if (type.getHashLen() != hashlen) 617 throw new IllegalArgumentException("type mismatch hash=" + hash.getClass() + " key=" + type); 618 619 java.security.Signature jsig = java.security.Signature.getInstance(algo); 620 jsig.initSign(privKey, _context.random()); 621 jsig.update(hash.getData()); 622 return SigUtil.fromJavaSig(jsig.sign(), type); 623 } 624 625 /** 365 626 * Alternate to sign() using java.security libraries. 366 627 * @throws GeneralSecurityException if algorithm unvailable or on other errors … … 369 630 private Signature altSignSHA1(byte[] data, SigningPrivateKey privateKey) throws GeneralSecurityException { 370 631 java.security.Signature jsig = java.security.Signature.getInstance("SHA1withDSA"); 371 KeyFactory keyFact = KeyFactory.getInstance("DSA"); 372 // y p q g 373 KeySpec spec = new DSAPrivateKeySpec(new NativeBigInteger(1, privateKey.getData()), 374 CryptoConstants.dsap, 375 CryptoConstants.dsaq, 376 CryptoConstants.dsag); 377 PrivateKey privKey = keyFact.generatePrivate(spec); 632 PrivateKey privKey = SigUtil.toJavaDSAKey(privateKey); 378 633 jsig.initSign(privKey, _context.random()); 379 634 jsig.update(data); 380 return new Signature(aSN1ToSigBytes(jsig.sign())); 381 } 382 383 /** 384 * http://download.oracle.com/javase/1.5.0/docs/guide/security/CryptoSpec.html 385 * Signature Format ASN.1 sequence of two INTEGER values: r and s, in that order: 386 * SEQUENCE ::= { r INTEGER, s INTEGER } 387 * 388 * http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One 389 * 30 -- tag indicating SEQUENCE 390 * xx - length in octets 391 * 392 * 02 -- tag indicating INTEGER 393 * xx - length in octets 394 * xxxxxx - value 395 * 396 * Convert to BigInteger and back so we have the minimum length representation, as required. 397 * r and s are always non-negative. 398 * 399 * @since 0.8.7 400 */ 401 private static byte[] sigBytesToASN1(byte[] sig) { 402 //System.out.println("pre TO asn1\n" + net.i2p.util.HexDump.dump(sig)); 403 ByteArrayOutputStream baos = new ByteArrayOutputStream(48); 404 baos.write(0x30); 405 baos.write(0); // length to be filled in below 406 407 byte[] tmp = new byte[20]; 408 baos.write(2); 409 System.arraycopy(sig, 0, tmp, 0, 20); 410 BigInteger r = new BigInteger(1, tmp); 411 byte[] b = r.toByteArray(); 412 baos.write(b.length); 413 baos.write(b, 0, b.length); 414 415 baos.write(2); 416 System.arraycopy(sig, 20, tmp, 0, 20); 417 BigInteger s = new BigInteger(1, tmp); 418 b = s.toByteArray(); 419 baos.write(b.length); 420 baos.write(b, 0, b.length); 421 byte[] rv = baos.toByteArray(); 422 rv[1] = (byte) (rv.length - 2); 423 //System.out.println("post TO asn1\n" + net.i2p.util.HexDump.dump(rv)); 424 return rv; 425 } 426 427 /** 428 * See above. 429 * @since 0.8.7 430 */ 431 private static byte[] aSN1ToSigBytes(byte[] asn) { 432 //System.out.println("pre from asn1\n" + net.i2p.util.HexDump.dump(asn)); 433 byte[] rv = new byte[40]; 434 int rlen = asn[3]; 435 if ((asn[4] & 0x80) != 0) 436 throw new IllegalArgumentException("R is negative"); 437 if (rlen > 21) 438 throw new IllegalArgumentException("R too big " + rlen); 439 else if (rlen == 21) { 440 System.arraycopy(asn, 5, rv, 0, 20); 441 } else 442 System.arraycopy(asn, 4, rv, 20 - rlen, rlen); 443 int slenloc = 25 + rlen - 20; 444 int slen = asn[slenloc]; 445 if ((asn[slenloc + 1] & 0x80) != 0) 446 throw new IllegalArgumentException("S is negative"); 447 if (slen > 21) 448 throw new IllegalArgumentException("S too big " + slen); 449 else if (slen == 21) { 450 System.arraycopy(asn, slenloc + 2, rv, 20, 20); 451 } else 452 System.arraycopy(asn, slenloc + 1, rv, 40 - slen, slen); 453 //System.out.println("post from asn1\n" + net.i2p.util.HexDump.dump(rv)); 454 return rv; 635 return SigUtil.fromJavaSig(jsig.sign(), SigType.DSA_SHA1); 636 } 637 638 /** @since 0.9.9 */ 639 private static String getRawAlgo(SigType type) { 640 switch (type.getBaseAlgorithm()) { 641 case DSA: 642 return "NONEwithDSA"; 643 case EC: 644 return "NONEwithECDSA"; 645 case RSA: 646 return "NONEwithRSA"; 647 default: 648 throw new IllegalArgumentException(); 649 } 650 } 651 652 /** @since 0.9.9 */ 653 private static String getRawAlgo(Key key) { 654 if (key instanceof DSAKey) 655 return "NONEwithDSA"; 656 if (key instanceof ECKey) 657 return "NONEwithECDSA"; 658 if (key instanceof RSAKey) 659 return "NONEwithRSA"; 660 throw new IllegalArgumentException(); 455 661 } 456 662 -
core/java/src/net/i2p/crypto/ElGamalEngine.java
ra1c8e3e r6bb1505d 82 82 public void shutdown() { 83 83 _ykgen.shutdown(); 84 SigUtil.clearCaches(); 84 85 } 85 86 -
core/java/src/net/i2p/crypto/KeyGenerator.java
ra1c8e3e r6bb1505d 11 11 12 12 import java.math.BigInteger; 13 import java.security.GeneralSecurityException; 14 import java.security.InvalidKeyException; 15 import java.security.KeyPair; 16 import java.security.KeyPairGenerator; 17 import java.security.ProviderException; 18 import java.security.interfaces.ECPrivateKey; 19 import java.security.interfaces.ECPublicKey; 20 import java.security.spec.ECPoint; 13 21 14 22 import net.i2p.I2PAppContext; … … 20 28 import net.i2p.data.SigningPublicKey; 21 29 import net.i2p.data.SimpleDataStructure; 30 import net.i2p.util.Log; 22 31 import net.i2p.util.NativeBigInteger; 23 32 import net.i2p.util.SystemVersion; 33 34 35 // main() 36 import net.i2p.data.DataHelper; 37 import net.i2p.data.Signature; 38 import net.i2p.util.Clock; 39 import net.i2p.util.RandomSource; 24 40 25 41 /** Define a way of generating asymmetrical key pairs as well as symmetrical keys … … 130 146 keys[0] = new PublicKey(); 131 147 keys[1] = new PrivateKey(); 132 byte[] k0 = aalpha.toByteArray();133 byte[] k1 = a.toByteArray();134 148 135 149 // bigInteger.toByteArray returns SIGNED integers, but since they'return positive, 136 150 // signed two's complement is the same as unsigned 137 151 138 keys[0].setData(padBuffer(k0, PublicKey.KEYSIZE_BYTES)); 139 keys[1].setData(padBuffer(k1, PrivateKey.KEYSIZE_BYTES)); 152 try { 153 keys[0].setData(SigUtil.rectify(aalpha, PublicKey.KEYSIZE_BYTES)); 154 keys[1].setData(SigUtil.rectify(a, PrivateKey.KEYSIZE_BYTES)); 155 } catch (InvalidKeyException ike) { 156 throw new IllegalArgumentException(ike); 157 } 140 158 141 159 return keys; … … 150 168 BigInteger aalpha = CryptoConstants.elgg.modPow(a, CryptoConstants.elgp); 151 169 PublicKey pub = new PublicKey(); 152 byte [] pubBytes = aalpha.toByteArray(); 153 pub.setData(padBuffer(pubBytes, PublicKey.KEYSIZE_BYTES)); 170 try { 171 pub.setData(SigUtil.rectify(aalpha, PublicKey.KEYSIZE_BYTES)); 172 } catch (InvalidKeyException ike) { 173 throw new IllegalArgumentException(ike); 174 } 154 175 return pub; 155 176 } 156 177 157 178 /** Generate a pair of DSA keys, where index 0 is a SigningPublicKey, and 158 * index 1 is a SigningPrivateKey 179 * index 1 is a SigningPrivateKey. 180 * DSA-SHA1 only. 181 * 159 182 * @return pair of keys 160 183 */ … … 164 187 165 188 /** 189 * DSA-SHA1 only. 190 * 166 191 * Same as above but different return type 167 192 * @since 0.8.7 … … 179 204 keys[0] = new SigningPublicKey(); 180 205 keys[1] = new SigningPrivateKey(); 181 byte k0[] = padBuffer(y.toByteArray(), SigningPublicKey.KEYSIZE_BYTES); 182 byte k1[] = padBuffer(x.toByteArray(), SigningPrivateKey.KEYSIZE_BYTES); 183 184 keys[0].setData(k0); 185 keys[1].setData(k1); 206 try { 207 keys[0].setData(SigUtil.rectify(y, SigningPublicKey.KEYSIZE_BYTES)); 208 keys[1].setData(SigUtil.rectify(x, SigningPrivateKey.KEYSIZE_BYTES)); 209 } catch (InvalidKeyException ike) { 210 throw new IllegalStateException(ike); 211 } 186 212 return keys; 187 213 } 188 214 189 /** Convert a SigningPrivateKey to a SigningPublicKey 215 /** 216 * Generic signature type, supports DSA and ECDSA 217 * @since 0.9.9 218 */ 219 public SimpleDataStructure[] generateSigningKeys(SigType type) throws GeneralSecurityException { 220 if (type == SigType.DSA_SHA1) 221 return generateSigningKeys(); 222 KeyPairGenerator kpg = KeyPairGenerator.getInstance(type.getBaseAlgorithm().getName()); 223 KeyPair kp; 224 try { 225 kpg.initialize(type.getParams(), _context.random()); 226 kp = kpg.generateKeyPair(); 227 } catch (ProviderException pe) { 228 // java.security.ProviderException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_DOMAIN_PARAMS_INVALID 229 // This is a RuntimeException, thx Sun 230 // Fails for P-192 only, on Ubuntu 231 Log log = _context.logManager().getLog(KeyGenerator.class); 232 String pname = kpg.getProvider().getName(); 233 if ("BC".equals(pname)) { 234 if (log.shouldLog(Log.WARN)) 235 log.warn("BC KPG failed for " + type, pe); 236 throw new GeneralSecurityException("BC KPG for " + type, pe); 237 } 238 if (!ECConstants.isBCAvailable()) 239 throw new GeneralSecurityException(pname + " KPG failed for " + type, pe); 240 if (log.shouldLog(Log.WARN)) 241 log.warn(pname + " KPG failed for " + type + ", trying BC" /* , pe */ ); 242 try { 243 kpg = KeyPairGenerator.getInstance(type.getBaseAlgorithm().getName(), "BC"); 244 kpg.initialize(type.getParams(), _context.random()); 245 kp = kpg.generateKeyPair(); 246 } catch (ProviderException pe2) { 247 if (log.shouldLog(Log.WARN)) 248 log.warn("BC KPG failed for " + type + " also", pe2); 249 // throw original exception 250 throw new GeneralSecurityException(pname + " KPG for " + type, pe); 251 } catch (GeneralSecurityException gse) { 252 if (log.shouldLog(Log.WARN)) 253 log.warn("BC KPG failed for " + type + " also", gse); 254 // throw original exception 255 throw new GeneralSecurityException(pname + " KPG for " + type, pe); 256 } 257 } 258 java.security.PublicKey pubkey = kp.getPublic(); 259 java.security.PrivateKey privkey = kp.getPrivate(); 260 SimpleDataStructure[] keys = new SimpleDataStructure[2]; 261 keys[0] = SigUtil.fromJavaKey(pubkey, type); 262 keys[1] = SigUtil.fromJavaKey(privkey, type); 263 return keys; 264 } 265 266 /** Convert a SigningPrivateKey to a SigningPublicKey. 267 * DSA-SHA1 only. 268 * 190 269 * @param priv a SigningPrivateKey object 191 270 * @return a SigningPublicKey object … … 195 274 BigInteger y = CryptoConstants.dsag.modPow(x, CryptoConstants.dsap); 196 275 SigningPublicKey pub = new SigningPublicKey(); 197 byte [] pubBytes = padBuffer(y.toByteArray(), SigningPublicKey.KEYSIZE_BYTES); 198 pub.setData(pubBytes); 276 try { 277 pub.setData(SigUtil.rectify(y, SigningPublicKey.KEYSIZE_BYTES)); 278 } catch (InvalidKeyException ike) { 279 throw new IllegalArgumentException(ike); 280 } 199 281 return pub; 200 282 } 201 283 202 /** 203 * Pad the buffer w/ leading 0s or trim off leading bits so the result is the 204 * given length. 205 */ 206 private final static byte[] padBuffer(byte src[], int length) { 207 byte buf[] = new byte[length]; 208 209 if (src.length > buf.length) // extra bits, chop leading bits 210 System.arraycopy(src, src.length - buf.length, buf, 0, buf.length); 211 else if (src.length < buf.length) // short bits, padd w/ 0s 212 System.arraycopy(src, 0, buf, buf.length - src.length, src.length); 213 else 214 // eq 215 System.arraycopy(src, 0, buf, 0, buf.length); 216 217 return buf; 284 public static void main(String args[]) { 285 try { 286 main2(args); 287 } catch (Exception e) { 288 e.printStackTrace(); 289 } 290 } 291 292 public static void main2(String args[]) { 293 RandomSource.getInstance().nextBoolean(); 294 try { Thread.sleep(1000); } catch (InterruptedException ie) {} 295 int runs = 200; // warmup 296 for (int j = 0; j < 2; j++) { 297 for (int i = 0; i <= 100; i++) { 298 SigType type = SigType.getByCode(i); 299 if (type == null) 300 break; 301 try { 302 System.out.println("Testing " + type); 303 testSig(type, runs); 304 } catch (Exception e) { 305 System.out.println("error testing " + type); 306 e.printStackTrace(); 307 } 308 } 309 runs = 1000; 310 } 311 } 312 313 private static void testSig(SigType type, int runs) throws GeneralSecurityException { 314 byte src[] = new byte[512]; 315 long stime = 0; 316 long vtime = 0; 317 SimpleDataStructure keys[] = KeyGenerator.getInstance().generateSigningKeys(type); 318 //System.out.println("pubkey " + keys[0]); 319 //System.out.println("privkey " + keys[1]); 320 for (int i = 0; i < runs; i++) { 321 RandomSource.getInstance().nextBytes(src); 322 long start = System.nanoTime(); 323 Signature sig = DSAEngine.getInstance().sign(src, (SigningPrivateKey) keys[1]); 324 long mid = System.nanoTime(); 325 boolean ok = DSAEngine.getInstance().verifySignature(sig, src, (SigningPublicKey) keys[0]); 326 long end = System.nanoTime(); 327 stime += mid - start; 328 vtime += end - mid; 329 if (!ok) 330 throw new GeneralSecurityException(type + " V(S(data)) fail"); 331 } 332 stime /= 1000*1000; 333 vtime /= 1000*1000; 334 System.out.println(type + " sign/verify " + runs + " times: " + (vtime+stime) + " ms = " + 335 (((double) stime) / runs) + " each sign, " + 336 (((double) vtime) / runs) + " each verify, " + 337 (((double) (stime + vtime)) / runs) + " s+v"); 218 338 } 219 339 -
core/java/src/net/i2p/crypto/SHA1Hash.java
ra1c8e3e r6bb1505d 26 26 27 27 public final static int HASH_LENGTH = SHA1.HASH_LENGTH; 28 29 /** @since 0.9.9 */ 30 public SHA1Hash() { 31 super(); 32 } 28 33 29 34 /** @throws IllegalArgumentException if data is not 20 bytes (null is ok) */ -
core/java/src/net/i2p/crypto/SU3File.java
ra1c8e3e r6bb1505d 12 12 import java.security.DigestInputStream; 13 13 import java.security.DigestOutputStream; 14 import java.security.GeneralSecurityException; 14 15 import java.security.MessageDigest; 16 import java.security.PrivateKey; 17 import java.security.PublicKey; 18 import java.util.ArrayList; 19 import java.util.Arrays; 20 import java.util.EnumSet; 15 21 import java.util.HashMap; 22 import java.util.Iterator; 23 import java.util.List; 24 import java.util.Locale; 16 25 import java.util.Map; 26 import java.util.NoSuchElementException; 27 import java.util.Properties; 17 28 18 29 import net.i2p.I2PAppContext; … … 22 33 import net.i2p.data.SigningPrivateKey; 23 34 import net.i2p.data.SigningPublicKey; 35 import net.i2p.data.SimpleDataStructure; 36 import net.i2p.util.HexDump; 37 import net.i2p.util.SecureFileOutputStream; 24 38 25 39 /** … … 32 46 33 47 private final I2PAppContext _context; 34 private final Map<SigningPublicKey, String> _trustedKeys;35 48 36 49 private final File _file; … … 39 52 private String _signer; 40 53 private int _signerLength; 41 private int_contentType;54 private ContentType _contentType; 42 55 private long _contentLength; 43 private SigningPublicKey _signerPubkey;56 private PublicKey _signerPubkey; 44 57 private boolean _headerVerified; 58 private SigType _sigType; 45 59 46 60 private static final byte[] MAGIC = DataHelper.getUTF8("I2Psu3"); 47 61 private static final int FILE_VERSION = 0; 48 62 private static final int MIN_VERSION_BYTES = 16; 49 private static final int VERSION_OFFSET = Signature.SIGNATURE_BYTES;63 private static final int VERSION_OFFSET = 40; // Signature.SIGNATURE_BYTES; avoid early ctx init 50 64 51 65 private static final int TYPE_ZIP = 0; 52 66 53 private static final int CONTENT_ROUTER = 0; 54 private static final int CONTENT_ROUTER_P200 = 1; 55 private static final int CONTENT_PLUGIN = 2; 56 private static final int CONTENT_RESEED = 3; 57 58 private static final int SIG_DSA_160 = SigType.DSA_SHA1.getCode(); 59 60 /** 61 * Uses TrustedUpdate's default keys for verification. 67 public static final int CONTENT_UNKNOWN = 0; 68 public static final int CONTENT_ROUTER = 1; 69 public static final int CONTENT_PLUGIN = 2; 70 public static final int CONTENT_RESEED = 3; 71 72 private enum ContentType { 73 UNKNOWN(CONTENT_UNKNOWN, "unknown"), 74 ROUTER(CONTENT_ROUTER, "router"), 75 PLUGIN(CONTENT_PLUGIN, "plugin"), 76 RESEED(CONTENT_RESEED, "reseed") 77 ; 78 79 private final int code; 80 private final String name; 81 82 ContentType(int code, String name) { 83 this.code = code; 84 this.name = name; 85 } 86 public int getCode() { return code; } 87 public String getName() { return name; } 88 89 /** @return null if not supported */ 90 public static ContentType getByCode(int code) { 91 return BY_CODE.get(Integer.valueOf(code)); 92 } 93 } 94 95 private static final Map<Integer, ContentType> BY_CODE = new HashMap<Integer, ContentType>(); 96 97 static { 98 for (ContentType type : ContentType.values()) { 99 BY_CODE.put(Integer.valueOf(type.getCode()), type); 100 } 101 } 102 103 private static final ContentType DEFAULT_CONTENT_TYPE = ContentType.UNKNOWN; 104 // avoid early ctx init 105 //private static final SigType DEFAULT_SIG_TYPE = SigType.DSA_SHA1; 106 private static final int DEFAULT_SIG_CODE = 0; 107 108 /** 109 * 62 110 */ 63 111 public SU3File(String file) { … … 66 114 67 115 /** 68 * Uses TrustedUpdate's default keys for verification.116 * 69 117 */ 70 118 public SU3File(File file) { 71 this(file, (new TrustedUpdate()).getKeys()); 72 } 73 74 /** 75 * @param trustedKeys map of pubkey to signer name, null ok if not verifying 76 */ 77 public SU3File(File file, Map<SigningPublicKey, String> trustedKeys) { 78 this(I2PAppContext.getGlobalContext(), file, trustedKeys); 79 } 80 81 /** 82 * @param trustedKeys map of pubkey to signer name, null ok if not verifying 83 */ 84 public SU3File(I2PAppContext context, File file, Map<SigningPublicKey, String> trustedKeys) { 119 this(I2PAppContext.getGlobalContext(), file); 120 } 121 122 /** 123 * 124 */ 125 public SU3File(I2PAppContext context, File file) { 85 126 _context = context; 86 127 _file = file; 87 _trustedKeys = trustedKeys;88 128 } 89 129 … … 96 136 verifyHeader(); 97 137 return _signer; 138 } 139 140 /** 141 * @return null if unknown 142 * @since 0.9.9 143 */ 144 public SigType getSigType() throws IOException { 145 verifyHeader(); 146 return _sigType; 147 } 148 149 /** 150 * @return -1 if unknown 151 * @since 0.9.9 152 */ 153 public int getContentType() throws IOException { 154 verifyHeader(); 155 return _contentType != null ? _contentType.getCode() : -1; 98 156 } 99 157 … … 129 187 if (foo != FILE_VERSION) 130 188 throw new IOException("bad file version"); 131 skip(in, 1); 132 int sigType = in.read(); 133 // TODO, for other known algos we must start over with a new MessageDigest 134 // (rewind 10 bytes) 135 if (sigType != SIG_DSA_160) 136 throw new IOException("bad sig type"); 189 int sigTypeCode = (int) DataHelper.readLong(in, 2); 190 _sigType = SigType.getByCode(sigTypeCode); 191 // In verifyAndMigrate it reads this far then rewinds, but we don't need to here 192 if (_sigType == null) 193 throw new IOException("unknown sig type: " + sigTypeCode); 137 194 _signerLength = (int) DataHelper.readLong(in, 2); 138 if (_signerLength != Signature.SIGNATURE_BYTES)195 if (_signerLength != _sigType.getSigLen()) 139 196 throw new IOException("bad sig length"); 140 197 skip(in, 1); … … 154 211 throw new IOException("bad type"); 155 212 skip(in, 1); 156 _contentType = in.read(); 157 if (_contentType < CONTENT_ROUTER || _contentType > CONTENT_RESEED) 158 throw new IOException("bad content type"); 213 int cType = in.read(); 214 _contentType = BY_CODE.get(Integer.valueOf(cType)); 215 if (_contentType == null) 216 throw new IOException("unknown content type " + cType); 159 217 skip(in, 12); 160 218 … … 175 233 throw new EOFException(); 176 234 _signer = DataHelper.getUTF8(data); 177 if (_trustedKeys != null) { 178 for (Map.Entry<SigningPublicKey, String> e : _trustedKeys.entrySet()) { 179 if (e.getValue().equals(_signer)) { 180 _signerPubkey = e.getKey(); 181 break; 182 } 183 } 184 if (_signerPubkey == null) 185 throw new IOException("unknown signer: " + _signer); 186 } 235 236 KeyRing ring = new DirKeyRing(new File(_context.getBaseDir(), "certificates")); 237 try { 238 _signerPubkey = ring.getKey(_signer, _contentType.getName(), _sigType); 239 } catch (GeneralSecurityException gse) { 240 IOException ioe = new IOException("keystore error"); 241 ioe.initCause(gse); 242 throw ioe; 243 } 244 245 if (_signerPubkey == null) 246 throw new IOException("unknown signer: " + _signer); 187 247 _headerVerified = true; 188 248 } … … 202 262 203 263 /** 264 * One-pass verify. 265 * Throws IOE on all format errors. 266 * 267 * @return true if signature is good 268 * @since 0.9.9 269 */ 270 public boolean verify() throws IOException { 271 return verifyAndMigrate(null); 272 } 273 274 /** 204 275 * One-pass verify and extract the content. 205 276 * Recommend extracting to a temp location as the sig is not checked until … … 207 278 * Throws IOE on all format errors. 208 279 * 209 * @param migrateTo the output file, probably in zip format 280 * @param migrateTo the output file, probably in zip format. Null for verify only. 210 281 * @return true if signature is good 211 282 */ 212 283 public boolean verifyAndMigrate(File migrateTo) throws IOException { 213 DigestInputStream in = null;284 InputStream in = null; 214 285 OutputStream out = null; 215 286 boolean rv = false; 216 287 try { 217 MessageDigest md = SHA1.getInstance(); 218 in = new DigestInputStream(new BufferedInputStream(new FileInputStream(_file)), md); 288 in = new BufferedInputStream(new FileInputStream(_file)); 289 // read 10 bytes to get the sig type 290 in.mark(10); 291 // following is a dup of that in verifyHeader() 292 byte[] magic = new byte[MAGIC.length]; 293 DataHelper.read(in, magic); 294 if (!DataHelper.eq(magic, MAGIC)) 295 throw new IOException("Not an su3 file"); 296 skip(in, 1); 297 int foo = in.read(); 298 if (foo != FILE_VERSION) 299 throw new IOException("bad file version"); 300 skip(in, 1); 301 int sigTypeCode = in.read(); 302 _sigType = SigType.getByCode(sigTypeCode); 303 if (_sigType == null) 304 throw new IOException("unknown sig type: " + sigTypeCode); 305 // end duplicate code 306 // rewind 307 in.reset(); 308 MessageDigest md = _sigType.getDigestInstance(); 309 DigestInputStream din = new DigestInputStream(in, md); 310 in = din; 219 311 if (!_headerVerified) 220 312 verifyHeader(in); … … 223 315 if (_signerPubkey == null) 224 316 throw new IOException("unknown signer: " + _signer); 225 out = new FileOutputStream(migrateTo); 317 if (migrateTo != null) // else verify only 318 out = new FileOutputStream(migrateTo); 226 319 byte[] buf = new byte[16*1024]; 227 320 long tot = 0; … … 230 323 if (read < 0) 231 324 throw new EOFException(); 232 out.write(buf, 0, read); 325 if (migrateTo != null) // else verify only 326 out.write(buf, 0, read); 233 327 tot += read; 234 328 } 235 329 byte[] sha = md.digest(); 236 in.on(false);237 Signature signature = new Signature( );330 din.on(false); 331 Signature signature = new Signature(_sigType); 238 332 signature.readBytes(in); 239 SHA1Hash hash = new SHA1Hash(sha); 333 SimpleDataStructure hash = _sigType.getHashInstance(); 334 hash.setData(sha); 335 //System.out.println("hash\n" + HexDump.dump(sha)); 336 //System.out.println("sig\n" + HexDump.dump(signature.getData())); 240 337 rv = _context.dsa().verifySignature(signature, hash, _signerPubkey); 241 338 } catch (DataFormatException dfe) { … … 246 343 if (in != null) try { in.close(); } catch (IOException ioe) {} 247 344 if (out != null) try { out.close(); } catch (IOException ioe) {} 248 if ( !rv)345 if (migrateTo != null && !rv) 249 346 migrateTo.delete(); 250 347 } … … 263 360 */ 264 361 public void write(File content, int contentType, String version, 265 String signer, SigningPrivateKey privkey) throws IOException {362 String signer, PrivateKey privkey, SigType sigType) throws IOException { 266 363 InputStream in = null; 267 364 DigestOutputStream out = null; … … 269 366 try { 270 367 in = new BufferedInputStream(new FileInputStream(content)); 271 MessageDigest md = SHA1.getInstance();368 MessageDigest md = sigType.getDigestInstance(); 272 369 out = new DigestOutputStream(new BufferedOutputStream(new FileOutputStream(_file)), md); 273 370 out.write(MAGIC); 274 371 out.write((byte) 0); 275 372 out.write((byte) FILE_VERSION); 276 out.write((byte) 0); 277 out.write((byte) SIG_DSA_160); 278 DataHelper.writeLong(out, 2, Signature.SIGNATURE_BYTES); 373 DataHelper.writeLong(out, 2, sigType.getCode()); 374 DataHelper.writeLong(out, 2, sigType.getSigLen()); 279 375 out.write((byte) 0); 280 376 byte[] verBytes = DataHelper.getUTF8(version); … … 316 412 byte[] sha = md.digest(); 317 413 out.on(false); 318 SHA1Hash hash = new SHA1Hash(sha); 319 Signature signature = _context.dsa().sign(hash, privkey); 414 SimpleDataStructure hash = sigType.getHashInstance(); 415 hash.setData(sha); 416 Signature signature = _context.dsa().sign(hash, privkey, sigType); 417 if (signature == null) 418 throw new IOException("sig fail"); 419 //System.out.println("hash\n" + HexDump.dump(sha)); 420 //System.out.println("sig\n" + HexDump.dump(signature.getData())); 320 421 signature.writeBytes(out); 321 422 ok = true; … … 341 442 public static void main(String[] args) { 342 443 boolean ok = false; 343 try { 344 if ("showversion".equals(args[0])) { 345 ok = showVersionCLI(args[1]); 346 } else if ("sign".equals(args[0])) { 347 ok = signCLI(args[1], args[2], args[3], args[4], args[5]); 348 } else if ("verifysig".equals(args[0])) { 349 ok = verifySigCLI(args[1]); 444 List<String> a = new ArrayList(Arrays.asList(args)); 445 try { 446 // defaults 447 String stype = null; 448 String ctype = null; 449 Iterator<String> iter = a.iterator(); 450 String cmd = iter.next(); 451 iter.remove(); 452 for ( ; iter.hasNext(); ) { 453 String arg = iter.next(); 454 if (arg.equals("-t")) { 455 iter.remove(); 456 stype = iter.next(); 457 iter.remove(); 458 } else if (arg.equals("-c")) { 459 iter.remove(); 460 ctype = iter.next(); 461 iter.remove(); 462 } 463 } 464 if ("showversion".equals(cmd)) { 465 ok = showVersionCLI(a.get(0)); 466 } else if ("sign".equals(cmd)) { 467 // speed things up by specifying a small PRNG buffer size 468 Properties props = new Properties(); 469 props.setProperty("prng.bufferSize", "16384"); 470 new I2PAppContext(props); 471 ok = signCLI(stype, ctype, a.get(0), a.get(1), a.get(2), a.get(3), a.get(4)); 472 } else if ("verifysig".equals(cmd)) { 473 ok = verifySigCLI(a.get(0)); 474 } else if ("keygen".equals(cmd)) { 475 ok = genKeysCLI(stype, a.get(0), a.get(1), a.get(2)); 476 } else if ("extract".equals(cmd)) { 477 ok = extractCLI(a.get(0), a.get(1)); 350 478 } else { 351 479 showUsageCLI(); 352 480 } 353 } catch (ArrayIndexOutOfBoundsException aioobe) { 481 } catch (NoSuchElementException nsee) { 482 showUsageCLI(); 483 } catch (IndexOutOfBoundsException ioobe) { 354 484 showUsageCLI(); 355 485 } … … 359 489 360 490 private static final void showUsageCLI() { 361 System.err.println("Usage: SU3File showversion signedFile.su3"); 362 System.err.println(" SU3File sign inputFile.zip signedFile.su3 privateKeyFile version signerName@mail.i2p"); 363 System.err.println(" SU3File verifysig signedFile.su3"); 491 System.err.println("Usage: SU3File keygen [-t type|code] publicKeyFile keystore.ks you@mail.i2p"); 492 System.err.println(" SU3File sign [-c type|code] [-t type|code] inputFile.zip signedFile.su3 keystore.ks version you@mail.i2p"); 493 System.err.println(" SU3File showversion signedFile.su3"); 494 System.err.println(" SU3File verifysig signedFile.su3"); 495 System.err.println(" SU3File extract signedFile.su3 outFile.zip"); 496 System.err.println(dumpTypes()); 497 } 498 499 /** @since 0.9.9 */ 500 private static String dumpTypes() { 501 StringBuilder buf = new StringBuilder(256); 502 buf.append("Available signature types:\n"); 503 for (SigType t : EnumSet.allOf(SigType.class)) { 504 buf.append(" ").append(t).append("\t(code: ").append(t.getCode()).append(')'); 505 if (t.getCode() == DEFAULT_SIG_CODE) 506 buf.append(" DEFAULT"); 507 buf.append('\n'); 508 } 509 buf.append("Available content types:\n"); 510 for (ContentType t : EnumSet.allOf(ContentType.class)) { 511 buf.append(" ").append(t).append("\t(code: ").append(t.getCode()).append(')'); 512 if (t == DEFAULT_CONTENT_TYPE) 513 buf.append(" DEFAULT"); 514 buf.append('\n'); 515 } 516 return buf.toString(); 517 } 518 519 /** 520 * @param stype number or name 521 * @return null if not found 522 * @since 0.9.9 523 */ 524 private static SigType parseSigType(String stype) { 525 try { 526 return SigType.valueOf(stype.toUpperCase(Locale.US)); 527 } catch (IllegalArgumentException iae) { 528 try { 529 int code = Integer.parseInt(stype); 530 return SigType.getByCode(code); 531 } catch (NumberFormatException nfe) { 532 return null; 533 } 534 } 535 } 536 /** 537 * @param stype number or name 538 * @return null if not found 539 * @since 0.9.9 540 */ 541 private static ContentType parseContentType(String ctype) { 542 try { 543 return ContentType.valueOf(ctype.toUpperCase(Locale.US)); 544 } catch (IllegalArgumentException iae) { 545 try { 546 int code = Integer.parseInt(ctype); 547 return ContentType.getByCode(code); 548 } catch (NumberFormatException nfe) { 549 return null; 550 } 551 } 364 552 } 365 553 … … 367 555 private static final boolean showVersionCLI(String signedFile) { 368 556 try { 369 SU3File file = new SU3File( new File(signedFile), null);557 SU3File file = new SU3File(signedFile); 370 558 String versionString = file.getVersionString(); 371 559 if (versionString.equals("")) 372 560 System.out.println("No version string found in file '" + signedFile + "'"); 373 561 else 374 System.out.println("Version: " + versionString); 562 System.out.println("Version: " + versionString); 563 String signerString = file.getSignerString(); 564 if (signerString.equals("")) 565 System.out.println("No signer string found in file '" + signedFile + "'"); 566 else 567 System.out.println("Signer: " + signerString); 568 if (file._sigType != null) 569 System.out.println("SigType: " + file._sigType); 375 570 return !versionString.equals(""); 376 571 } catch (IOException ioe) { … … 380 575 } 381 576 382 /** @return success */ 383 private static final boolean signCLI(String inputFile, String signedFile, String privateKeyFile, 384 String version, String signerName) { 385 InputStream in = null; 386 try { 387 in = new FileInputStream(privateKeyFile); 388 SigningPrivateKey spk = new SigningPrivateKey(); 389 spk.readBytes(in); 390 in.close(); 577 /** 578 * @return success 579 * @since 0.9.9 580 */ 581 private static final boolean signCLI(String stype, String ctype, String inputFile, String signedFile, 582 String privateKeyFile, String version, String signerName) { 583 SigType type = stype == null ? SigType.getByCode(Integer.valueOf(DEFAULT_SIG_CODE)) : parseSigType(stype); 584 if (type == null) { 585 System.out.println("Signature type " + stype + " is not supported"); 586 return false; 587 } 588 ContentType ct = ctype == null ? DEFAULT_CONTENT_TYPE : parseContentType(ctype); 589 if (ct == null) { 590 System.out.println("Content type " + ctype + " is not supported"); 591 return false; 592 } 593 return signCLI(type, ct, inputFile, signedFile, privateKeyFile, version, signerName); 594 } 595 596 /** 597 * @return success 598 * @since 0.9.9 599 */ 600 private static final boolean signCLI(SigType type, ContentType ctype, String inputFile, String signedFile, 601 String privateKeyFile, String version, String signerName) { 602 try { 603 String keypw = ""; 604 while (keypw.length() < 6) { 605 System.out.print("Enter password for key \"" + signerName + "\": "); 606 keypw = DataHelper.readLine(System.in).trim(); 607 if (keypw.length() > 0 && keypw.length() < 6) 608 System.out.println("Key password must be at least 6 characters"); 609 } 610 File pkfile = new File(privateKeyFile); 611 PrivateKey pk = KeyStoreUtil.getPrivateKey(pkfile,KeyStoreUtil.DEFAULT_KEYSTORE_PASSWORD, signerName, keypw); 612 if (pk == null) { 613 System.out.println("Private key for " + signerName + " not found in keystore " + privateKeyFile); 614 return false; 615 } 391 616 SU3File file = new SU3File(signedFile); 392 file.write(new File(inputFile), CONTENT_ROUTER, version, signerName, spk);617 file.write(new File(inputFile), ctype.getCode(), version, signerName, pk, type); 393 618 System.out.println("Input file '" + inputFile + "' signed and written to '" + signedFile + "'"); 394 619 return true; 395 } catch ( DataFormatException dfe) {620 } catch (GeneralSecurityException gse) { 396 621 System.out.println("Error signing input file '" + inputFile + "'"); 397 dfe.printStackTrace();622 gse.printStackTrace(); 398 623 return false; 399 624 } catch (IOException ioe) { … … 401 626 ioe.printStackTrace(); 402 627 return false; 403 } finally {404 if (in != null) try { in.close(); } catch (IOException ioe) {}405 628 } 406 629 } … … 411 634 try { 412 635 SU3File file = new SU3File(signedFile); 413 boolean isValidSignature = file.verify AndMigrate(new File("/dev/null"));636 boolean isValidSignature = file.verify(); 414 637 if (isValidSignature) 415 System.out.println("Signature VALID (signed by " + file.getSignerString() + ' )');638 System.out.println("Signature VALID (signed by " + file.getSignerString() + ' ' + file._sigType + ')'); 416 639 else 417 System.out.println("Signature INVALID (signed by " + file.getSignerString() + ' )');640 System.out.println("Signature INVALID (signed by " + file.getSignerString() + ' ' + file._sigType +')'); 418 641 return isValidSignature; 419 642 } catch (IOException ioe) { … … 423 646 } 424 647 } 648 649 /** 650 * @return success 651 * @since 0.9.9 652 */ 653 private static final boolean extractCLI(String signedFile, String outFile) { 654 InputStream in = null; 655 try { 656 SU3File file = new SU3File(signedFile); 657 File out = new File(outFile); 658 boolean ok = file.verifyAndMigrate(out); 659 if (ok) 660 System.out.println("File extracted (signed by " + file.getSignerString() + ' ' + file._sigType + ')'); 661 else 662 System.out.println("Signature INVALID (signed by " + file.getSignerString() + ' ' + file._sigType +')'); 663 return ok; 664 } catch (IOException ioe) { 665 System.out.println("Error extracting from file '" + signedFile + "'"); 666 ioe.printStackTrace(); 667 return false; 668 } 669 } 670 671 /** 672 * @return success 673 * @since 0.9.9 674 */ 675 private static final boolean genKeysCLI(String stype, String publicKeyFile, String privateKeyFile, String alias) { 676 SigType type = stype == null ? SigType.getByCode(Integer.valueOf(DEFAULT_SIG_CODE)) : parseSigType(stype); 677 if (type == null) { 678 System.out.println("Signature type " + stype + " is not supported"); 679 return false; 680 } 681 return genKeysCLI(type, publicKeyFile, privateKeyFile, alias); 682 } 683 684 /** 685 * Writes Java-encoded keys (X.509 for public and PKCS#8 for private) 686 * @return success 687 * @since 0.9.9 688 */ 689 private static final boolean genKeysCLI(SigType type, String publicKeyFile, String privateKeyFile, String alias) { 690 File pubFile = new File(publicKeyFile); 691 if (pubFile.exists()) { 692 System.out.println("Error: Not overwriting file " + publicKeyFile); 693 return false; 694 } 695 File ksFile = new File(privateKeyFile); 696 String keypw = ""; 697 try { 698 while (alias.length() == 0) { 699 System.out.print("Enter key name (example@mail.i2p): "); 700 alias = DataHelper.readLine(System.in).trim(); 701 } 702 while (keypw.length() < 6) { 703 System.out.print("Enter new key password: "); 704 keypw = DataHelper.readLine(System.in).trim(); 705 if (keypw.length() > 0 && keypw.length() < 6) 706 System.out.println("Key password must be at least 6 characters"); 707 } 708 } catch (IOException ioe) { 709 return false; 710 } 711 int keylen = type.getPubkeyLen() * 8; 712 if (type.getBaseAlgorithm() == SigAlgo.EC) { 713 keylen /= 2; 714 if (keylen == 528) 715 keylen = 521; 716 } 717 boolean success = KeyStoreUtil.createKeys(ksFile, KeyStoreUtil.DEFAULT_KEYSTORE_PASSWORD, alias, 718 alias, "I2P", 3652, type.getBaseAlgorithm().getName(), 719 keylen, keypw); 720 if (!success) { 721 System.err.println("Error creating keys for " + alias); 722 return false; 723 } 724 File outfile = new File(publicKeyFile); 725 success = KeyStoreUtil.exportCert(ksFile, KeyStoreUtil.DEFAULT_KEYSTORE_PASSWORD, alias, outfile); 726 if (!success) { 727 System.err.println("Error writing public key for " + alias + " to " + outfile); 728 return false; 729 } 730 return true; 731 } 425 732 } -
core/java/src/net/i2p/crypto/SigType.java
ra1c8e3e r6bb1505d 7 7 import java.util.HashMap; 8 8 import java.util.Map; 9 10 import net.i2p.data.Hash; 11 import net.i2p.data.SimpleDataStructure; 9 12 10 13 /** … … 24 27 * @since 0.9.8 25 28 */ 26 DSA_SHA1(0, 128, 20, 20, 40, "SHA-1", "SHA1withDSA", null), 29 DSA_SHA1(0, 128, 20, 20, 40, SigAlgo.DSA, "SHA-1", "SHA1withDSA", CryptoConstants.DSA_SHA1_SPEC), 30 /** Pubkey 64 bytes; privkey 32 bytes; hash 32 bytes; sig 64 bytes */ 31 ECDSA_SHA256_P256(1, 64, 32, 32, 64, SigAlgo.EC, "SHA-256", "SHA256withECDSA", ECConstants.P256_SPEC), 32 /** Pubkey 96 bytes; privkey 48 bytes; hash 48 bytes; sig 96 bytes */ 33 ECDSA_SHA384_P384(2, 96, 48, 48, 96, SigAlgo.EC, "SHA-384", "SHA384withECDSA", ECConstants.P384_SPEC), 34 /** Pubkey 132 bytes; privkey 66 bytes; hash 64 bytes; sig 132 bytes */ 35 ECDSA_SHA512_P521(3, 132, 66, 64, 132, SigAlgo.EC, "SHA-512", "SHA512withECDSA", ECConstants.P521_SPEC), 36 37 /** Pubkey 256 bytes; privkey 512 bytes; hash 32 bytes; sig 256 bytes */ 38 RSA_SHA256_2048(4, 256, 512, 32, 256, SigAlgo.RSA, "SHA-256", "SHA256withRSA", RSAConstants.F4_2048_SPEC), 39 /** Pubkey 384 bytes; privkey 768 bytes; hash 48 bytes; sig 384 bytes */ 40 RSA_SHA384_3072(5, 384, 768, 48, 384, SigAlgo.RSA, "SHA-384", "SHA384withRSA", RSAConstants.F4_3072_SPEC), 41 /** Pubkey 512 bytes; privkey 1024 bytes; hash 64 bytes; sig 512 bytes */ 42 RSA_SHA512_4096(6, 512, 1024, 64, 512, SigAlgo.RSA, "SHA-512", "SHA512withRSA", RSAConstants.F4_4096_SPEC), 43 44 45 46 // TESTING.................... 47 48 49 50 // others.......... 51 52 // EC mix and match 53 //ECDSA_SHA256_P192(5, 48, 24, 32, 48, SigAlgo.EC, "SHA-256", "SHA256withECDSA", ECConstants.P192_SPEC), 54 //ECDSA_SHA256_P384(6, 96, 48, 32, 96, SigAlgo.EC, "SHA-256", "SHA256withECDSA", ECConstants.P384_SPEC), 55 //ECDSA_SHA256_P521(7, 132, 66, 32, 132, SigAlgo.EC, "SHA-256", "SHA256withECDSA", ECConstants.P521_SPEC), 56 //ECDSA_SHA384_P256(8, 64, 32, 48, 64, SigAlgo.EC, "SHA-384", "SHA384withECDSA", ECConstants.P256_SPEC), 57 //ECDSA_SHA384_P521(9, 132, 66, 48, 132, SigAlgo.EC, "SHA-384", "SHA384withECDSA", ECConstants.P521_SPEC), 58 //ECDSA_SHA512_P256(10, 64, 32, 64, 64, SigAlgo.EC, "SHA-512", "SHA512withECDSA", ECConstants.P256_SPEC), 59 //ECDSA_SHA512_P384(11, 96, 48, 64, 96, SigAlgo.EC, "SHA-512", "SHA512withECDSA", ECConstants.P384_SPEC), 60 61 // Koblitz 62 //ECDSA_SHA256_K163(12, 42, 21, 32, 42, SigAlgo.EC, "SHA-256", "SHA256withECDSA", ECConstants.K163_SPEC), 63 //ECDSA_SHA256_K233(13, 60, 30, 32, 60, SigAlgo.EC, "SHA-256", "SHA256withECDSA", ECConstants.K233_SPEC), 64 //ECDSA_SHA256_K283(14, 72, 36, 32, 72, SigAlgo.EC, "SHA-256", "SHA256withECDSA", ECConstants.K283_SPEC), 65 //ECDSA_SHA256_K409(15, 104, 52, 32, 104, SigAlgo.EC, "SHA-256", "SHA256withECDSA", ECConstants.K409_SPEC), 66 //ECDSA_SHA256_K571(16, 144, 72, 32, 144, SigAlgo.EC, "SHA-256", "SHA256withECDSA", ECConstants.K571_SPEC), 67 68 // too short.............. 27 69 /** Pubkey 48 bytes; privkey 24 bytes; hash 20 bytes; sig 48 bytes */ 28 ECDSA_SHA1_P192(1, 48, 24, 20, 48, "SHA-1", "SHA1withECDSA", null), 29 /** Pubkey 64 bytes; privkey 32 bytes; hash 32 bytes; sig 64 bytes */ 30 ECDSA_SHA256_P256(2, 64, 32, 32, 64, "SHA-256", "SHA256withECDSA", null), 31 /** Pubkey 96 bytes; privkey 48 bytes; hash 48 bytes; sig 96 bytes */ 32 ECDSA_SHA384_P384(3, 96, 48, 48, 96, "SHA-384", "SHA384withECDSA", null), 33 /** Pubkey 132 bytes; privkey 66 bytes; hash 64 bytes; sig 132 bytes */ 34 ECDSA_SHA512_P521(4, 132, 66, 64, 132, "SHA-512", "SHA512withECDSA", null), 70 //ECDSA_SHA1_P192(1, 48, 24, 20, 48, SigAlgo.EC, "SHA-1", "SHA1withECDSA", ECConstants.P192_SPEC), 71 //RSA_SHA1(17, 128, 256, 20, 128, SigAlgo.RSA, "SHA-1", "SHA1withRSA", RSAConstants.F4_1024_SPEC), 72 //MD5 73 //RSA_SHA1 35 74 36 //MD537 75 //ELGAMAL_SHA256 38 //RSA_SHA139 //RSA_SHA25640 //RSA_SHA38441 //RSA_SHA51242 76 //DSA_2048_224(2, 256, 28, 32, 56, "SHA-256"), 43 77 // Nonstandard, used by Syndie. … … 48 82 // Pubkey 384 bytes; privkey 32 bytes; hash 32 bytes; sig 64 bytes 49 83 //DSA_3072_256(3, 384, 32, 32, 64, "SHA-256", "?"), 84 50 85 ; 51 86 52 87 private final int code, pubkeyLen, privkeyLen, hashLen, sigLen; 88 private final SigAlgo base; 53 89 private final String digestName, algoName; 54 90 private final AlgorithmParameterSpec params; 55 91 56 SigType(int cod, int pubLen, int privLen, int hLen, int sLen, 92 SigType(int cod, int pubLen, int privLen, int hLen, int sLen, SigAlgo baseAlgo, 57 93 String mdName, String aName, AlgorithmParameterSpec pSpec) { 58 94 code = cod; … … 61 97 hashLen = hLen; 62 98 sigLen = sLen; 99 base = baseAlgo; 63 100 digestName = mdName; 64 101 algoName = aName; … … 76 113 /** the length of the signature, in bytes */ 77 114 public int getSigLen() { return sigLen; } 115 /** the standard base algorithm name used for the Java crypto factories */ 116 public SigAlgo getBaseAlgorithm() { return base; } 78 117 /** the standard name used for the Java crypto factories */ 79 118 public String getAlgorithmName() { return algoName; } … … 101 140 } 102 141 142 /** 143 * @since 0.9.9 144 * @throws UnsupportedOperationException if not supported 145 */ 146 public SimpleDataStructure getHashInstance() { 147 switch (getHashLen()) { 148 case 20: 149 return new SHA1Hash(); 150 case 32: 151 return new Hash(); 152 case 48: 153 return new Hash384(); 154 case 64: 155 return new Hash512(); 156 default: 157 throw new UnsupportedOperationException("Unsupported hash length: " + getHashLen()); 158 } 159 } 160 103 161 private static final Map<Integer, SigType> BY_CODE = new HashMap<Integer, SigType>(); 104 162 -
core/java/src/net/i2p/crypto/TrustedUpdate.java
ra1c8e3e r6bb1505d 22 22 import net.i2p.data.SigningPublicKey; 23 23 import net.i2p.util.Log; 24 import net.i2p.util.SecureFileOutputStream; 24 25 import net.i2p.util.VersionComparator; 25 26 import net.i2p.util.ZipFileComment; … … 316 317 /** @return success */ 317 318 private static final boolean genKeysCLI(String publicKeyFile, String privateKeyFile) { 319 File pubFile = new File(publicKeyFile); 320 File privFile = new File(privateKeyFile); 321 if (pubFile.exists()) { 322 System.out.println("Error: Not overwriting file " + publicKeyFile); 323 return false; 324 } 325 if (privFile.exists()) { 326 System.out.println("Error: Not overwriting file " + privateKeyFile); 327 return false; 328 } 318 329 FileOutputStream fileOutputStream = null; 319 320 330 I2PAppContext context = I2PAppContext.getGlobalContext(); 321 331 try { … … 324 334 SigningPrivateKey signingPrivateKey = (SigningPrivateKey) signingKeypair[1]; 325 335 326 fileOutputStream = new FileOutputStream(publicKeyFile);336 fileOutputStream = new SecureFileOutputStream(pubFile); 327 337 signingPublicKey.writeBytes(fileOutputStream); 328 338 fileOutputStream.close(); 329 339 fileOutputStream = null; 330 340 331 fileOutputStream = new FileOutputStream(privateKeyFile);341 fileOutputStream = new SecureFileOutputStream(privFile); 332 342 signingPrivateKey.writeBytes(fileOutputStream); 333 343 -
core/java/src/net/i2p/update/UpdateType.java
ra1c8e3e r6bb1505d 7 7 */ 8 8 public enum UpdateType { 9 TYPE_DUMMY, // Internal use only 9 /** Dummy: internal use only */ 10 TYPE_DUMMY, 10 11 NEWS, 11 12 ROUTER_SIGNED, 12 13 ROUTER_UNSIGNED, 13 14 PLUGIN, 15 /** unused */ 14 16 GEOIP, 17 /** unused */ 15 18 BLOCKLIST, 19 /** unused */ 16 20 RESEED, 21 /** unused */ 17 22 HOMEPAGE, 18 ADDRESSBOOK 23 /** unused */ 24 ADDRESSBOOK, 25 /** @since 0.9.9 */ 26 ROUTER_SIGNED_SU3 19 27 } -
core/java/src/net/i2p/util/EepGet.java
ra1c8e3e r6bb1505d 1056 1056 if ("http".equals(url.getProtocol())) { 1057 1057 String host = url.getHost(); 1058 if (host.toLowerCase(Locale.US).endsWith(".i2p")) 1059 throw new MalformedURLException("I2P addresses must be proxied"); 1058 1060 int port = url.getPort(); 1059 1061 if (port == -1) … … 1061 1063 _proxy = new Socket(host, port); 1062 1064 } else { 1063 throw new IOException("URL is not supported:" + _actualURL);1065 throw new MalformedURLException("URL is not supported:" + _actualURL); 1064 1066 } 1065 1067 // an MUE is an IOE … … 1090 1092 URL url = new URL(_actualURL); 1091 1093 String host = url.getHost(); 1094 if (host == null || host.length() <= 0) 1095 throw new MalformedURLException("Bad URL, no host"); 1092 1096 int port = url.getPort(); 1093 1097 String path = url.getPath(); -
core/java/src/net/i2p/util/NativeBigInteger.java
ra1c8e3e r6bb1505d 113 113 */ 114 114 private static boolean _doLog = System.getProperty("jbigi.dontLog") == null && 115 I2PAppContext.getGlobalContext().isRouterContext(); 115 I2PAppContext.getCurrentContext() != null && 116 I2PAppContext.getCurrentContext().isRouterContext(); 116 117 117 118 /** -
core/java/src/net/i2p/util/PartialEepGet.java
ra1c8e3e r6bb1505d 4 4 import java.io.IOException; 5 5 import java.io.OutputStream; 6 import java.net.MalformedURLException; 6 7 import java.net.URL; 7 8 … … 12 13 * Anything less or more will throw an IOException 13 14 * No retries, no min and max size options, no timeout option 15 * If the server does not return a Content-Length header of the correct size, 16 * the fetch will fail. 17 * 14 18 * Useful for checking .sud versions 15 19 * … … 20 24 long _fetchSize; 21 25 22 /** @param size fetch exactly this many bytes */ 26 /** 27 * Instantiate an EepGet that will fetch exactly size bytes when fetch() is called. 28 * 29 * @param proxyHost use null or "" for no proxy 30 * @param proxyPort use 0 for no proxy 31 * @param size fetch exactly this many bytes 32 */ 23 33 public PartialEepGet(I2PAppContext ctx, String proxyHost, int proxyPort, 24 34 OutputStream outputStream, String url, long size) { 25 35 // we're using this constructor: 26 // public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, long minSize, long maxSize, String outputFile, OutputStream outputStream, String url, boolean allowCaching, String etag, String postData) { 27 super(ctx, true, proxyHost, proxyPort, 0, size, size, null, outputStream, url, true, null, null); 36 // public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, 37 // long minSize, long maxSize, String outputFile, OutputStream outputStream, String url, boolean allowCaching, String etag, String postData) { 38 super(ctx, proxyHost != null && proxyPort > 0, proxyHost, proxyPort, 0, 39 size, size, null, outputStream, url, true, null, null); 28 40 _fetchSize = size; 29 41 } … … 89 101 90 102 private static void usage() { 91 System.err.println("PartialEepGet [-p 127.0.0.1:4444] [-l #bytes] url"); 103 System.err.println("PartialEepGet [-p 127.0.0.1:4444] [-l #bytes] url\n" + 104 " (use -p :0 for no proxy)"); 92 105 } 93 106 … … 97 110 URL url = new URL(_actualURL); 98 111 String host = url.getHost(); 112 if (host == null || host.length() <= 0) 113 throw new MalformedURLException("Bad URL, no host"); 99 114 int port = url.getPort(); 100 115 String path = url.getPath(); -
core/java/src/net/i2p/util/SSLEepGet.java
ra1c8e3e r6bb1505d 47 47 import java.io.PipedInputStream; 48 48 import java.io.PipedOutputStream; 49 import java. io.PrintWriter;49 import java.net.MalformedURLException; 50 50 import java.net.URL; 51 51 import java.security.KeyStore; 52 52 import java.security.GeneralSecurityException; 53 53 import java.security.cert.Certificate; 54 import java.security.cert.CertificateEncodingException; 54 55 import java.security.cert.CertificateException; 55 import java.security.cert.CertificateEncodingException;56 import java.security.cert.CertificateExpiredException;57 import java.security.cert.CertificateNotYetValidException;58 import java.security.cert.CertificateFactory;59 56 import java.security.cert.X509Certificate; 60 import java.util.Enumeration;61 57 import java.util.Locale; 62 58 import javax.net.ssl.SSLContext; … … 68 64 69 65 import net.i2p.I2PAppContext; 70 import net.i2p.data.Base64; 66 import net.i2p.crypto.CertUtil; 67 import net.i2p.crypto.KeyStoreUtil; 71 68 import net.i2p.data.DataHelper; 72 69 … … 77 74 * Self-signed certs or CAs not in the JVM key store must be loaded to be trusted. 78 75 * 79 * Since 0.8.2, loads additional trusted CA certs from $I2P/certificates/ and ~/.i2p/certificates/76 * Since 0.8.2, loads additional trusted CA certs from $I2P/certificates/ssl/ and ~/.i2p/certificates/ssl/ 80 77 * 81 78 * @author zzz … … 92 89 private SavingTrustManager _stm; 93 90 94 private static final boolean _isAndroid = SystemVersion.isAndroid();91 private static final String CERT_DIR = "certificates/ssl"; 95 92 96 93 /** … … 108 105 */ 109 106 public SSLEepGet(I2PAppContext ctx, OutputStream outputStream, String url, SSLState state) { 107 this(ctx, null, outputStream, url, null); 108 } 109 110 /** 111 * A new SSLEepGet with a new SSLState 112 * @since 0.9.9 113 */ 114 public SSLEepGet(I2PAppContext ctx, String outputFile, String url) { 115 this(ctx, outputFile, url, null); 116 } 117 118 /** 119 * @param state an SSLState retrieved from a previous SSLEepGet with getSSLState(), or null. 120 * This makes repeated fetches from the same host MUCH faster, 121 * and prevents repeated key store loads even for different hosts. 122 * @since 0.9.9 123 */ 124 public SSLEepGet(I2PAppContext ctx, String outputFile, String url, SSLState state) { 125 this(ctx, outputFile, null, url, null); 126 } 127 128 /** 129 * outputFile, outputStream: One null, one non-null 130 * 131 * @param state an SSLState retrieved from a previous SSLEepGet with getSSLState(), or null. 132 * This makes repeated fetches from the same host MUCH faster, 133 * and prevents repeated key store loads even for different hosts. 134 * @since 0.9.9 135 */ 136 private SSLEepGet(I2PAppContext ctx, String outputFile, OutputStream outputStream, String url, SSLState state) { 110 137 // we're using this constructor: 111 138 // public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, long minSize, long maxSize, String outputFile, OutputStream outputStream, String url, boolean allowCaching, String etag, String postData) { 112 super(ctx, false, null, -1, 0, -1, -1, null, outputStream, url, true, null, null);139 super(ctx, false, null, -1, 0, -1, -1, outputFile, outputStream, url, true, null, null); 113 140 if (state != null && state.context != null) 114 141 _sslContext = state.context; … … 178 205 * else from $JAVA_HOME/lib/security/cacerts. 179 206 * 180 * Then adds certs found in the $I2P/certificates/ directory181 * and in the ~/.i2p/certificates/ directory.207 * Then adds certs found in the $I2P/certificates/ssl/ directory 208 * and in the ~/.i2p/certificates/ssl/ directory. 182 209 * 183 210 * @return null on failure … … 185 212 */ 186 213 private SSLContext initSSLContext() { 187 KeyStore ks; 188 try { 189 ks = KeyStore.getInstance(KeyStore.getDefaultType()); 190 } catch (GeneralSecurityException gse) { 191 _log.error("Key Store init error", gse); 214 KeyStore ks = KeyStoreUtil.loadSystemKeyStore(); 215 if (ks == null) { 216 _log.error("Key Store init error"); 192 217 return null; 193 218 } 194 boolean success = false; 195 String override = System.getProperty("javax.net.ssl.keyStore"); 196 if (override != null) 197 success = loadCerts(new File(override), ks); 198 if (!success) { 199 if (_isAndroid) { 200 // thru API 13. As of API 14 (ICS), the file is gone, but 201 // ks.load(null, pw) will bring in the default certs? 202 success = loadCerts(new File(System.getProperty("java.home"), "etc/security/cacerts.bks"), ks); 203 } else { 204 success = loadCerts(new File(System.getProperty("java.home"), "lib/security/jssecacerts"), ks); 205 if (!success) 206 success = loadCerts(new File(System.getProperty("java.home"), "lib/security/cacerts"), ks); 207 } 208 } 209 210 if (!success) { 211 try { 212 // must be initted 213 ks.load(null, "changeit".toCharArray()); 214 } catch (Exception e) {} 215 _log.error("All key store loads failed, will only load local certificates"); 216 } else if (_log.shouldLog(Log.INFO)) { 217 int count = 0; 218 try { 219 for(Enumeration<String> e = ks.aliases(); e.hasMoreElements();) { 220 String alias = e.nextElement(); 221 if (ks.isCertificateEntry(alias)) 222 count++; 223 } 224 } catch (Exception foo) {} 219 if (_log.shouldLog(Log.INFO)) { 220 int count = KeyStoreUtil.countCerts(ks); 225 221 _log.info("Loaded " + count + " default trusted certificates"); 226 222 } 227 223 228 File dir = new File(_context.getBaseDir(), "certificates");229 int adds = addCerts(dir, ks);224 File dir = new File(_context.getBaseDir(), CERT_DIR); 225 int adds = KeyStoreUtil.addCerts(dir, ks); 230 226 int totalAdds = adds; 231 227 if (adds > 0 && _log.shouldLog(Log.INFO)) 232 228 _log.info("Loaded " + adds + " trusted certificates from " + dir.getAbsolutePath()); 233 229 if (!_context.getBaseDir().getAbsolutePath().equals(_context.getConfigDir().getAbsolutePath())) { 234 dir = new File(_context.getConfigDir(), "certificates");235 adds = addCerts(dir, ks);230 dir = new File(_context.getConfigDir(), CERT_DIR); 231 adds = KeyStoreUtil.addCerts(dir, ks); 236 232 totalAdds += adds; 237 233 if (adds > 0 && _log.shouldLog(Log.INFO)) … … 240 236 dir = new File(System.getProperty("user.dir")); 241 237 if (!_context.getBaseDir().getAbsolutePath().equals(dir.getAbsolutePath())) { 242 dir = new File(_context.getConfigDir(), "certificates");243 adds = addCerts(dir, ks);238 dir = new File(_context.getConfigDir(), CERT_DIR); 239 adds = KeyStoreUtil.addCerts(dir, ks); 244 240 totalAdds += adds; 245 241 if (adds > 0 && _log.shouldLog(Log.INFO)) … … 261 257 } 262 258 return null; 263 }264 265 /**266 * Load all X509 Certs from a key store File into a KeyStore267 * Note that each call reinitializes the KeyStore268 *269 * @return success270 * @since 0.8.2271 */272 private boolean loadCerts(File file, KeyStore ks) {273 if (!file.exists())274 return false;275 InputStream fis = null;276 try {277 fis = new FileInputStream(file);278 // "changeit" is the default password279 ks.load(fis, "changeit".toCharArray());280 } catch (GeneralSecurityException gse) {281 _log.error("KeyStore load error, no default keys: " + file.getAbsolutePath(), gse);282 try {283 // not clear if null is allowed for password284 ks.load(null, "changeit".toCharArray());285 } catch (Exception foo) {}286 return false;287 } catch (IOException ioe) {288 _log.error("KeyStore load error, no default keys: " + file.getAbsolutePath(), ioe);289 try {290 ks.load(null, "changeit".toCharArray());291 } catch (Exception foo) {}292 return false;293 } finally {294 try { if (fis != null) fis.close(); } catch (IOException foo) {}295 }296 return true;297 }298 299 /**300 * Load all X509 Certs from a directory and add them to the301 * trusted set of certificates in the key store302 *303 * @return number successfully added304 * @since 0.8.2305 */306 private int addCerts(File dir, KeyStore ks) {307 if (_log.shouldLog(Log.INFO))308 _log.info("Looking for X509 Certificates in " + dir.getAbsolutePath());309 int added = 0;310 if (dir.exists() && dir.isDirectory()) {311 File[] files = dir.listFiles();312 if (files != null) {313 for (int i = 0; i < files.length; i++) {314 File f = files[i];315 if (!f.isFile())316 continue;317 // use file name as alias318 // https://www.sslshopper.com/ssl-converter.html319 // No idea if all these formats can actually be read by CertificateFactory320 String alias = f.getName().toLowerCase(Locale.US);321 if (alias.endsWith(".crt") || alias.endsWith(".pem") || alias.endsWith(".key") ||322 alias.endsWith(".der") || alias.endsWith(".key") || alias.endsWith(".p7b") ||323 alias.endsWith(".p7c") || alias.endsWith(".pfx") || alias.endsWith(".p12"))324 alias = alias.substring(0, alias.length() - 4);325 boolean success = addCert(f, alias, ks);326 if (success)327 added++;328 }329 }330 }331 return added;332 }333 334 /**335 * Load an X509 Cert from a file and add it to the336 * trusted set of certificates in the key store337 *338 * @return success339 * @since 0.8.2340 */341 private boolean addCert(File file, String alias, KeyStore ks) {342 InputStream fis = null;343 try {344 fis = new FileInputStream(file);345 CertificateFactory cf = CertificateFactory.getInstance("X.509");346 X509Certificate cert = (X509Certificate)cf.generateCertificate(fis);347 if (_log.shouldLog(Log.INFO)) {348 _log.info("Read X509 Certificate from " + file.getAbsolutePath() +349 " Issuer: " + cert.getIssuerX500Principal() +350 "; Valid From: " + cert.getNotBefore() +351 " To: " + cert.getNotAfter());352 }353 try {354 cert.checkValidity();355 } catch (CertificateExpiredException cee) {356 _log.error("Rejecting expired X509 Certificate: " + file.getAbsolutePath(), cee);357 return false;358 } catch (CertificateNotYetValidException cnyve) {359 _log.error("Rejecting X509 Certificate not yet valid: " + file.getAbsolutePath(), cnyve);360 return false;361 }362 ks.setCertificateEntry(alias, cert);363 if (_log.shouldLog(Log.INFO))364 _log.info("Now trusting X509 Certificate, Issuer: " + cert.getIssuerX500Principal());365 } catch (GeneralSecurityException gse) {366 _log.error("Error reading X509 Certificate: " + file.getAbsolutePath(), gse);367 return false;368 } catch (IOException ioe) {369 _log.error("Error reading X509 Certificate: " + file.getAbsolutePath(), ioe);370 return false;371 } finally {372 try { if (fis != null) fis.close(); } catch (IOException foo) {}373 }374 return true;375 259 } 376 260 … … 426 310 System.out.println(" WARNING: Certificate is not currently valid, it cannot be used"); 427 311 } 428 saveCert(cert, new File(name));312 CertUtil.saveCert(cert, new File(name)); 429 313 } 430 314 System.out.println("NOTE: To trust them, copy the certificate file(s) to the certificates directory and rerun without the -s option"); 431 315 System.out.println("NOTE: EepGet failed, certificate error follows:"); 432 }433 434 private static final int LINE_LENGTH = 64;435 436 /**437 * Modified from:438 * http://www.exampledepot.com/egs/java.security.cert/ExportCert.html439 *440 * This method writes a certificate to a file in base64 format.441 * @since 0.8.2442 */443 private static void saveCert(Certificate cert, File file) {444 OutputStream os = null;445 try {446 // Get the encoded form which is suitable for exporting447 byte[] buf = cert.getEncoded();448 os = new FileOutputStream(file);449 PrintWriter wr = new PrintWriter(os);450 wr.println("-----BEGIN CERTIFICATE-----");451 String b64 = Base64.encode(buf, true); // true = use standard alphabet452 for (int i = 0; i < b64.length(); i += LINE_LENGTH) {453 wr.println(b64.substring(i, Math.min(i + LINE_LENGTH, b64.length())));454 }455 wr.println("-----END CERTIFICATE-----");456 wr.flush();457 } catch (CertificateEncodingException cee) {458 System.out.println("Error writing X509 Certificate " + file.getAbsolutePath() + ' ' + cee);459 } catch (IOException ioe) {460 System.out.println("Error writing X509 Certificate " + file.getAbsolutePath() + ' ' + ioe);461 } finally {462 try { if (os != null) os.close(); } catch (IOException foo) {}463 }464 316 } 465 317 … … 642 494 if ("https".equals(url.getProtocol())) { 643 495 host = url.getHost(); 496 if (host.toLowerCase(Locale.US).endsWith(".i2p")) 497 throw new MalformedURLException("I2P addresses unsupported"); 644 498 port = url.getPort(); 645 499 if (port == -1) … … 650 504 _proxy = SSLSocketFactory.getDefault().createSocket(host, port); 651 505 } else { 652 throw new IOException("Only https supported: " + _actualURL);506 throw new MalformedURLException("Only https supported: " + _actualURL); 653 507 } 654 508 // an MUE is an IOE -
installer/resources/deletelist.txt
ra1c8e3e r6bb1505d 69 69 docs/initialNews/initialNews_ru.xml 70 70 docs/initialNews/initialNews_sv.xml 71 # certificates moved to certificates/ssl 72 certificates/193.150.121.66.crt 73 certificates/cert.smartcom.org.crt 74 certificates/i2p.feared.eu.crt 75 certificates/i2p.mooo.com.crt 76 certificates/i2pprojekt.de.cert 77 certificates/ieb9oopo.mooo.com.crt 78 certificates/netdb.i2p2.de.crt 79 certificates/netdb.i2p2.no.crt 80 certificates/reseed.info.crt 81 certificates/reseed.pkol.de.crt 82 certificates/www.cacert.org.crt -
router/java/src/net/i2p/router/client/SSLClientListenerRunner.java
ra1c8e3e r6bb1505d 22 22 23 23 import net.i2p.client.I2PClient; 24 import net.i2p.crypto.CertUtil; 25 import net.i2p.crypto.KeyStoreUtil; 24 26 import net.i2p.data.Base32; 25 import net.i2p.data.Base64;26 27 import net.i2p.router.RouterContext; 27 28 import net.i2p.util.Log; 28 29 import net.i2p.util.SecureDirectory; 29 import net.i2p.util.SecureFileOutputStream;30 import net.i2p.util.ShellCommand;31 30 32 31 /** … … 88 87 private boolean createKeyStore(File ks) { 89 88 // make a random 48 character password (30 * 8 / 5) 90 byte[] rand = new byte[30]; 91 _context.random().nextBytes(rand); 92 String keyPassword = Base32.encode(rand); 89 String keyPassword = KeyStoreUtil.randomString(); 93 90 // and one for the cname 94 _context.random().nextBytes(rand); 95 String cname = Base32.encode(rand) + ".i2cp.i2p.net"; 96 97 String keytool = (new File(System.getProperty("java.home"), "bin/keytool")).getAbsolutePath(); 98 String[] args = new String[] { 99 keytool, 100 "-genkey", // -genkeypair preferred in newer keytools, but this works with more 101 "-storetype", KeyStore.getDefaultType(), 102 "-keystore", ks.getAbsolutePath(), 103 "-storepass", DEFAULT_KEYSTORE_PASSWORD, 104 "-alias", KEY_ALIAS, 105 "-dname", "CN=" + cname + ",OU=I2CP,O=I2P Anonymous Network,L=XX,ST=XX,C=XX", 106 "-validity", "3652", // 10 years 107 "-keyalg", "DSA", 108 "-keysize", "1024", 109 "-keypass", keyPassword}; 110 boolean success = (new ShellCommand()).executeSilentAndWaitTimed(args, 30); // 30 secs 91 String cname = KeyStoreUtil.randomString() + ".i2cp.i2p.net"; 92 93 boolean success = KeyStoreUtil.createKeys(ks, KEY_ALIAS, cname, "I2CP", keyPassword); 111 94 if (success) { 112 95 success = ks.exists(); 113 96 if (success) { 114 SecureFileOutputStream.setPerms(ks);115 97 Map<String, String> changes = new HashMap(); 116 98 changes.put(PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD); … … 124 106 "IP address, host name, router identity, or destination keys."); 125 107 } else { 126 _log.error("Failed to create I2CP SSL keystore using command line:"); 127 StringBuilder buf = new StringBuilder(256); 128 for (int i = 0; i < args.length; i++) { 129 buf.append('"').append(args[i]).append("\" "); 130 } 131 _log.error(buf.toString()); 132 _log.error("This is for the Sun/Oracle keytool, others may be incompatible.\n" + 108 _log.error("Failed to create I2CP SSL keystore.\n" + 109 "This is for the Sun/Oracle keytool, others may be incompatible.\n" + 133 110 "If you create the keystore manually, you must add " + PROP_KEYSTORE_PASSWORD + " and " + PROP_KEY_PASSWORD + 134 111 " to " + (new File(_context.getConfigDir(), "router.config")).getAbsolutePath()); … … 144 121 File sdir = new SecureDirectory(_context.getConfigDir(), "certificates"); 145 122 if (sdir.exists() || sdir.mkdir()) { 146 InputStream fis = null; 147 try { 148 KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 149 fis = new FileInputStream(ks); 150 String ksPass = _context.getProperty(PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD); 151 keyStore.load(fis, ksPass.toCharArray()); 152 Certificate cert = keyStore.getCertificate(KEY_ALIAS); 153 if (cert != null) { 154 File certFile = new File(sdir, ASCII_KEYFILE); 155 saveCert(cert, certFile); 156 } else { 157 _log.error("Error getting SSL cert to save as ASCII"); 158 } 159 } catch (GeneralSecurityException gse) { 160 _log.error("Error saving ASCII SSL keys", gse); 161 } catch (IOException ioe) { 162 _log.error("Error saving ASCII SSL keys", ioe); 163 } finally { 164 if (fis != null) try { fis.close(); } catch (IOException ioe) {} 165 } 123 String ksPass = _context.getProperty(PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD); 124 File out = new File(sdir, ASCII_KEYFILE); 125 boolean success = KeyStoreUtil.exportCert(ks, ksPass, KEY_ALIAS, out); 126 if (!success) 127 _log.error("Error getting SSL cert to save as ASCII"); 166 128 } else { 167 129 _log.error("Error saving ASCII SSL keys"); 168 }169 }170 171 private static final int LINE_LENGTH = 64;172 173 /**174 * Modified from:175 * http://www.exampledepot.com/egs/java.security.cert/ExportCert.html176 *177 * Write a certificate to a file in base64 format.178 */179 private void saveCert(Certificate cert, File file) {180 OutputStream os = null;181 try {182 // Get the encoded form which is suitable for exporting183 byte[] buf = cert.getEncoded();184 os = new SecureFileOutputStream(file);185 PrintWriter wr = new PrintWriter(os);186 wr.println("-----BEGIN CERTIFICATE-----");187 String b64 = Base64.encode(buf, true); // true = use standard alphabet188 for (int i = 0; i < b64.length(); i += LINE_LENGTH) {189 wr.println(b64.substring(i, Math.min(i + LINE_LENGTH, b64.length())));190 }191 wr.println("-----END CERTIFICATE-----");192 wr.flush();193 } catch (CertificateEncodingException cee) {194 _log.error("Error writing X509 Certificate " + file.getAbsolutePath(), cee);195 } catch (IOException ioe) {196 _log.error("Error writing X509 Certificate " + file.getAbsolutePath(), ioe);197 } finally {198 try { if (os != null) os.close(); } catch (IOException foo) {}199 130 } 200 131 } -
tests/scripts/checkcerts.sh
ra1c8e3e r6bb1505d 155 155 cd `dirname $0`/../../installer/resources/certificates 156 156 157 for i in * .crt *.cert157 for i in */*.crt 158 158 do 159 159 echo "Checking $i ..."
Note: See TracChangeset
for help on using the changeset viewer.