forked from I2P_Developers/i2p.i2p
I2CP, Data: Initial support for LS2 offline keys in I2PSession and PrivateKeyFile
This commit is contained in:
@@ -19,7 +19,9 @@ import net.i2p.data.Hash;
|
||||
import net.i2p.data.PrivateKey;
|
||||
import net.i2p.data.SessionKey;
|
||||
import net.i2p.data.SessionTag;
|
||||
import net.i2p.data.Signature;
|
||||
import net.i2p.data.SigningPrivateKey;
|
||||
import net.i2p.data.SigningPublicKey;
|
||||
|
||||
/**
|
||||
* <p>Define the standard means of sending and receiving messages on the
|
||||
@@ -300,10 +302,36 @@ public interface I2PSession {
|
||||
public PrivateKey getDecryptionKey();
|
||||
|
||||
/**
|
||||
* Retrieve the signing SigningPrivateKey associated with the Destination
|
||||
* Retrieve the signing SigningPrivateKey associated with the Destination.
|
||||
* As of 0.9.38, this will be the transient key if offline signed.
|
||||
*/
|
||||
public SigningPrivateKey getPrivateKey();
|
||||
|
||||
/**
|
||||
* Does this session have offline and transient keys?
|
||||
* @since 0.9.38
|
||||
*/
|
||||
public boolean isOffline();
|
||||
|
||||
/**
|
||||
* Get the offline expiration
|
||||
* @return Java time (ms) or 0 if not initialized or does not have offline keys
|
||||
* @since 0.9.38
|
||||
*/
|
||||
public long getOfflineExpiration();
|
||||
|
||||
/**
|
||||
* @return null on error or if not initialized or does not have offline keys
|
||||
* @since 0.9.38
|
||||
*/
|
||||
public Signature getOfflineSignature();
|
||||
|
||||
/**
|
||||
* @return null on error or if not initialized or does not have offline keys
|
||||
* @since 0.9.38
|
||||
*/
|
||||
public SigningPublicKey getTransientSigningPublicKey();
|
||||
|
||||
/**
|
||||
* Lookup a Destination by Hash.
|
||||
* Blocking. Waits a max of 10 seconds by default.
|
||||
|
||||
@@ -36,13 +36,17 @@ import net.i2p.client.I2PClient;
|
||||
import net.i2p.client.I2PSession;
|
||||
import net.i2p.client.I2PSessionException;
|
||||
import net.i2p.client.I2PSessionListener;
|
||||
import net.i2p.crypto.SigType;
|
||||
import net.i2p.data.Base32;
|
||||
import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.data.LeaseSet;
|
||||
import net.i2p.data.PrivateKey;
|
||||
import net.i2p.data.Signature;
|
||||
import net.i2p.data.SigningPrivateKey;
|
||||
import net.i2p.data.SigningPublicKey;
|
||||
import net.i2p.data.i2cp.DestLookupMessage;
|
||||
import net.i2p.data.i2cp.DestReplyMessage;
|
||||
import net.i2p.data.i2cp.GetBandwidthLimitsMessage;
|
||||
@@ -91,6 +95,9 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
private SessionId _sessionId;
|
||||
/** currently granted lease set, or null */
|
||||
protected volatile LeaseSet _leaseSet;
|
||||
private long _offlineExpiration;
|
||||
private Signature _offlineSignature;
|
||||
protected SigningPublicKey _transientSigningPublicKey;
|
||||
|
||||
// subsession stuff
|
||||
// registered subsessions
|
||||
@@ -301,6 +308,9 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
*
|
||||
* As of 0.9.19, defaults in options are honored.
|
||||
*
|
||||
* This does NOT validate consistency of the destKeyStream,
|
||||
* e.g. pubkey/privkey match or valid offline sig. The router does that.
|
||||
*
|
||||
* @param destKeyStream stream containing the private key data,
|
||||
* format is specified in {@link net.i2p.data.PrivateKeyFile PrivateKeyFile}
|
||||
* @param options set of options to configure the router with, if null will use System properties
|
||||
@@ -548,7 +558,11 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
}
|
||||
|
||||
/**
|
||||
* Load up the destKeyFile for our Destination, PrivateKey, and SigningPrivateKey
|
||||
* Load up the destKeyFile for our Destination, PrivateKey, and SigningPrivateKey.
|
||||
* As of 0.9.38, loads the offline data also. See PrivateKeyFile.
|
||||
*
|
||||
* This does NOT validate consistency of the destKeyStream,
|
||||
* e.g. pubkey/privkey match or valid offline sig. The router does that.
|
||||
*
|
||||
* @throws DataFormatException if the file is in the wrong format or keys are invalid
|
||||
* @throws IOException if there is a problem reading the file
|
||||
@@ -556,8 +570,68 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
private void readDestination(InputStream destKeyStream) throws DataFormatException, IOException {
|
||||
_myDestination.readBytes(destKeyStream);
|
||||
_privateKey.readBytes(destKeyStream);
|
||||
_signingPrivateKey = new SigningPrivateKey(_myDestination.getSigningPublicKey().getType());
|
||||
SigType dtype = _myDestination.getSigningPublicKey().getType();
|
||||
_signingPrivateKey = new SigningPrivateKey(dtype);
|
||||
_signingPrivateKey.readBytes(destKeyStream);
|
||||
if (isOffline(_signingPrivateKey)) {
|
||||
_offlineExpiration = DataHelper.readLong(destKeyStream, 4) * 1000;;
|
||||
int itype = (int) DataHelper.readLong(destKeyStream, 2);
|
||||
SigType type = SigType.getByCode(itype);
|
||||
if (type == null)
|
||||
throw new DataFormatException("Unsupported transient sig type: " + itype);
|
||||
_transientSigningPublicKey = new SigningPublicKey(type);
|
||||
_transientSigningPublicKey.readBytes(destKeyStream);
|
||||
_offlineSignature = new Signature(dtype);
|
||||
_offlineSignature.readBytes(destKeyStream);
|
||||
// replace SPK
|
||||
_signingPrivateKey = new SigningPrivateKey(type);
|
||||
_signingPrivateKey.readBytes(destKeyStream);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public boolean isOffline() {
|
||||
return _offlineSignature != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Java time (ms) or 0 if not initialized or does not have offline keys
|
||||
* @since 0.9.38
|
||||
*/
|
||||
public long getOfflineExpiration() {
|
||||
return _offlineExpiration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null on error or if not initialized or does not have offline keys
|
||||
* @since 0.9.38
|
||||
*/
|
||||
public Signature getOfflineSignature() {
|
||||
return _offlineSignature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null on error or if not initialized or does not have offline keys
|
||||
* @since 0.9.38
|
||||
*/
|
||||
public SigningPublicKey getTransientSigningPublicKey() {
|
||||
return _transientSigningPublicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1044,7 +1118,8 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
public PrivateKey getDecryptionKey() { return _privateKey; }
|
||||
|
||||
/**
|
||||
* Retrieve the signing SigningPrivateKey
|
||||
* Retrieve the signing SigningPrivateKey.
|
||||
* As of 0.9.38, this will be the transient key if offline signed.
|
||||
*/
|
||||
public SigningPrivateKey getPrivateKey() { return _signingPrivateKey; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user