package net.i2p.data.i2np; import net.i2p.I2PAppContext; import net.i2p.data.DataHelper; import net.i2p.data.Hash; import net.i2p.data.SessionKey; //import net.i2p.util.Log; /** * Class that creates an encrypted tunnel build message record. * * The reply record is the same size as the request record (528 bytes). * * When decrypted: * *<pre> * Bytes 0-31 contain the hash of bytes 32-527 * Bytes 32-526 contain random data. * Byte 527 contains the reply. *</pre> */ public class BuildResponseRecord { /** * Create a new encrypted response * * @param status the response 0-255 * @param replyIV 16 bytes * @param responseMessageId unused except for debugging * @return a 528-byte response record */ public static EncryptedBuildRecord create(I2PAppContext ctx, int status, SessionKey replyKey, byte replyIV[], long responseMessageId) { //Log log = ctx.logManager().getLog(BuildResponseRecord.class); byte rv[] = new byte[TunnelBuildReplyMessage.RECORD_SIZE]; ctx.random().nextBytes(rv, Hash.HASH_LENGTH, TunnelBuildReplyMessage.RECORD_SIZE - Hash.HASH_LENGTH - 1); DataHelper.toLong(rv, TunnelBuildMessage.RECORD_SIZE-1, 1, status); // rv = AES(SHA256(padding+status) + padding + status, replyKey, replyIV) ctx.sha().calculateHash(rv, Hash.HASH_LENGTH, rv.length - Hash.HASH_LENGTH, rv, 0); //if (log.shouldLog(Log.DEBUG)) // log.debug(responseMessageId + ": before encrypt: " + Base64.encode(rv, 0, 128) + " with " + replyKey.toBase64() + "/" + Base64.encode(replyIV)); ctx.aes().encrypt(rv, 0, rv, 0, replyKey, replyIV, rv.length); //if (log.shouldLog(Log.DEBUG)) // log.debug(responseMessageId + ": after encrypt: " + Base64.encode(rv, 0, 128)); return new EncryptedBuildRecord(rv); } }