Unprotects an RTP Packet by decrypting the payload.

@param packet
RTP Packet to be unprotected
@return error code, 0 = success
2091
public int unprotect(RtpPacket packet) {
		if (txSessAuthKey == null) {
			// Only the tx session key is set at session start, rx is done when
			// 1st packet received
			log("unprotect() called out of session");
			return UNPROTECT_SESSION_NOT_STARTED;
		}
		if (packet == null) {
			logWarning("unprotect() called with null RtpPacket");
			return UNPROTECT_NULL_PACKET;
		}
		if (previousSSRC != packet.getSscr()) {
			previousSSRC = packet.getSscr();
			// reset indexes & Seq
			rxRoc = 0;
			rxSeq = packet.getSequenceNumber();
			replayWindow.removeAllElements();
			logWarning("New SSRC detected. Resetting SRTP replay protection");
		}
		if (!receivedFirst) {
			receivedFirst = true;
			rxSeq = packet.getSequenceNumber();
			if (VERBOSE) {
				log("unprotect() iRxSeq = " + rxSeq);
			}
			if (!rxSessionKeyDerivation()) {
				logWarning("unprotect() unable to create session keys");
				return UNPROTECT_ERROR_DECRYPTING;
			}
		}
		// First need to work out the implicit srtp sequence number,
		// see rfc3711 appendix A & section 3.3.1
		// Using same naming convention as in rfc for ROC estimate (v)
		// Needs to be done before authentication as v is used as part of auth
		long v;
		int seq = packet.getSequenceNumber();
		if (rxSeq < 0x8000) {
			if ((seq - rxSeq) > 0x8000) {
				v = rxRoc - 0x10000L;
			} else {
				v = rxRoc;
			}
		} else {
			if ((rxSeq - 0x8000) > seq) {
				v = rxRoc + 0x10000L;
			} else {
				v = rxRoc;
			}
		}

		long index = v + seq;
		if (SUPER_VERBOSE) {
			log("unprotect(), seq = " + seq);
			logBuffer("unprotect(), rcvd pkt = ", packet.getPacket());
		}
		if (isReplayedPacket(index)) {
			logWarning("Replayed packet received, sequence number=#" + seq
					+ ", index=" + index);
			return UNPROTECT_REPLAYED_PACKET;
		}

		// Now need to check authentication & remove auth bytes from payload
		int originalLen = packet.getPayloadLength();
		int newLen = originalLen - getHmacAuthSizeBytes();

		// we'll reduce the payload length but the auth-code will still be
		// present after the payload for comparison
		int pktAuthCodePos = packet.getHeaderLength() + newLen;
		packet.setPayloadLength(newLen);
		byte[] authCode = null;
		try {
			authCode = getAuthentication(packet, v, false); // iRxSessAuthKey);
		} catch (Throwable e) {
			logError("unprotect() error getting authCode EX: " + e);
			e.printStackTrace();
			return UNPROTECT_ERROR_DECRYPTING;
		}

		if (!platform.getUtils().equals(authCode, 0, packet.getPacket(),
				pktAuthCodePos, getHmacAuthSizeBytes())) {
			// Auth failed
			logWarning("unprotect() Authentication failed");
			logBuffer("authCode:", authCode);
			byte[] pktAuthCode = new byte[getHmacAuthSizeBytes()];
			System.arraycopy(packet.getPacket(), pktAuthCodePos, pktAuthCode,
					0, getHmacAuthSizeBytes());
			logBuffer("pktAuthCode:", pktAuthCode);
			logBuffer("iRxSessAuthKey:", rxSessAuthKey);
			log("v = " + Integer.toHexString((int) v) + " (" + v + ")");
			return UNPROTECT_INVALID_PACKET;
		}

		if (VERBOSE) {
			log("unprotect() -------- Authenticated OK --------");
		}

		// Authenticated, now unprotect the payload
		// Note the use of encryptIV() in transformPayload is correct
		// At 1st sight, might expect to use decrypt but unprotection consists
		// of XORing payload with an encrypted IV to obtain original payload
		// data

		if (!transformPayload(packet, v, seq, rxSessSaltKey, false)) {
			log("unprotect() transformPayload error, decryption failed");
			return UNPROTECT_ERROR_DECRYPTING;
		}

		// Payload now unprotected. Update the latest seq & ROC ready for next
		// packet
		if (v == rxRoc) {
			if (seq > rxSeq) {
				rxSeq = seq;
			}
		} else if (v == rxRoc + 0x10000L) {
			rxRoc += 0x10000L;
			rxSeq = seq;
		}

		if (SUPER_VERBOSE) {
			logBuffer("unprotect(), new packet - ", packet.getPacket());
		}
		return UNPROTECT_OK;
	}
