use of net.i2p.data.PublicKey in project i2p.i2p by i2p.
the class GarlicMessageBuilder method buildMessage.
/**
* called by netdb and above
*
* @param ctx scope
* @param config how/what to wrap
* @param wrappedKey output parameter that will be filled with the sessionKey used
* @param wrappedTags Output parameter that will be filled with the sessionTags used.
* If non-empty on return you must call skm.tagsDelivered() when sent
* and then call skm.tagsAcked() or skm.failTags() later.
* @param numTagsToDeliver only if the estimated available tags are below the threshold.
* Set to zero to disable tag delivery. You must set to zero if you are not
* equipped to confirm delivery and call skm.tagsAcked() or failTags() later.
* If this is always 0, it forces ElGamal every time.
* @param lowTagsThreshold the threshold
* @param skm non-null
* @throws IllegalArgumentException on error
*/
public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set<SessionTag> wrappedTags, int numTagsToDeliver, int lowTagsThreshold, SessionKeyManager skm) {
Log log = ctx.logManager().getLog(GarlicMessageBuilder.class);
PublicKey key = config.getRecipientPublicKey();
if (key == null) {
if (config.getRecipient() == null) {
throw new IllegalArgumentException("Null recipient specified");
} else if (config.getRecipient().getIdentity() == null) {
throw new IllegalArgumentException("Null recipient.identity specified");
} else if (config.getRecipient().getIdentity().getPublicKey() == null) {
throw new IllegalArgumentException("Null recipient.identity.publicKey specified");
} else
key = config.getRecipient().getIdentity().getPublicKey();
}
if (log.shouldLog(Log.INFO))
log.info("Encrypted with public key to expire on " + new Date(config.getExpiration()));
SessionKey curKey = skm.getCurrentOrNewKey(key);
SessionTag curTag = null;
curTag = skm.consumeNextAvailableTag(key, curKey);
if (log.shouldLog(Log.DEBUG)) {
int availTags = skm.getAvailableTags(key, curKey);
log.debug("Available tags for encryption: " + availTags + " low threshold: " + lowTagsThreshold);
}
if (numTagsToDeliver > 0 && skm.shouldSendTags(key, curKey, lowTagsThreshold)) {
for (int i = 0; i < numTagsToDeliver; i++) wrappedTags.add(new SessionTag(true));
if (log.shouldLog(Log.INFO))
log.info("Too few tags available so we're including " + numTagsToDeliver);
}
wrappedKey.setData(curKey.getData());
return buildMessage(ctx, config, wrappedKey, wrappedTags, key, curKey, curTag);
}
use of net.i2p.data.PublicKey in project i2p.i2p by i2p.
the class CreateRouterInfoJob method createRouterInfo.
/**
* Writes 6 files: router.info (standard RI format),
* router.keys.dat, and 4 individual key files under keyBackup/
*
* router.keys.dat 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.
*<pre>
* - Private key (256 bytes)
* - Signing Private key (20 bytes)
* - Public key (256 bytes)
* - Signing Public key (128 bytes)
* Total 660 bytes
*</pre>
*
* Caller must hold Router.routerInfoFileLock.
*/
RouterInfo createRouterInfo() {
SigType type = getSigTypeConfig(getContext());
RouterInfo info = new RouterInfo();
OutputStream fos1 = null;
try {
info.setAddresses(getContext().commSystem().createAddresses());
// not necessary, in constructor
// info.setPeers(new HashSet());
info.setPublished(getCurrentPublishDate(getContext()));
Object[] keypair = getContext().keyGenerator().generatePKIKeypair();
PublicKey pubkey = (PublicKey) keypair[0];
PrivateKey privkey = (PrivateKey) keypair[1];
SimpleDataStructure[] signingKeypair = getContext().keyGenerator().generateSigningKeys(type);
SigningPublicKey signingPubKey = (SigningPublicKey) signingKeypair[0];
SigningPrivateKey signingPrivKey = (SigningPrivateKey) signingKeypair[1];
RouterIdentity ident = new RouterIdentity();
Certificate cert = createCertificate(getContext(), signingPubKey);
ident.setCertificate(cert);
ident.setPublicKey(pubkey);
ident.setSigningPublicKey(signingPubKey);
byte[] padding;
int padLen = SigningPublicKey.KEYSIZE_BYTES - signingPubKey.length();
if (padLen > 0) {
padding = new byte[padLen];
getContext().random().nextBytes(padding);
ident.setPadding(padding);
} else {
padding = null;
}
info.setIdentity(ident);
Properties stats = getContext().statPublisher().publishStatistics(ident.getHash());
info.setOptions(stats);
info.sign(signingPrivKey);
if (!info.isValid())
throw new DataFormatException("RouterInfo we just built is invalid: " + info);
// remove router.keys
(new File(getContext().getRouterDir(), KEYS_FILENAME)).delete();
// write router.info
File ifile = new File(getContext().getRouterDir(), INFO_FILENAME);
fos1 = new BufferedOutputStream(new SecureFileOutputStream(ifile));
info.writeBytes(fos1);
// write router.keys.dat
File kfile = new File(getContext().getRouterDir(), KEYS2_FILENAME);
PrivateKeyFile pkf = new PrivateKeyFile(kfile, pubkey, signingPubKey, cert, privkey, signingPrivKey, padding);
pkf.write();
// set or overwrite old random keys
Map<String, String> map = new HashMap<String, String>(2);
byte[] rk = new byte[32];
getContext().random().nextBytes(rk);
map.put(Router.PROP_IB_RANDOM_KEY, Base64.encode(rk));
getContext().random().nextBytes(rk);
map.put(Router.PROP_OB_RANDOM_KEY, Base64.encode(rk));
getContext().router().saveConfig(map, null);
getContext().keyManager().setKeys(pubkey, privkey, signingPubKey, signingPrivKey);
if (_log.shouldLog(Log.INFO))
_log.info("Router info created and stored at " + ifile.getAbsolutePath() + " with private keys stored at " + kfile.getAbsolutePath() + " [" + info + "]");
getContext().router().eventLog().addEvent(EventLog.REKEYED, ident.calculateHash().toBase64());
} catch (GeneralSecurityException gse) {
_log.log(Log.CRIT, "Error building the new router information", gse);
} catch (DataFormatException dfe) {
_log.log(Log.CRIT, "Error building the new router information", dfe);
} catch (IOException ioe) {
_log.log(Log.CRIT, "Error writing out the new router information", ioe);
} finally {
if (fos1 != null)
try {
fos1.close();
} catch (IOException ioe) {
}
}
return info;
}
use of net.i2p.data.PublicKey in project i2p.i2p by i2p.
the class LoadRouterInfoJob method loadRouterInfo.
/**
* Loads router.info and either router.keys.dat or router.keys.
*
* See CreateRouterInfoJob for file formats
*/
private void loadRouterInfo() {
RouterInfo info = null;
File rif = new File(getContext().getRouterDir(), CreateRouterInfoJob.INFO_FILENAME);
boolean infoExists = rif.exists();
File rkf = new File(getContext().getRouterDir(), CreateRouterInfoJob.KEYS_FILENAME);
boolean keysExist = rkf.exists();
File rkf2 = new File(getContext().getRouterDir(), CreateRouterInfoJob.KEYS2_FILENAME);
boolean keys2Exist = rkf2.exists();
InputStream fis1 = null;
try {
// so pretend the RI isn't there if there is no keyfile
if (infoExists && (keys2Exist || keysExist)) {
fis1 = new BufferedInputStream(new FileInputStream(rif));
info = new RouterInfo();
info.readBytes(fis1);
// Catch this here before it all gets worse
if (!info.isValid())
throw new DataFormatException("Our RouterInfo has a bad signature");
if (_log.shouldLog(Log.DEBUG))
_log.debug("Reading in routerInfo from " + rif.getAbsolutePath() + " and it has " + info.getAddresses().size() + " addresses");
// don't reuse if family name changed
if (DataHelper.eq(info.getOption(FamilyKeyCrypto.OPT_NAME), getContext().getProperty(FamilyKeyCrypto.PROP_FAMILY_NAME))) {
_us = info;
} else {
_log.logAlways(Log.WARN, "NetDb family name changed");
}
}
if (keys2Exist || keysExist) {
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;
if (sigTypeChanged && getContext().getProperty(CreateRouterInfoJob.PROP_ROUTER_SIGTYPE) == null) {
// TODO reduce to ~3 (i.e. increase probability) in future release
if (getContext().random().nextInt(4) > 0) {
sigTypeChanged = false;
if (_log.shouldWarn())
_log.warn("Deferring RI rekey from " + stype + " to " + cstype);
}
}
if (sigTypeChanged || shouldRebuild(privkey)) {
if (_us != null) {
Hash h = _us.getIdentity().getHash();
_log.logAlways(Log.WARN, "Deleting old router identity " + h.toBase64());
// the netdb hasn't started yet, but we want to delete the RI
File f = PersistentDataStore.getRouterInfoFile(getContext(), h);
f.delete();
// the banlist can be called at any time
getContext().banlist().banlistRouterForever(h, "Our previous identity");
_us = null;
}
if (sigTypeChanged)
_log.logAlways(Log.WARN, "Rebuilding RouterInfo with new signature type " + cstype);
// windows... close before deleting
if (fis1 != null) {
try {
fis1.close();
} catch (IOException ioe) {
}
fis1 = null;
}
rif.delete();
rkf.delete();
rkf2.delete();
return;
}
getContext().keyManager().setKeys(pubkey, privkey, signingPubKey, signingPrivKey);
}
} catch (IOException ioe) {
_log.log(Log.CRIT, "Error reading the router info from " + rif.getAbsolutePath() + " and the keys from " + rkf.getAbsolutePath(), ioe);
_us = null;
// windows... close before deleting
if (fis1 != null) {
try {
fis1.close();
} catch (IOException ioe2) {
}
fis1 = null;
}
rif.delete();
rkf.delete();
rkf2.delete();
} catch (DataFormatException dfe) {
_log.log(Log.CRIT, "Corrupt router info or keys at " + rif.getAbsolutePath() + " / " + rkf.getAbsolutePath(), dfe);
_us = null;
// windows... close before deleting
if (fis1 != null) {
try {
fis1.close();
} catch (IOException ioe) {
}
fis1 = null;
}
rif.delete();
rkf.delete();
rkf2.delete();
} finally {
if (fis1 != null)
try {
fis1.close();
} catch (IOException ioe) {
}
}
}
use of net.i2p.data.PublicKey in project i2p.i2p by i2p.
the class SessionEncryptionTest method testNoSessions1.
public void testNoSessions1() throws Exception {
Object[] keys = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey pubKey = (PublicKey) keys[0];
PrivateKey privKey = (PrivateKey) keys[1];
SessionKeyManager skm = new TransientSessionKeyManager(_context);
SessionKey curKey = skm.createSession(pubKey);
byte[] msg = DataHelper.getASCII("msg 1");
byte[] emsg = _context.elGamalAESEngine().encrypt(msg, pubKey, curKey, null, null, 64);
byte[] dmsg = _context.elGamalAESEngine().decrypt(emsg, privKey, skm);
assertTrue(DataHelper.eq(dmsg, msg));
}
use of net.i2p.data.PublicKey in project i2p.i2p by i2p.
the class SessionEncryptionTest method testSessions.
/**
* Run tagsIncluded useTag rekey
* 1 yes (2) no no
* 2 no yes no
* 3 yes (2) yes no
* 4 no yes no
* 5 no yes no
*/
public void testSessions() throws Exception {
Object[] keys = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey pubKey = (PublicKey) keys[0];
PrivateKey privKey = (PrivateKey) keys[1];
SessionKeyManager skm = new TransientSessionKeyManager(_context);
SessionKey curKey = skm.createSession(pubKey);
SessionTag tag1 = new SessionTag(true);
SessionTag tag2 = new SessionTag(true);
SessionTag tag3 = new SessionTag(true);
SessionTag tag4 = new SessionTag(true);
HashSet<SessionTag> firstTags = new HashSet<SessionTag>();
firstTags.add(tag1);
firstTags.add(tag2);
HashSet<SessionTag> secondTags = new HashSet<SessionTag>();
secondTags.add(tag3);
secondTags.add(tag4);
byte[] msg1 = DataHelper.getASCII("msg 1");
byte[] msg2 = DataHelper.getASCII("msg 2");
byte[] msg3 = DataHelper.getASCII("msg 3");
byte[] msg4 = DataHelper.getASCII("msg 4");
byte[] msg5 = DataHelper.getASCII("msg 5");
byte[] emsg1 = _context.elGamalAESEngine().encrypt(msg1, pubKey, curKey, firstTags, null, 64);
byte[] dmsg1 = _context.elGamalAESEngine().decrypt(emsg1, privKey, skm);
assertTrue(DataHelper.eq(dmsg1, msg1));
TagSetHandle tsh = skm.tagsDelivered(pubKey, curKey, firstTags);
skm.tagsAcked(pubKey, curKey, tsh);
curKey = skm.getCurrentKey(pubKey);
SessionTag curTag = skm.consumeNextAvailableTag(pubKey, curKey);
assertNotNull(curTag);
byte[] emsg2 = _context.elGamalAESEngine().encrypt(msg2, pubKey, curKey, null, curTag, 64);
byte[] dmsg2 = _context.elGamalAESEngine().decrypt(emsg2, privKey, skm);
assertTrue(DataHelper.eq(dmsg2, msg2));
curKey = skm.getCurrentKey(pubKey);
curTag = skm.consumeNextAvailableTag(pubKey, curKey);
assertNotNull(curTag);
assertNotNull(curKey);
byte[] emsg3 = _context.elGamalAESEngine().encrypt(msg3, pubKey, curKey, secondTags, curTag, 64);
byte[] dmsg3 = _context.elGamalAESEngine().decrypt(emsg3, privKey, skm);
assertTrue(DataHelper.eq(dmsg3, msg3));
tsh = skm.tagsDelivered(pubKey, curKey, secondTags);
skm.tagsAcked(pubKey, curKey, tsh);
curKey = skm.getCurrentKey(pubKey);
curTag = skm.consumeNextAvailableTag(pubKey, curKey);
assertNotNull(curTag);
assertNotNull(curKey);
byte[] emsg4 = _context.elGamalAESEngine().encrypt(msg4, pubKey, curKey, null, curTag, 64);
byte[] dmsg4 = _context.elGamalAESEngine().decrypt(emsg4, privKey, skm);
assertTrue(DataHelper.eq(dmsg4, msg4));
curKey = skm.getCurrentKey(pubKey);
curTag = skm.consumeNextAvailableTag(pubKey, curKey);
assertNotNull(curTag);
assertNotNull(curKey);
byte[] emsg5 = _context.elGamalAESEngine().encrypt(msg5, pubKey, curKey, null, curTag, 64);
byte[] dmsg5 = _context.elGamalAESEngine().decrypt(emsg5, privKey, skm);
assertTrue(DataHelper.eq(dmsg5, msg5));
}
Aggregations