diff --git a/apps/i2ptunnel/jsp/register.jsp b/apps/i2ptunnel/jsp/register.jsp
index 313eea4b3e..5f4f229e98 100644
--- a/apps/i2ptunnel/jsp/register.jsp
+++ b/apps/i2ptunnel/jsp/register.jsp
@@ -127,6 +127,8 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
SigningPrivateKey spk = editBean.getSigningPrivateKey(curTunnel);
if (spk == null) {
%>
<%=intl._t("Destination signing key is not available. Start the tunnel.")%> |
<%
+ } else if (spk.isOffline()) {
+ %><%=intl._t("Destination signing key is offline. Use CLI tools on the offline machine.")%> |
<%
} else {
valid = true;
OrderedProperties props = new OrderedProperties();
diff --git a/apps/sam/java/src/net/i2p/sam/SAMUtils.java b/apps/sam/java/src/net/i2p/sam/SAMUtils.java
index a17ec1f000..3ab98301bb 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMUtils.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMUtils.java
@@ -117,7 +117,7 @@ class SAMUtils {
SigType dtype = d.getSigningPublicKey().getType();
SigningPrivateKey spk = new SigningPrivateKey(dtype);
spk.readBytes(destKeyStream);
- if (isOffline(spk)) {
+ if (spk.isOffline()) {
// offlineExpiration
DataHelper.readLong(destKeyStream, 4);
int itype = (int) DataHelper.readLong(destKeyStream, 2);
@@ -140,19 +140,6 @@ class SAMUtils {
return destKeyStream.available() == 0;
}
- /**
- * @since 0.9.39
- */
- private static boolean isOffline(SigningPrivateKey spk) {
- byte[] data = spk.getData();
- for (int i = 0; i < data.length; i++) {
- if (data[i] != 0)
- return false;
- }
- return true;
- }
-
-
/**
* Resolved the specified hostname.
*
diff --git a/core/java/src/net/i2p/client/impl/I2PSessionImpl.java b/core/java/src/net/i2p/client/impl/I2PSessionImpl.java
index 249f5b74bd..fad799a8e8 100644
--- a/core/java/src/net/i2p/client/impl/I2PSessionImpl.java
+++ b/core/java/src/net/i2p/client/impl/I2PSessionImpl.java
@@ -577,7 +577,7 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
SigType dtype = _myDestination.getSigningPublicKey().getType();
_signingPrivateKey = new SigningPrivateKey(dtype);
_signingPrivateKey.readBytes(destKeyStream);
- if (isOffline(_signingPrivateKey)) {
+ if (_signingPrivateKey.isOffline()) {
_offlineExpiration = DataHelper.readLong(destKeyStream, 4) * 1000;;
int itype = (int) DataHelper.readLong(destKeyStream, 2);
SigType type = SigType.getByCode(itype);
@@ -593,19 +593,6 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
}
}
- /**
- * Constant time
- * @since 0.9.38
- */
- private static boolean isOffline(SigningPrivateKey spk) {
- byte b = 0;
- byte[] data = spk.getData();
- for (int i = 0; i < data.length; i++) {
- b |= data[i];
- }
- return b == 0;
- }
-
/**
* Does this session have offline and transient keys?
* @since 0.9.38
diff --git a/core/java/src/net/i2p/data/PrivateKeyFile.java b/core/java/src/net/i2p/data/PrivateKeyFile.java
index 597ef1b161..db064bfc21 100644
--- a/core/java/src/net/i2p/data/PrivateKeyFile.java
+++ b/core/java/src/net/i2p/data/PrivateKeyFile.java
@@ -620,19 +620,6 @@ public class PrivateKeyFile {
//// offline methods
- /**
- * Constant time
- * @since 0.9.38
- */
- private static boolean isOffline(SigningPrivateKey spk) {
- byte b = 0;
- byte[] data = spk.getData();
- for (int i = 0; i < data.length; i++) {
- b |= data[i];
- }
- return b == 0;
- }
-
/**
* Does this session have offline and transient keys?
* @since 0.9.38
@@ -646,7 +633,7 @@ public class PrivateKeyFile {
* @since 0.9.38
*/
public void setOfflineData(long expires, SigningPublicKey transientPub, Signature sig, SigningPrivateKey transientPriv) {
- if (!isOffline(signingPrivKey)) {
+ if (!signingPrivKey.isOffline()) {
SigType type = getSigningPrivKey().getType();
byte[] dbytes = new byte[type.getPrivkeyLen()];
signingPrivKey = new SigningPrivateKey(type, dbytes);
diff --git a/core/java/src/net/i2p/data/SigningPrivateKey.java b/core/java/src/net/i2p/data/SigningPrivateKey.java
index c9f0143d0a..757c9102a3 100644
--- a/core/java/src/net/i2p/data/SigningPrivateKey.java
+++ b/core/java/src/net/i2p/data/SigningPrivateKey.java
@@ -100,6 +100,21 @@ public class SigningPrivateKey extends SimpleDataStructure {
return Blinding.blind(this, alpha);
}
+ /**
+ * Constant time
+ * @return true if all zeros
+ * @since 0.9.39 moved from PrivateKeyFile
+ */
+ public boolean isOffline() {
+ if (_data == null)
+ return true;
+ byte b = 0;
+ for (int i = 0; i < _data.length; i++) {
+ b |= _data[i];
+ }
+ return b == 0;
+ }
+
/**
* @since 0.9.8
*/