31062
public static byte[] decipher(byte[] encrypted_bytes, String crypto_algorithm)
                    throws InvalidPasswordCipherException, UnsupportedCryptoAlgorithmException {

        if (crypto_algorithm == null) {
            logger.logp(Level.SEVERE, PasswordCipherUtil.class.getName(), "decipher", "PASSWORDUTIL_UNKNOWN_ALGORITHM",
                        new Object[] { "null", formatSupportedCryptoAlgorithms() });
            throw new UnsupportedCryptoAlgorithmException();
        }

        byte[] decrypted_bytes = null;

        if (AES.equalsIgnoreCase(crypto_algorithm)) {
            decrypted_bytes = aesDecipher(encrypted_bytes, decrypted_bytes);
        } else if (XOR.equalsIgnoreCase(crypto_algorithm)) {
            decrypted_bytes = xor(encrypted_bytes);
        } else if (HASH.equalsIgnoreCase(crypto_algorithm)) {
            throw new InvalidPasswordCipherException(MessageUtils.getMessage("PASSWORDUTIL_ERROR_UNSUPPORTED_OPERATION", crypto_algorithm));
        } else if (CUSTOM.equalsIgnoreCase(crypto_algorithm) || crypto_algorithm.startsWith(CUSTOM_COLON)) {

            CustomPasswordEncryption cpe = getCustomImpl();
            if (cpe != null) {
                int index = crypto_algorithm.indexOf(':');
                String keyAlias = null;

                if (index != -1) {
                    keyAlias = crypto_algorithm.substring(index + 1);
                }

                try {
                    decrypted_bytes = cpe.decrypt(new EncryptedInfo(encrypted_bytes, keyAlias));
                    if (logger.isLoggable(Level.FINE))
                        logger.fine("Successfully decrypted password using custom encryption plug point.");
                } catch (Exception e) {
                    logger.logp(Level.SEVERE, PasswordCipherUtil.class.getName(), "decipher", "PASSWORDUTIL_CUSTOM_DECRYPTION_ERROR", e);
                    throw (InvalidPasswordCipherException) new InvalidPasswordCipherException(e.getMessage()).initCause(e);
                }
            } else {
                logger.logp(Level.SEVERE, PasswordCipherUtil.class.getName(), "decipher", "PASSWORDUTIL_CUSTOM_SERVICE_DOES_NOT_EXIST");
                throw new UnsupportedCryptoAlgorithmException();
            }
        } else {
            logger.logp(Level.SEVERE, PasswordCipherUtil.class.getName(), "decipher", "PASSWORDUTIL_UNKNOWN_ALGORITHM", new Object[] { crypto_algorithm,
                                                                                                                                      formatSupportedCryptoAlgorithms() });
            throw new UnsupportedCryptoAlgorithmException();
        }

        if (decrypted_bytes == null) {
            throw new InvalidPasswordCipherException("The output is null.");
        }
        return decrypted_bytes;
    }
558288
public static byte[] decodeLines(final String text) {
       char[] buf = new char[text.length()];
       int pValue = 0;
       for (int ip = 0; ip < text.length(); ip++) {
           final char cValue = text.charAt(ip);
           if (cValue != ' ' && cValue != '\r' && cValue != '\n' && cValue != '\t') {
               buf[pValue++] = cValue;
           }
       }
       return decode(buf, 0, pValue);
   }
654064
public ByteBuffer encode(Packet packet, GroupContext groupContext, ChannelContext channelContext) {
        SimplePacket helloPacket  = (SimplePacket) packet;
        byte[] body = helloPacket.getBody();
        int bodyLen = 0;
        if(body != null){
            bodyLen = body.length;
        }

        //Bytebuffer总长度 = 消息头+消息体的长度
        int allLen = SimplePacket.HEADER_LENGTH+bodyLen;
        //创建新的Bytebuffer
        ByteBuffer buf = ByteBuffer.allocate(allLen);
        //设置字节序
        buf.order(groupContext.getByteOrder());
        //写入消息头
        buf.putInt(bodyLen);
        //写入消息体
        if(body != null){
            buf.put(body);
        }
        return buf;
    }
