@Override public void send(Map<String, Object> data) throws IOException { checkConnected(); byte[] packed = mySessionKey.etaEncrypt(Boss.pack(data)); if (!connection.isClosed()) connection.sendParams("block", packed); else throw new EOFException("connection closed"); }
/** * All packets data ({@link Packet#payload}) of type {@link PacketTypes#DATA} * must be encrypted with sessionKey ({@link SymmetricKey}). * This method implements encryption procedure for it. * @param sessionKey key for encryption * @param payload data to encrypt * @return encrypted data, ready for sending to network */ private byte[] preparePayloadForSession(SymmetricKey sessionKey, byte[] payload) { try { byte[] payloadWithRandomChunk = new byte[payload.length + 2]; System.arraycopy(payload, 0, payloadWithRandomChunk, 0, payload.length); System.arraycopy(Bytes.random(2).toArray(), 0, payloadWithRandomChunk, payload.length, 2); byte[] encryptedPayload = new SymmetricKey(sessionKey.getKey()).etaEncrypt(payloadWithRandomChunk); byte[] crc32 = new Crc32().digest(encryptedPayload); byte[] dataToSend = new byte[encryptedPayload.length + crc32.length]; System.arraycopy(encryptedPayload, 0, dataToSend, 0, encryptedPayload.length); System.arraycopy(crc32, 0, dataToSend, encryptedPayload.length, crc32.length); return dataToSend; } catch (EncryptionError e) { callErrorCallbacks("(preparePayloadForSession) EncryptionError: " + e); return payload; } }
data.put("data", mainKey.etaEncrypt(packedPrivate));
/** * ACK packets are used only for respond to DATA packets. Retransmission of handshake's packet types stops on each * next handshake step. But last step need to be ACK-ed. For this used {@link PacketTypes#SESSION_ACK} packet. * @param session is {@link Session} in which sending is. * @throws EncryptionError */ private void sendSessionAck(Session session) throws EncryptionError { report(logLabel, ()->"send session_ack to "+session.remoteNodeInfo.getNumber(), VerboseLevel.BASE); Packet packet = new Packet(0, myNodeInfo.getNumber(), session.remoteNodeInfo.getNumber(), PacketTypes.SESSION_ACK, new SymmetricKey(session.sessionKey.getKey()).etaEncrypt(Do.randomBytes(32))); sendPacket(session.remoteNodeInfo, packet); }
/** * Each adapter will try to send blocks until have got special {@link Packet} with type {@link PacketTypes#ACK}, * that means receiver have got block. So when we got packet and all is ok - call this method. * @param sessionReader is {@link SessionReader} in which sending is. * @param packetId is id of packet we have got. */ private void sendAck(SessionReader sessionReader, Integer packetId) throws EncryptionError { report(logLabel, ()->"send ack to "+sessionReader.remoteNodeInfo.getNumber(), VerboseLevel.DETAILED); Packet packet = new Packet(0, myNodeInfo.getNumber(), sessionReader.remoteNodeInfo.getNumber(), PacketTypes.ACK, new SymmetricKey(sessionReader.sessionKey.getKey()).etaEncrypt(Boss.pack(packetId))); sendPacket(sessionReader.remoteNodeInfo, packet); }
@Test public void etaEncrypt() throws Exception { SymmetricKey k = new SymmetricKey(); byte[] plainText = "Hello, world!".getBytes(); byte[] cipherText = k.etaEncrypt(plainText); // Bytes.dump(cipherText); assertEquals(16 + 32 + plainText.length, cipherText.length); byte[] decryptedText = k.etaDecrypt(cipherText); assertArrayEquals(plainText, decryptedText); exception.expect(SymmetricKey.AuthenticationFailed.class); cipherText[19] += 1; k.etaDecrypt(cipherText); }