private boolean handleGetOfferedKey(Message m, PeerNode source) { Key key = (Key) m.getObject(DMT.KEY); byte[] authenticator = ((ShortBuffer) m.getObject(DMT.OFFER_AUTHENTICATOR)).getData(); long uid = m.getLong(DMT.UID); if (!HMAC.verifyWithSHA256( node.failureTable.offerAuthenticatorKey, key.getFullKey(), authenticator)) { Logger.error( this, "Invalid offer request from " + source + " : authenticator did not verify"); try { source.sendAsync( DMT.createFNPGetOfferedKeyInvalid(uid, DMT.GET_OFFERED_KEY_REJECTED_BAD_AUTHENTICATOR), null, node.failureTable.senderCounter); } catch (NotConnectedException e) { // Too bad. } return true; } if (logMINOR) Logger.minor(this, "Valid GetOfferedKey for " + key + " from " + source); // Do we want it? We can RejectOverload if we don't have the bandwidth... boolean isSSK = key instanceof NodeSSK; OfferReplyTag tag = new OfferReplyTag(isSSK); node.lockUID(uid, isSSK, false, true, false, tag); boolean needPubKey; try { needPubKey = m.getBoolean(DMT.NEED_PUB_KEY); String reject = nodeStats.shouldRejectRequest(true, false, isSSK, false, true, source, false); if (reject != null) { Logger.normal( this, "Rejecting FNPGetOfferedKey from " + source + " for " + key + " : " + reject); Message rejected = DMT.createFNPRejectedOverload(uid, true); try { source.sendAsync(rejected, null, node.failureTable.senderCounter); } catch (NotConnectedException e) { Logger.normal( this, "Rejecting (overload) data request from " + source.getPeer() + ": " + e); } node.unlockUID(uid, isSSK, false, false, true, false, tag); return true; } } catch (Error e) { node.unlockUID(uid, isSSK, false, false, true, false, tag); throw e; } catch (RuntimeException e) { node.unlockUID(uid, isSSK, false, false, true, false, tag); throw e; } // Otherwise, sendOfferedKey is responsible for unlocking. // Accept it. try { node.failureTable.sendOfferedKey(key, isSSK, needPubKey, uid, source, tag); } catch (NotConnectedException e) { // Too bad. } return true; }
/** * Key Derivation Function for client.dat: Use the database key as an HMAC key to an HMAC of the * key plus some constant plus the storeIdentifier. * * @return An encryption key, as byte[]. */ public byte[] getKeyForClientLayer() { byte[] full = new byte[databaseKey.length + CLIENT_LAYER.length]; int x = 0; System.arraycopy(databaseKey, 0, full, 0, databaseKey.length); x += databaseKey.length; System.arraycopy(CLIENT_LAYER, 0, full, x, CLIENT_LAYER.length); return HMAC.macWithSHA256(databaseKey, full); }
/** * Key Derivation Function for plugin stores: Use the database key as an HMAC key to an HMAC of * the key plus some constant plus the storeIdentifier. * * @param storeIdentifier The classname of the plugin, used as part of a filename. * @return An encryption key, as byte[]. */ public byte[] getPluginStoreKey(String storeIdentifier) { try { byte[] id = storeIdentifier.getBytes("UTF-8"); byte[] full = new byte[databaseKey.length + PLUGIN.length + id.length]; int x = 0; System.arraycopy(databaseKey, 0, full, 0, databaseKey.length); x += databaseKey.length; System.arraycopy(PLUGIN, 0, full, x, PLUGIN.length); x += PLUGIN.length; System.arraycopy(id, 0, full, x, id.length); return HMAC.macWithSHA256(databaseKey, full); } catch (UnsupportedEncodingException e) { throw new Error(e); } }