258450
public UnbindResp unbindResp(byte[] b) {
        UnbindResp resp = new UnbindResp();
        assignHeader(resp, b);
        return resp;
    }
1265332
@FFDCIgnore({ BadPaddingException.class, Exception.class })
    private final void decrypt() throws InvalidTokenException {
        byte[] tokenData;
        try {
            tokenData = LTPAKeyUtil.decrypt(encryptedBytes.clone(), sharedKey, cipher);

            checkTokenBytes(tokenData);
            String UTF8TokenString = toUTF8String(tokenData);
            String[] userFields = LTPATokenizer.parseToken(UTF8TokenString);
            Map<String, ArrayList<String>> attribs = LTPATokenizer.parseUserData(userFields[0]);
            userData = new UserData(attribs);

            String tokenString = toSimpleString(tokenData);
            String[] fields = LTPATokenizer.parseToken(tokenString);
            String[] expirationArray = userData.getAttributes(AttributeNameConstants.WSTOKEN_EXPIRATION);
            if (expirationArray != null && expirationArray[expirationArray.length - 1] != null) {
                // the new expiration value inside the signature
                expirationInMilliseconds = Long.parseLong(expirationArray[expirationArray.length - 1]);
            } else {
                // the old expiration value outside of the signature
                expirationInMilliseconds = Long.parseLong(fields[1]);
            }

            byte[] signature = Base64Coder.base64Decode(Base64Coder.getBytes(fields[2]));
            setSignature(signature);
        } catch (BadPaddingException e) {
            if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) {
                Tr.event(this, tc, "Caught BadPaddingException while decrypting token, this is only a critical problem if decryption should have worked.", e);
            }
            throw new InvalidTokenException(e.getMessage(), e);
        } catch (Exception e) {
            if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) {
                Tr.event(this, tc, "Error decrypting; " + e);
            }
            throw new InvalidTokenException(e.getMessage(), e);
        }
    }
856101
public IoBuffer encodePacket(Packet packet) {
        IoBuffer out = null;
        Header header = packet.getHeader();
        int channelId = header.getChannelId();
        //log.trace("Channel id: {}", channelId);
        IRTMPEvent message = packet.getMessage();
        if (message instanceof ChunkSize) {
            ChunkSize chunkSizeMsg = (ChunkSize) message;
            ((RTMPConnection) Red5.getConnectionLocal()).getState().setWriteChunkSize(chunkSizeMsg.getSize());
        }
        // normally the message is expected not to be dropped
        if (!dropMessage(channelId, message)) {
            //log.trace("Header time: {} message timestamp: {}", header.getTimer(), message.getTimestamp());
            IoBuffer data = encodeMessage(header, message);
            if (data != null) {
                RTMP rtmp = ((RTMPConnection) Red5.getConnectionLocal()).getState();
                // set last write packet
                rtmp.setLastWritePacket(channelId, packet);
                // ensure we're at the beginning
                if (data.position() != 0) {
                    data.flip();
                } else {
                    data.rewind();
                }
                // length of the data to be chunked
                int dataLen = data.limit();
                header.setSize(dataLen);
                //if (log.isTraceEnabled()) {
                    //log.trace("Message: {}", data);
                //}
                // chunk size for writing
                int chunkSize = rtmp.getWriteChunkSize();
                // number of chunks to write
                int numChunks = (int) Math.ceil(dataLen / (float) chunkSize);
                // get last header
                Header lastHeader = rtmp.getLastWriteHeader(channelId);
                if (log.isTraceEnabled()) {
                    log.trace("Channel id: {} chunkSize: {}", channelId, chunkSize);
                }
                // attempt to properly guess the size of the buffer we'll need
                int bufSize = dataLen + 18 + (numChunks * 2);
                //log.trace("Allocated buffer size: {}", bufSize);
                out = IoBuffer.allocate(bufSize, false);
                out.setAutoExpand(true);
                do {
                    // encode the header
                    encodeHeader(header, lastHeader, out);
                    // write a chunk
                    byte[] buf = new byte[Math.min(chunkSize, data.remaining())];
                    data.get(buf);
                    //log.trace("Buffer: {}", Hex.encodeHexString(buf));
                    out.put(buf);
                    // move header over to last header
                    lastHeader = header.clone();
                } while (data.hasRemaining());
                // collapse the time stamps on the last header after decode is complete
                lastHeader.setTimerBase(lastHeader.getTimer());
                // clear the delta
                lastHeader.setTimerDelta(0);
                // set last write header
                rtmp.setLastWriteHeader(channelId, lastHeader);
                data.free();
                out.flip();
                data = null;
            }
        }
        message.release();
        return out;
    }
