forked from I2P_Developers/i2p.i2p
PrivateKeyFile: New constructor with padding
Router: - Use eepPriv.dat format for router keys file (thx orignal) - Consolidate router keys readin code - Update killKeys file list RouterPrivateKeyFile: New extension to add getRouterIdentity()
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
package net.i2p.data;
|
||||
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@@ -24,6 +26,7 @@ import net.i2p.crypto.DSAEngine;
|
||||
import net.i2p.crypto.KeyGenerator;
|
||||
import net.i2p.crypto.SigType;
|
||||
import net.i2p.util.RandomSource;
|
||||
import net.i2p.util.SecureFileOutputStream;
|
||||
|
||||
/**
|
||||
* This helper class reads and writes files in the
|
||||
@@ -48,11 +51,11 @@ public class PrivateKeyFile {
|
||||
|
||||
private static final int HASH_EFFORT = VerifiedDestination.MIN_HASHCASH_EFFORT;
|
||||
|
||||
private final File file;
|
||||
protected final File file;
|
||||
private final I2PClient client;
|
||||
private Destination dest;
|
||||
private PrivateKey privKey;
|
||||
private SigningPrivateKey signingPrivKey;
|
||||
protected PrivateKey privKey;
|
||||
protected SigningPrivateKey signingPrivKey;
|
||||
|
||||
/**
|
||||
* Create a new PrivateKeyFile, or modify an existing one, with various
|
||||
@@ -224,6 +227,16 @@ public class PrivateKeyFile {
|
||||
*/
|
||||
public PrivateKeyFile(File file, PublicKey pubkey, SigningPublicKey spubkey, Certificate cert,
|
||||
PrivateKey pk, SigningPrivateKey spk) {
|
||||
this(file, pubkey, spubkey, cert, pk, spk, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param padding null OK, must be non-null if spubkey length < 128
|
||||
* @throws IllegalArgumentException on mismatch of spubkey and spk types
|
||||
* @since 0.9.16
|
||||
*/
|
||||
public PrivateKeyFile(File file, PublicKey pubkey, SigningPublicKey spubkey, Certificate cert,
|
||||
PrivateKey pk, SigningPrivateKey spk, byte[] padding) {
|
||||
if (spubkey.getType() != spk.getType())
|
||||
throw new IllegalArgumentException("Signing key type mismatch");
|
||||
this.file = file;
|
||||
@@ -232,6 +245,8 @@ public class PrivateKeyFile {
|
||||
this.dest.setPublicKey(pubkey);
|
||||
this.dest.setSigningPublicKey(spubkey);
|
||||
this.dest.setCertificate(cert);
|
||||
if (padding != null)
|
||||
this.dest.setPadding(padding);
|
||||
this.privKey = pk;
|
||||
this.signingPrivKey = spk;
|
||||
}
|
||||
@@ -241,9 +256,9 @@ public class PrivateKeyFile {
|
||||
*/
|
||||
public Destination createIfAbsent() throws I2PException, IOException, DataFormatException {
|
||||
if(!this.file.exists()) {
|
||||
FileOutputStream out = null;
|
||||
OutputStream out = null;
|
||||
try {
|
||||
out = new FileOutputStream(this.file);
|
||||
out = new SecureFileOutputStream(this.file);
|
||||
if (this.client != null)
|
||||
this.client.createDestination(out);
|
||||
else
|
||||
@@ -257,7 +272,10 @@ public class PrivateKeyFile {
|
||||
return getDestination();
|
||||
}
|
||||
|
||||
/** Also sets the local privKey and signingPrivKey */
|
||||
/**
|
||||
* If the destination is not set, read it in from the file.
|
||||
* Also sets the local privKey and signingPrivKey.
|
||||
*/
|
||||
public Destination getDestination() throws I2PSessionException, IOException, DataFormatException {
|
||||
if (dest == null) {
|
||||
I2PSession s = open();
|
||||
@@ -408,9 +426,9 @@ public class PrivateKeyFile {
|
||||
}
|
||||
|
||||
public I2PSession open(Properties opts) throws I2PSessionException, IOException {
|
||||
FileInputStream in = null;
|
||||
InputStream in = null;
|
||||
try {
|
||||
in = new FileInputStream(this.file);
|
||||
in = new BufferedInputStream(new FileInputStream(this.file));
|
||||
I2PSession s = this.client.createSession(in, opts);
|
||||
return s;
|
||||
} finally {
|
||||
@@ -424,13 +442,12 @@ public class PrivateKeyFile {
|
||||
* Copied from I2PClientImpl.createDestination()
|
||||
*/
|
||||
public void write() throws IOException, DataFormatException {
|
||||
FileOutputStream out = null;
|
||||
OutputStream out = null;
|
||||
try {
|
||||
out = new FileOutputStream(this.file);
|
||||
out = new SecureFileOutputStream(this.file);
|
||||
this.dest.writeBytes(out);
|
||||
this.privKey.writeBytes(out);
|
||||
this.signingPrivKey.writeBytes(out);
|
||||
out.flush();
|
||||
} finally {
|
||||
if (out != null) {
|
||||
try { out.close(); } catch (IOException ioe) {}
|
||||
|
@@ -0,0 +1,52 @@
|
||||
package net.i2p.data.router;
|
||||
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import net.i2p.crypto.SigType;
|
||||
import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.PrivateKey;
|
||||
import net.i2p.data.PrivateKeyFile;
|
||||
import net.i2p.data.SigningPrivateKey;
|
||||
|
||||
/**
|
||||
* Same format as super, simply adds a method to
|
||||
* treat it as a RouterIdentity instead of a Destination.
|
||||
*
|
||||
* @since 0.9.16
|
||||
*/
|
||||
public class RouterPrivateKeyFile extends PrivateKeyFile {
|
||||
|
||||
public RouterPrivateKeyFile(File file) {
|
||||
super(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read it in from the file.
|
||||
* Also sets the local privKey and signingPrivKey.
|
||||
*/
|
||||
public RouterIdentity getRouterIdentity() throws IOException, DataFormatException {
|
||||
InputStream in = null;
|
||||
try {
|
||||
in = new BufferedInputStream(new FileInputStream(this.file));
|
||||
RouterIdentity ri = new RouterIdentity();
|
||||
ri.readBytes(in);
|
||||
privKey = new PrivateKey();
|
||||
privKey.readBytes(in);
|
||||
SigType type = ri.getSigningPublicKey().getType();
|
||||
if (type == null)
|
||||
throw new DataFormatException("Unknown sig type");
|
||||
signingPrivKey = new SigningPrivateKey(type);
|
||||
signingPrivKey.readBytes(in);
|
||||
return ri;
|
||||
} finally {
|
||||
if (in != null) {
|
||||
try { in.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -49,10 +49,10 @@ public class KeyManager {
|
||||
|
||||
public final static String PROP_KEYDIR = "router.keyBackupDir";
|
||||
public final static String DEFAULT_KEYDIR = "keyBackup";
|
||||
private final static String KEYFILE_PRIVATE_ENC = "privateEncryption.key";
|
||||
private final static String KEYFILE_PUBLIC_ENC = "publicEncryption.key";
|
||||
private final static String KEYFILE_PRIVATE_SIGNING = "privateSigning.key";
|
||||
private final static String KEYFILE_PUBLIC_SIGNING = "publicSigning.key";
|
||||
public final static String KEYFILE_PRIVATE_ENC = "privateEncryption.key";
|
||||
public final static String KEYFILE_PUBLIC_ENC = "publicEncryption.key";
|
||||
public final static String KEYFILE_PRIVATE_SIGNING = "privateSigning.key";
|
||||
public final static String KEYFILE_PUBLIC_SIGNING = "publicSigning.key";
|
||||
|
||||
public KeyManager(RouterContext context) {
|
||||
_context = context;
|
||||
|
@@ -34,6 +34,7 @@ import net.i2p.data.SigningPrivateKey;
|
||||
import net.i2p.data.i2np.GarlicMessage;
|
||||
import net.i2p.router.message.GarlicMessageHandler;
|
||||
import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade;
|
||||
import net.i2p.router.startup.CreateRouterInfoJob;
|
||||
import net.i2p.router.startup.StartupJob;
|
||||
import net.i2p.router.startup.WorkingDir;
|
||||
import net.i2p.router.tasks.*;
|
||||
@@ -679,16 +680,18 @@ public class Router implements RouterClock.ClockShiftListener {
|
||||
* Ugly list of files that we need to kill if we are building a new identity
|
||||
*
|
||||
*/
|
||||
private static final String _rebuildFiles[] = new String[] { "router.info",
|
||||
"router.keys",
|
||||
"netDb/my.info", // no longer used
|
||||
"connectionTag.keys", // never used?
|
||||
"keyBackup/privateEncryption.key",
|
||||
"keyBackup/privateSigning.key",
|
||||
"keyBackup/publicEncryption.key",
|
||||
"keyBackup/publicSigning.key",
|
||||
"sessionKeys.dat" // no longer used
|
||||
};
|
||||
private static final String _rebuildFiles[] = new String[] {
|
||||
CreateRouterInfoJob.INFO_FILENAME,
|
||||
CreateRouterInfoJob.KEYS_FILENAME,
|
||||
CreateRouterInfoJob.KEYS2_FILENAME,
|
||||
"netDb/my.info", // no longer used
|
||||
"connectionTag.keys", // never used?
|
||||
KeyManager.DEFAULT_KEYDIR + '/' + KeyManager.KEYFILE_PRIVATE_ENC,
|
||||
KeyManager.DEFAULT_KEYDIR + '/' + KeyManager.KEYFILE_PUBLIC_ENC,
|
||||
KeyManager.DEFAULT_KEYDIR + '/' + KeyManager.KEYFILE_PRIVATE_SIGNING,
|
||||
KeyManager.DEFAULT_KEYDIR + '/' + KeyManager.KEYFILE_PUBLIC_SIGNING,
|
||||
"sessionKeys.dat" // no longer used
|
||||
};
|
||||
|
||||
public void killKeys() {
|
||||
//new Exception("Clearing identity files").printStackTrace();
|
||||
|
@@ -21,6 +21,7 @@ import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.data.KeyCertificate;
|
||||
import net.i2p.data.PrivateKey;
|
||||
import net.i2p.data.PrivateKeyFile;
|
||||
import net.i2p.data.PublicKey;
|
||||
import net.i2p.data.router.RouterIdentity;
|
||||
import net.i2p.data.router.RouterInfo;
|
||||
@@ -46,13 +47,11 @@ public class CreateRouterInfoJob extends JobImpl {
|
||||
private final Job _next;
|
||||
|
||||
public static final String INFO_FILENAME = "router.info";
|
||||
static final String KEYS_FILENAME = "router.keys";
|
||||
static final String KEYS2_FILENAME = "router.keys2";
|
||||
public static final String KEYS_FILENAME = "router.keys";
|
||||
public static final String KEYS2_FILENAME = "router.keys.dat";
|
||||
private static final String PROP_ROUTER_SIGTYPE = "router.sigType";
|
||||
/** TODO when changing, check isAvailable() and fallback to DSA_SHA1 */
|
||||
private static final SigType DEFAULT_SIGTYPE = SigType.DSA_SHA1;
|
||||
static final byte[] KEYS2_MAGIC = DataHelper.getASCII("I2Pkeys2");
|
||||
static final int KEYS2_UNUSED_BYTES = 28;
|
||||
|
||||
CreateRouterInfoJob(RouterContext ctx, Job next) {
|
||||
super(ctx);
|
||||
@@ -75,20 +74,9 @@ public class CreateRouterInfoJob extends JobImpl {
|
||||
* Writes 6 files: router.info (standard RI format),
|
||||
* router.keys2, and 4 individual key files under keyBackup/
|
||||
*
|
||||
* router.keys2 file format: Note that this is NOT the
|
||||
* same "eepPriv.dat" format used by the client code.
|
||||
*<pre>
|
||||
* - Magic "I2Pkeys2"
|
||||
* - 2 byte crypto type, always 0000 for now
|
||||
* - 2 byte sig type, see SigType
|
||||
* - 28 bytes unused
|
||||
* - Private key (256 bytes)
|
||||
* - Signing Private key (20 bytes or see SigType)
|
||||
* - Public key (256 bytes)
|
||||
* - Random padding for Signing Public Key if less than 128 bytes
|
||||
* - Signing Public key (128 bytes or see SigTpe)
|
||||
* Total 660 bytes
|
||||
*</pre>
|
||||
* router.keys2 file format: This is the
|
||||
* same "eepPriv.dat" format used by the client code,
|
||||
* as documented in PrivateKeyFile.
|
||||
*
|
||||
* Old router.keys file format: Note that this is NOT the
|
||||
* same "eepPriv.dat" format used by the client code.
|
||||
@@ -106,7 +94,6 @@ public class CreateRouterInfoJob extends JobImpl {
|
||||
SigType type = getSigTypeConfig(getContext());
|
||||
RouterInfo info = new RouterInfo();
|
||||
OutputStream fos1 = null;
|
||||
OutputStream fos2 = null;
|
||||
try {
|
||||
info.setAddresses(getContext().commSystem().createAddresses());
|
||||
Properties stats = getContext().statPublisher().publishStatistics();
|
||||
@@ -151,19 +138,11 @@ public class CreateRouterInfoJob extends JobImpl {
|
||||
fos1 = new BufferedOutputStream(new SecureFileOutputStream(ifile));
|
||||
info.writeBytes(fos1);
|
||||
|
||||
// write router.keys2
|
||||
// write router.keys.dat
|
||||
File kfile = new File(getContext().getRouterDir(), KEYS2_FILENAME);
|
||||
fos2 = new BufferedOutputStream(new SecureFileOutputStream(kfile));
|
||||
fos2.write(KEYS2_MAGIC);
|
||||
DataHelper.writeLong(fos2, 2, 0);
|
||||
DataHelper.writeLong(fos2, 2, type.getCode());
|
||||
fos2.write(new byte[KEYS2_UNUSED_BYTES]);
|
||||
privkey.writeBytes(fos2);
|
||||
signingPrivKey.writeBytes(fos2);
|
||||
pubkey.writeBytes(fos2);
|
||||
if (padding != null)
|
||||
fos2.write(padding);
|
||||
signingPubKey.writeBytes(fos2);
|
||||
PrivateKeyFile pkf = new PrivateKeyFile(kfile, pubkey, signingPubKey, cert,
|
||||
privkey, signingPrivKey, padding);
|
||||
pkf.write();
|
||||
|
||||
getContext().keyManager().setKeys(pubkey, privkey, signingPubKey, signingPrivKey);
|
||||
|
||||
@@ -178,7 +157,6 @@ public class CreateRouterInfoJob extends JobImpl {
|
||||
_log.log(Log.CRIT, "Error writing out the new router information", ioe);
|
||||
} finally {
|
||||
if (fos1 != null) try { fos1.close(); } catch (IOException ioe) {}
|
||||
if (fos2 != null) try { fos2.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
@@ -16,13 +16,16 @@ import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import net.i2p.crypto.SigType;
|
||||
import net.i2p.data.Certificate;
|
||||
import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.data.PrivateKey;
|
||||
import net.i2p.data.PublicKey;
|
||||
import net.i2p.data.router.RouterInfo;
|
||||
import net.i2p.data.SigningPrivateKey;
|
||||
import net.i2p.data.SigningPublicKey;
|
||||
import net.i2p.data.router.RouterIdentity;
|
||||
import net.i2p.data.router.RouterInfo;
|
||||
import net.i2p.data.router.RouterPrivateKeyFile;
|
||||
import net.i2p.router.JobImpl;
|
||||
import net.i2p.router.Router;
|
||||
import net.i2p.router.RouterContext;
|
||||
@@ -76,7 +79,6 @@ class LoadRouterInfoJob extends JobImpl {
|
||||
boolean keys2Exist = rkf2.exists();
|
||||
|
||||
InputStream fis1 = null;
|
||||
InputStream fis2 = null;
|
||||
try {
|
||||
// if we have a routerinfo but no keys, things go bad in a hurry:
|
||||
// CRIT ...rkdb.PublishLocalRouterInfoJob: Internal error - signing private key not known? rescheduling publish for 30s
|
||||
@@ -97,33 +99,17 @@ class LoadRouterInfoJob extends JobImpl {
|
||||
}
|
||||
|
||||
if (keys2Exist || keysExist) {
|
||||
SigType stype;
|
||||
if (keys2Exist) {
|
||||
fis2 = new BufferedInputStream(new FileInputStream(rkf2));
|
||||
// read keys2 headers
|
||||
byte[] magic = new byte[CreateRouterInfoJob.KEYS2_MAGIC.length];
|
||||
DataHelper.read(fis2, magic);
|
||||
if (!DataHelper.eq(magic, CreateRouterInfoJob.KEYS2_MAGIC))
|
||||
throw new IOException("Bad magic");
|
||||
int ctype = (int) DataHelper.readLong(fis2, 2);
|
||||
if (ctype != 0)
|
||||
throw new IOException("Unsupported RI crypto type " + ctype);
|
||||
int sstype = (int) DataHelper.readLong(fis2, 2);
|
||||
stype = SigType.getByCode(sstype);
|
||||
if (stype == null || !stype.isAvailable())
|
||||
throw new IOException("Unsupported RI sig type " + stype);
|
||||
DataHelper.skip(fis2, CreateRouterInfoJob.KEYS2_UNUSED_BYTES);
|
||||
} else {
|
||||
fis2 = new BufferedInputStream(new FileInputStream(rkf));
|
||||
stype = SigType.DSA_SHA1;
|
||||
}
|
||||
KeyData kd = readKeyData(rkf, rkf2);
|
||||
PublicKey pubkey = kd.routerIdentity.getPublicKey();
|
||||
SigningPublicKey signingPubKey = kd.routerIdentity.getSigningPublicKey();
|
||||
PrivateKey privkey = kd.privateKey;
|
||||
SigningPrivateKey signingPrivKey = kd.signingPrivateKey;
|
||||
SigType stype = signingPubKey.getType();
|
||||
|
||||
// check if the sigtype config changed
|
||||
SigType cstype = CreateRouterInfoJob.getSigTypeConfig(getContext());
|
||||
boolean sigTypeChanged = stype != cstype;
|
||||
|
||||
PrivateKey privkey = new PrivateKey();
|
||||
privkey.readBytes(fis2);
|
||||
if (sigTypeChanged || shouldRebuild(privkey)) {
|
||||
if (sigTypeChanged)
|
||||
_log.logAlways(Log.WARN, "Rebuilding RouterInfo with new signature type " + cstype);
|
||||
@@ -133,24 +119,11 @@ class LoadRouterInfoJob extends JobImpl {
|
||||
try { fis1.close(); } catch (IOException ioe) {}
|
||||
fis1 = null;
|
||||
}
|
||||
try { fis2.close(); } catch (IOException ioe) {}
|
||||
fis2 = null;
|
||||
rif.delete();
|
||||
rkf.delete();
|
||||
rkf2.delete();
|
||||
return;
|
||||
}
|
||||
SigningPrivateKey signingPrivKey = new SigningPrivateKey(stype);
|
||||
signingPrivKey.readBytes(fis2);
|
||||
PublicKey pubkey = new PublicKey();
|
||||
pubkey.readBytes(fis2);
|
||||
SigningPublicKey signingPubKey = new SigningPublicKey(stype);
|
||||
int padLen = SigningPublicKey.KEYSIZE_BYTES - signingPubKey.length();
|
||||
if (padLen > 0) {
|
||||
// we lose the padding as keymanager doesn't store it, what to do?
|
||||
DataHelper.skip(fis2, padLen);
|
||||
}
|
||||
signingPubKey.readBytes(fis2);
|
||||
|
||||
getContext().keyManager().setKeys(pubkey, privkey, signingPubKey, signingPrivKey);
|
||||
}
|
||||
@@ -162,10 +135,6 @@ class LoadRouterInfoJob extends JobImpl {
|
||||
try { fis1.close(); } catch (IOException ioe2) {}
|
||||
fis1 = null;
|
||||
}
|
||||
if (fis2 != null) {
|
||||
try { fis2.close(); } catch (IOException ioe2) {}
|
||||
fis2 = null;
|
||||
}
|
||||
rif.delete();
|
||||
rkf.delete();
|
||||
rkf2.delete();
|
||||
@@ -177,16 +146,11 @@ class LoadRouterInfoJob extends JobImpl {
|
||||
try { fis1.close(); } catch (IOException ioe) {}
|
||||
fis1 = null;
|
||||
}
|
||||
if (fis2 != null) {
|
||||
try { fis2.close(); } catch (IOException ioe) {}
|
||||
fis2 = null;
|
||||
}
|
||||
rif.delete();
|
||||
rkf.delete();
|
||||
rkf2.delete();
|
||||
} finally {
|
||||
if (fis1 != null) try { fis1.close(); } catch (IOException ioe) {}
|
||||
if (fis2 != null) try { fis2.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,4 +183,55 @@ class LoadRouterInfoJob extends JobImpl {
|
||||
_log.logAlways(Log.WARN, "Rebuilding RouterInfo with faster key");
|
||||
return uselong != haslong;
|
||||
}
|
||||
|
||||
/** @since 0.9.16 */
|
||||
public static class KeyData {
|
||||
public final RouterIdentity routerIdentity;
|
||||
public final PrivateKey privateKey;
|
||||
public final SigningPrivateKey signingPrivateKey;
|
||||
|
||||
public KeyData(RouterIdentity ri, PrivateKey pk, SigningPrivateKey spk) {
|
||||
routerIdentity = ri;
|
||||
privateKey = pk;
|
||||
signingPrivateKey = spk;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rkf1 in router.keys format, tried second
|
||||
* @param rkf2 in eepPriv.dat format, tried first
|
||||
* @return non-null, throws IOE if neither exisits
|
||||
* @since 0.9.16
|
||||
*/
|
||||
public static KeyData readKeyData(File rkf1, File rkf2) throws DataFormatException, IOException {
|
||||
RouterIdentity ri;
|
||||
PrivateKey privkey;
|
||||
SigningPrivateKey signingPrivKey;
|
||||
if (rkf2.exists()) {
|
||||
RouterPrivateKeyFile pkf = new RouterPrivateKeyFile(rkf2);
|
||||
ri = pkf.getRouterIdentity();
|
||||
privkey = pkf.getPrivKey();
|
||||
signingPrivKey = pkf.getSigningPrivKey();
|
||||
} else {
|
||||
InputStream fis = null;
|
||||
try {
|
||||
fis = new BufferedInputStream(new FileInputStream(rkf1));
|
||||
privkey = new PrivateKey();
|
||||
privkey.readBytes(fis);
|
||||
signingPrivKey = new SigningPrivateKey();
|
||||
signingPrivKey.readBytes(fis);
|
||||
PublicKey pubkey = new PublicKey();
|
||||
pubkey.readBytes(fis);
|
||||
SigningPublicKey signingPubKey = new SigningPublicKey();
|
||||
signingPubKey.readBytes(fis);
|
||||
ri = new RouterIdentity();
|
||||
ri.setPublicKey(pubkey);
|
||||
ri.setSigningPublicKey(signingPubKey);
|
||||
ri.setCertificate(Certificate.NULL_CERT);
|
||||
} finally {
|
||||
if (fis != null) try { fis.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
return new KeyData(ri, privkey, signingPrivKey);
|
||||
}
|
||||
}
|
||||
|
@@ -8,11 +8,8 @@ package net.i2p.router.startup;
|
||||
*
|
||||
*/
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
@@ -29,6 +26,7 @@ import net.i2p.data.SigningPublicKey;
|
||||
import net.i2p.router.JobImpl;
|
||||
import net.i2p.router.Router;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.startup.LoadRouterInfoJob.KeyData;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.SecureFileOutputStream;
|
||||
|
||||
@@ -96,61 +94,16 @@ class RebuildRouterInfoJob extends JobImpl {
|
||||
// ok, no need to rebuild a brand new identity, just update what we can
|
||||
RouterInfo oldinfo = getContext().router().getRouterInfo();
|
||||
if (oldinfo == null) {
|
||||
info = new RouterInfo();
|
||||
InputStream fis = null;
|
||||
try {
|
||||
SigType stype;
|
||||
if (keyFile2.exists()) {
|
||||
fis = new BufferedInputStream(new FileInputStream(keyFile2));
|
||||
byte[] magic = new byte[CreateRouterInfoJob.KEYS2_MAGIC.length];
|
||||
DataHelper.read(fis, magic);
|
||||
if (!DataHelper.eq(magic, CreateRouterInfoJob.KEYS2_MAGIC))
|
||||
throw new IOException("Bad magic");
|
||||
int ctype = (int) DataHelper.readLong(fis, 2);
|
||||
if (ctype != 0)
|
||||
throw new IOException("Unsupported RI crypto type " + ctype);
|
||||
int sstype = (int) DataHelper.readLong(fis, 2);
|
||||
stype = SigType.getByCode(sstype);
|
||||
if (stype == null || !stype.isAvailable())
|
||||
throw new IOException("Unsupported RI sig type " + stype);
|
||||
DataHelper.skip(fis, CreateRouterInfoJob.KEYS2_UNUSED_BYTES);
|
||||
} else {
|
||||
fis = new BufferedInputStream(new FileInputStream(keyFile));
|
||||
stype = SigType.DSA_SHA1;
|
||||
}
|
||||
PrivateKey privkey = new PrivateKey();
|
||||
privkey.readBytes(fis);
|
||||
SigningPrivateKey signingPrivKey = new SigningPrivateKey(stype);
|
||||
signingPrivKey.readBytes(fis);
|
||||
PublicKey pubkey = new PublicKey();
|
||||
pubkey.readBytes(fis);
|
||||
SigningPublicKey signingPubKey = new SigningPublicKey(stype);
|
||||
byte[] padding;
|
||||
int padLen = SigningPublicKey.KEYSIZE_BYTES - signingPubKey.length();
|
||||
if (padLen > 0) {
|
||||
padding = new byte[padLen];
|
||||
DataHelper.read(fis, padding);
|
||||
} else {
|
||||
padding = null;
|
||||
}
|
||||
signingPubKey.readBytes(fis);
|
||||
RouterIdentity ident = new RouterIdentity();
|
||||
Certificate cert = CreateRouterInfoJob.createCertificate(getContext(), signingPubKey);
|
||||
ident.setCertificate(cert);
|
||||
ident.setPublicKey(pubkey);
|
||||
ident.setSigningPublicKey(signingPubKey);
|
||||
if (padding != null)
|
||||
ident.setPadding(padding);
|
||||
info.setIdentity(ident);
|
||||
KeyData kd = LoadRouterInfoJob.readKeyData(keyFile, keyFile2);
|
||||
info = new RouterInfo();
|
||||
info.setIdentity(kd.routerIdentity);
|
||||
} catch (Exception e) {
|
||||
_log.log(Log.CRIT, "Error reading in the key data from " + keyFile.getAbsolutePath(), e);
|
||||
if (fis != null) try { fis.close(); } catch (IOException ioe) {}
|
||||
fis = null;
|
||||
keyFile.delete();
|
||||
keyFile2.delete();
|
||||
rebuildRouterInfo(alreadyRunning);
|
||||
return;
|
||||
} finally {
|
||||
if (fis != null) try { fis.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
} else {
|
||||
// Make a new RI from the old identity, or else info.setAddresses() will throw an ISE
|
||||
|
Reference in New Issue
Block a user