public DigestMD5PrivacyIoFilterCodec(IoSession session) { super(session); String encoding = (String) session.getAttribute(AuthDigestMD5Command.ENCODING); try { AuthDigestMD5IoFilter.computePrivacyKeys(session, encoding, false); } catch (Exception e) { e.printStackTrace(); } encCipher = (Cipher) session.getAttribute(AuthDigestMD5IoFilter.ENCODING_CIPHER); decCipher = (Cipher) session.getAttribute(AuthDigestMD5IoFilter.DECODING_CIPHER); }
public void wrap(NextFilter nextFilter, WriteRequest writeRequest, IoBuffer buf) throws AuthException { int start = buf.position(); int len = buf.remaining() - LINE_TERMINATOR.length; if (len == 0) throw new AuthException("Decryption failed"); // HMAC(Ki, {SeqNum, msg})[0..9] byte[] originalMessage = new byte[len]; buf.get(originalMessage); byte[] mac = AuthDigestMD5IoFilter.computeMACBlock(session, originalMessage, false); // Calculate padding int bs = encCipher.getBlockSize(); byte[] padding; if (bs > 1) { int pad = bs - ((len + 10) % bs); // add 10 for HMAC[0..9] padding = new byte[pad]; for (int i = 0; i < pad; i++) padding[i] = (byte) pad; } else padding = EMPTY_BYTE_ARRAY; byte[] toBeEncrypted = new byte[len + padding.length + 10]; // {msg, pad, HMAC(Ki, {SeqNum, msg}[0..9])} System.arraycopy(originalMessage, start, toBeEncrypted, 0, len); System.arraycopy(padding, 0, toBeEncrypted, len, padding.length); System.arraycopy(mac, 0, toBeEncrypted, len + padding.length, 10); // CIPHER(Kc, {msg, pad, HMAC(Ki, {SeqNum, msg}[0..9])}) byte[] cipherBlock; try { // Do CBC (chaining) across packets cipherBlock = encCipher.update(toBeEncrypted); // update() can return null if (cipherBlock == null) throw new IllegalBlockSizeException("" + toBeEncrypted.length); } catch (IllegalBlockSizeException e) { throw new AuthException("Invalid block size for cipher", e); } IoBuffer out = IoBuffer.allocate(cipherBlock.length + 2 + 4 + LINE_TERMINATOR.length); out.put(cipherBlock); out.put(mac, 10, 6); // messageType & sequenceNum out.put(LINE_TERMINATOR); out.flip(); if (out.limit() > ((Integer) session.getAttribute(AuthDigestMD5Command.CLIENT_MAXBUF)).intValue()) throw new AuthException("Data exceeds client maxbuf capability"); nextFilter.filterWrite(session, new DefaultWriteRequest(out, writeRequest.getFuture())); }
public void unwrap(NextFilter nextFilter, IoBuffer buf) { try { int len = buf.remaining(); if (len == 0) throw new AuthException("Decryption failed"); byte[] encryptedMsg = new byte[len - 6]; byte[] msgType = new byte[2]; byte[] seqNum = new byte[4]; // Get cipherMsg; msgType; sequenceNum buf.get(encryptedMsg); buf.get(msgType); buf.get(seqNum); // Decrypt message - CIPHER(Kc, {msg, pad, HMAC(Ki, {SeqNum, msg}[0..9])}) byte[] decryptedMsg; try { // Do CBC (chaining) across packets decryptedMsg = decCipher.update(encryptedMsg); // update() can return null if (decryptedMsg == null) throw new IllegalBlockSizeException("" + encryptedMsg.length); } catch (IllegalBlockSizeException e) { throw new AuthException("Illegal block sizes used with chosen cipher", e); } byte[] msgWithPadding = new byte[decryptedMsg.length - 10]; byte[] mac = new byte[10]; System.arraycopy(decryptedMsg, 0, msgWithPadding, 0, msgWithPadding.length); System.arraycopy(decryptedMsg, msgWithPadding.length, mac, 0, 10); int msgLength = msgWithPadding.length; int blockSize = decCipher.getBlockSize(); if (blockSize > 1) { // get value of last octet of the byte array msgLength -= (int) msgWithPadding[msgWithPadding.length - 1]; if (msgLength < 0) // Discard message and do not increment sequence number throw new AuthException("Decryption failed"); } byte[] msg = new byte[msgLength]; System.arraycopy(msgWithPadding, 0, msg, 0, msgLength); // Re-calculate MAC to ensure integrity byte[] expectedMac = AuthDigestMD5IoFilter.computeMACBlock(session, msg, true); byte[] fullMac = new byte[16]; System.arraycopy(mac, 0, fullMac, 0, 10); System.arraycopy(msgType, 0, fullMac, 10, 2); System.arraycopy(seqNum, 0, fullMac, 12, 4); if (isValidMAC(fullMac, expectedMac)) { IoBuffer out = IoBuffer.allocate(msgLength + LINE_TERMINATOR.length); out.put(msg); out.put(LINE_TERMINATOR); out.flip(); nextFilter.messageReceived(session, out); } } catch (Exception ex) { log.debug(ex.getMessage()); nextFilter.messageReceived(session, "\r\n"); } if (session instanceof AbstractIoSession) ((AbstractIoSession) session).increaseReadMessages(System.currentTimeMillis()); }