516012
@Override
  public String decrypt(String cipherText) {
    this.decryptionLock.lock();
    try{
      String decryptedValue = null;
      try {
        byte[] bytes = Base64.getDecoder().decode(cipherText);
        decryptedValue = new String(decryptCipher.doFinal(bytes), charset);
      } catch (UnsupportedEncodingException | IllegalBlockSizeException | BadPaddingException e) {
        logger.error("DefaultAESCBCCipher failed to decrypt text", e);
        throw new JsonDBException("DefaultAESCBCCipher failed to decrypt text", e);
      }
      return decryptedValue;
    } finally{
      this.decryptionLock.unlock();
    }
  }
947175
public String encrypt(final String pText) throws GeneralSecurityException {
        byte[] clearBytes = pText.getBytes(Charset.forName("UTF-8"));
        byte[] salt = getSalt(SALT_SIZE);

        Cipher cipher = createCipher(salt, Cipher.ENCRYPT_MODE);
        byte[] encryptedBytes = cipher.doFinal(clearBytes);
        int len = encryptedBytes.length;

        byte padLen = (byte) (CHUNK_SIZE - (SALT_SIZE + len + 1) % CHUNK_SIZE);
        int totalLen = SALT_SIZE + len + padLen + 1;

        byte[] allEncryptedBytes = getSalt(totalLen);
        System.arraycopy(salt, 0, allEncryptedBytes, 0, SALT_SIZE);
        allEncryptedBytes[SALT_SIZE] = padLen;
        System.arraycopy(encryptedBytes, 0, allEncryptedBytes, SALT_SIZE + 1, len);

        return Base64Util.encode(allEncryptedBytes);
    }
386858
public static AbstractPacket unserializeFrom( RawDataBuffer in )
    {
        byte type = in.readByte(); 
        AbstractPacket packet = PacketType.createInstance(type);
        packet.unserializeFrom(in);
        
        return packet;
    }
30928
public byte[] decrypt(byte[] msg) {
        if (msg == null) return null;
        try {
            Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM_IMPLEMENTATION);
            SecretKeySpec key = new SecretKeySpec(getMd5(), ENCRYPTION_ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(getIv());
            cipher.init(Cipher.DECRYPT_MODE, key, iv);
            return cipher.doFinal(msg);
        } catch (Exception e) {
            return null;
        }
    }
1002238
public byte[] unwrap(byte []inBuf, int off, int len, MessageProp prop)
        throws GSSException {

        checkContext();

        logger.debug("enter unwrap");

        byte [] token = null;

        /*
         * see if the token is a straight SSL packet or
         * one of ours made by wrap using get_mic
         */
        if (inBuf[off] == GSI_WRAP &&
            inBuf[off+1] == 3 &&
            inBuf[off+2] == 0) {
            throw new GSSException(GSSException.UNAVAILABLE);
/*DEL

            int micLen = SSLUtil.toShort(inBuf[off+3], inBuf[off+4]);
            int msgLen = len - 5 - micLen;

            if (micLen > len-5 || msgLen < 0) {
                throw new GSSException(GSSException.DEFECTIVE_TOKEN);
            }

            verifyMIC(inBuf, off+5, micLen,
                      inBuf, off+5+micLen, msgLen,
                      null);

            if (prop != null) {
                prop.setPrivacy(false);
                prop.setQOP(GSSConstants.GSI_BIG);
            }

            // extract the data
            token = new byte[msgLen];
            System.arraycopy(inBuf, off+5+micLen, token, 0, msgLen);
*/

        } else {
            token = unwrap(inBuf, off, len);

            if (prop != null) {
                prop.setPrivacy(this.encryption);
                prop.setQOP(0);
            }
        }

        logger.debug("exit unwrap");
        return token;
    }
