package tor;
/*
Tor Research Framework - easy to use tor client library/framework
Copyright (C) 2014 Dr Gareth Owen <drgowen@gmail.com>
www.ghowen.me / github.com/drgowen/tor-research-framework
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import tor.util.TorCircuitException;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.util.Arrays;
public class TorHop {
final static Logger log = LogManager.getLogger();
byte[] kh = new byte[TorCrypto.HASH_LEN], df = new byte[TorCrypto.HASH_LEN], db = new byte[TorCrypto.HASH_LEN];
byte[] kf = new byte[TorCrypto.KEY_LEN], kb = new byte[TorCrypto.KEY_LEN];
public MessageDigest df_md, db_md;
Cipher encf, encb;
OnionRouter router;
/**
* Creates TorHop object taking derived key data and calculating keys
*
* @param kdf Derived key data from created/extended cell
* @param _kh KH for verification of correct KDF
* @param _r Router which this hop represents
*/
public TorHop(byte kdf[], byte _kh[], OnionRouter _r) throws TorCircuitException {
router = _r;
ByteBuffer buf = ByteBuffer.wrap(kdf);
buf.get(kh);
buf.get(df);
buf.get(db);
buf.get(kf);
buf.get(kb);
try {
df_md = MessageDigest.getInstance("SHA-1");
df_md.update(df);
db_md = MessageDigest.getInstance("SHA-1");
db_md.update(db);
IvParameterSpec ivSpec = new IvParameterSpec(new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
SecretKeySpec keysp = new SecretKeySpec(kf, "AES");
encf = Cipher.getInstance("AES/CTR/NoPadding");
encf.init(Cipher.ENCRYPT_MODE, keysp, ivSpec);
keysp = new SecretKeySpec(kb, "AES");
encb = Cipher.getInstance("AES/CTR/NoPadding");
ivSpec = new IvParameterSpec(new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
encb.init(Cipher.DECRYPT_MODE, keysp, ivSpec);
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
}
if (!Arrays.equals(_kh, kh))
log.error("hop key setup failed to router: " + router);
log.debug("Hop added " + router);
}
@Override
public String toString() {
return "TorHop{" +
"router=" + router +
'}';
}
public byte[] encrypt(byte[] in) {
return encf.update(in);
}
protected byte[] decrypt(byte[] in) {
return encb.update(in);
}
}