diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java
index 77c89319b0..2f5152ad1f 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java
@@ -15,6 +15,7 @@ import java.util.Set;
import java.util.TreeMap;
import net.i2p.client.I2PClient;
+import net.i2p.crypto.SigType;
import net.i2p.data.Base64;
import net.i2p.data.Destination;
import net.i2p.data.PrivateKeyFile;
@@ -183,6 +184,12 @@ public class EditBean extends IndexBean {
return getProperty(tunnel, I2PClient.PROP_SIGTYPE, 0);
}
+ /** @since 0.9.12 */
+ public boolean isSigTypeAvailable(int code) {
+ SigType type = SigType.getByCode(code);
+ return type != null && type.isAvailable();
+ }
+
/** @since 0.8.9 */
public boolean getDCC(int tunnel) {
return getBooleanProperty(tunnel, I2PTunnelIRCClient.PROP_DCC);
diff --git a/apps/i2ptunnel/jsp/editClient.jsp b/apps/i2ptunnel/jsp/editClient.jsp
index 2b560173c8..b07c964acb 100644
--- a/apps/i2ptunnel/jsp/editClient.jsp
+++ b/apps/i2ptunnel/jsp/editClient.jsp
@@ -461,18 +461,24 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
class="tickbox" />
+ <% if (editBean.isSigTypeAvailable(1)) { %>
class="tickbox" />
+ <% }
+ if (editBean.isSigTypeAvailable(2)) { %>
class="tickbox" />
+ <% }
+ if (editBean.isSigTypeAvailable(3)) { %>
class="tickbox" />
+ <% } // isAvailable %>
diff --git a/apps/i2ptunnel/jsp/editServer.jsp b/apps/i2ptunnel/jsp/editServer.jsp
index 1a109b22d9..e0e8023884 100644
--- a/apps/i2ptunnel/jsp/editServer.jsp
+++ b/apps/i2ptunnel/jsp/editServer.jsp
@@ -563,18 +563,24 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
class="tickbox" />
+ <% if (editBean.isSigTypeAvailable(1)) { %>
class="tickbox" />
+ <% }
+ if (editBean.isSigTypeAvailable(2)) { %>
class="tickbox" />
+ <% }
+ if (editBean.isSigTypeAvailable(3)) { %>
class="tickbox" />
+ <% } // isAvailable %>
diff --git a/core/java/src/net/i2p/client/RequestLeaseSetMessageHandler.java b/core/java/src/net/i2p/client/RequestLeaseSetMessageHandler.java
index 09f224efc0..662d50969d 100644
--- a/core/java/src/net/i2p/client/RequestLeaseSetMessageHandler.java
+++ b/core/java/src/net/i2p/client/RequestLeaseSetMessageHandler.java
@@ -9,6 +9,7 @@ package net.i2p.client;
*
*/
+import java.security.GeneralSecurityException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -25,6 +26,7 @@ import net.i2p.data.PublicKey;
import net.i2p.data.SessionKey;
import net.i2p.data.SigningPrivateKey;
import net.i2p.data.SigningPublicKey;
+import net.i2p.data.SimpleDataStructure;
import net.i2p.data.i2cp.I2CPMessage;
import net.i2p.data.i2cp.RequestLeaseSetMessage;
import net.i2p.util.Log;
@@ -129,9 +131,16 @@ class RequestLeaseSetMessageHandler extends HandlerImpl {
private final PrivateKey _privKey;
private final SigningPublicKey _signingPubKey;
private final SigningPrivateKey _signingPrivKey;
+
public LeaseInfo(Destination dest) {
Object encKeys[] = KeyGenerator.getInstance().generatePKIKeypair();
- Object signKeys[] = KeyGenerator.getInstance().generateSigningKeypair();
+ // must be same type as the Destination's signing key
+ SimpleDataStructure signKeys[];
+ try {
+ signKeys = KeyGenerator.getInstance().generateSigningKeys(dest.getSigningPublicKey().getType());
+ } catch (GeneralSecurityException gse) {
+ throw new IllegalStateException(gse);
+ }
_pubKey = (PublicKey) encKeys[0];
_privKey = (PrivateKey) encKeys[1];
_signingPubKey = (SigningPublicKey) signKeys[0];
diff --git a/core/java/src/net/i2p/crypto/SigType.java b/core/java/src/net/i2p/crypto/SigType.java
index c5e32f048d..2ce774c841 100644
--- a/core/java/src/net/i2p/crypto/SigType.java
+++ b/core/java/src/net/i2p/crypto/SigType.java
@@ -2,6 +2,7 @@ package net.i2p.crypto;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.security.Signature;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import java.util.HashMap;
@@ -159,6 +160,24 @@ public enum SigType {
}
}
+ /**
+ * @since 0.9.12
+ * @return true if supported in this JVM
+ */
+ public boolean isAvailable() {
+ if (DSA_SHA1 == this)
+ return true;
+ try {
+ getParams();
+ Signature.getInstance(getAlgorithmName());
+ getDigestInstance();
+ getHashInstance();
+ } catch (Exception e) {
+ return false;
+ }
+ return true;
+ }
+
private static final Map BY_CODE = new HashMap();
static {
diff --git a/core/java/src/net/i2p/data/LeaseSet.java b/core/java/src/net/i2p/data/LeaseSet.java
index cf9b39deb2..6ea3051af8 100644
--- a/core/java/src/net/i2p/data/LeaseSet.java
+++ b/core/java/src/net/i2p/data/LeaseSet.java
@@ -137,12 +137,23 @@ public class LeaseSet extends DatabaseEntry {
_encryptionKey = encryptionKey;
}
- /** @deprecated unused */
+ /**
+ * The revocation key.
+ * @deprecated unused
+ */
public SigningPublicKey getSigningKey() {
return _signingKey;
}
+ /**
+ * The revocation key. Unused.
+ * Must be the same type as the Destination's SigningPublicKey.
+ * @throws IllegalArgumentException if different type
+ */
public void setSigningKey(SigningPublicKey key) {
+ if (key != null && _destination != null &&
+ key.getType() != _destination.getSigningPublicKey().getType())
+ throw new IllegalArgumentException("Signing key type mismatch");
_signingKey = key;
}
diff --git a/history.txt b/history.txt
index 2b77c35371..c36f910836 100644
--- a/history.txt
+++ b/history.txt
@@ -1,3 +1,12 @@
+2014-02-21 zzz
+ * Build: Add property for target version
+ * I2CP Client: Generate revocation key of same type as signing key
+ * i2ptunnel: Only offer SigType options that are available in the JVM
+ * LeaseSet: Add check for SigType mismatch
+ * RouterAddress: Restore storage of expiration and use in signature
+ calculation, broken in 0.9.3, in anticipation of using it someday
+ * SigType: Add isAvailable()
+
2014-02-20 zzz
* i2ptunnel: Add inproxy block option to HTTP server
* Router: Allow null args to main() (broke Android)
diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java
index 7ca1a3ec2c..5a58b19bc2 100644
--- a/router/java/src/net/i2p/router/RouterVersion.java
+++ b/router/java/src/net/i2p/router/RouterVersion.java
@@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION;
- public final static long BUILD = 10;
+ public final static long BUILD = 11;
/** for example "-test" */
public final static String EXTRA = "";