589727
private String unprotectPayload(String payload) throws IOException {
        try {
            JWEObject jweObject = JWEObject.deserialize(MessageSecurityHelper.base64UrltoString(payload));
            JWEHeader jweHeader = jweObject.jweHeader();

            if (!clientEncryptionKey.kid().equals(jweHeader.kid()) || !jweHeader.alg().equals("RSA-OAEP")
                    || !jweHeader.enc().equals("A128CBC-HS256")) {
                throw new IOException("Invalid protected response");
            }

            byte[] key = MessageSecurityHelper.base64UrltoByteArray(jweObject.encryptedKey());

            RsaKey clientEncryptionRsaKey = new RsaKey(clientEncryptionKey.kid(), clientEncryptionKey.toRSA(true));
            byte[] aesKeyBytes = clientEncryptionRsaKey.decryptAsync(key, null, null, null, "RSA-OAEP").get();

            SymmetricKey aesKey = new SymmetricKey(UUID.randomUUID().toString(), aesKeyBytes);
            byte[] result = aesKey.decryptAsync(MessageSecurityHelper.base64UrltoByteArray(jweObject.cipherText()),
                    MessageSecurityHelper.base64UrltoByteArray(jweObject.iv()),
                    jweObject.originalProtected().getBytes(MESSAGE_ENCODING),
                    MessageSecurityHelper.base64UrltoByteArray(jweObject.tag()), "A128CBC-HS256").get();

            return new String(result, MESSAGE_ENCODING);
        } catch (ExecutionException e) {
            // unexpected;
            return null;
        } catch (InterruptedException e) {
            // unexpected;
            return null;
        } catch (NoSuchAlgorithmException e) {
            // unexpected;
            return null;
        }
    }
200350
final public function decode(& $packet_data, $remaining_length, & $payload_pos)
    {
        $cmd = Utility::ParseCommand(ord($packet_data[0]));
        $message_type = $cmd['message_type'];
        if ($this->message->getMessageType() != $message_type) {
            throw new Exception('Unexpected Control Packet Type');
        }

        $flags        = $cmd['flags'];
        $this->setFlags($flags);

        $pos = 1;
        $rl_len = strlen(($this->remaining_length_bytes = Utility::EncodeLength($remaining_length)));
        $pos += $rl_len;

        $this->remaining_length = $remaining_length;
        $this->decodeVariableHeader($packet_data, $pos);
        $payload_pos = $pos;
    }
464907
function(packet) {
        packet.status = packet.readInt(8);
        packet.oskType = packet.readInt(12);
        // TODO: for some reason, the way we decode it
        //  gives an extra 16 bytes of garbage here. We
        //  should really figure out why that's happening
        //  ... and fix it
        if (packet.buf.length > 36) {
            packet.max = packet.readInt(32);
            packet.initial = packet.readString(36);
        }
        this.emit('start_osk_result', packet);
    }
643920
@Override
    public void write(final Packet packet) {
        log.debug("write - state: {}", state);
        if (closing || state.getState() == RTMP.STATE_DISCONNECTED) {
            // Connection is being closed, don't send any new packets
            return;
        }
        IoBuffer data;
        try {
            Red5.setConnectionLocal(this);
            data = encoder.encode(packet);
        } catch (Exception e) {
            log.error("Could not encode message {}", packet, e);
            return;
        } finally {
            Red5.setConnectionLocal(null);
        }

        if (data != null) {
            // Mark packet as being written
            writingMessage(packet);
            //add to pending
            pendingMessages.add(new PendingData(data, packet));
        } else {
            log.info("Response buffer was null after encoding");
        }
    }
44873
public boolean useEncryption() {
        switch (handshakeType) {
            case RTMPConnection.RTMP_ENCRYPTED:
            case RTMPConnection.RTMP_ENCRYPTED_XTEA:
            case RTMPConnection.RTMP_ENCRYPTED_BLOWFISH:
                return true;
        }
        return false;
    }