📄 protocoldecoderphe.java
字号:
byte[] sha1 = hasher.getDigest();
for (int i=0;i<decode.length;i++){
decode[i] ^= sha1[i];
}
synchronized( global_shared_secrets ){
shared_secret = (byte[])global_shared_secrets.get( new HashWrapper( decode ));
}
if ( shared_secret == null ){
throw( new IOException( "No matching shared secret" ));
}
// System.out.println( "inbound - using crypto secret " + ByteFormatter.encodeString( shared_secret ));
setupCrypto();
byte[] crypted = new byte[VC.length + 4 + 2];
read_buffer.get( crypted );
byte[] plain = read_cipher.update( crypted );
byte other_supported_protocols = plain[VC.length+3];
int common_protocols = my_supported_protocols & other_supported_protocols;
if (( common_protocols & CRYPTO_PLAIN )!= 0 ){
selected_protocol = CRYPTO_PLAIN;
}else if (( common_protocols & CRYPTO_XOR )!= 0 ){
selected_protocol = CRYPTO_XOR;
}else if (( common_protocols & CRYPTO_RC4 )!= 0 ){
selected_protocol = CRYPTO_RC4;
}else if (( common_protocols & CRYPTO_AES )!= 0 ){
selected_protocol = CRYPTO_AES;
}else{
throw( new IOException(
"No crypto protocol in common: mine = " +
Integer.toHexString((byte)my_supported_protocols) + ", theirs = " +
Integer.toHexString((byte)other_supported_protocols)));
}
int padding = (( plain[VC.length+4] & 0xff ) << 8 ) + ( plain[VC.length+5] & 0xff );
if ( padding > PADDING_MAX ){
throw( new IOException( "Invalid padding '" + padding + "'" ));
}
read_buffer = ByteBuffer.allocate( padding + 2 );
// skip the padding
protocol_substate = 3;
}else if ( protocol_substate == 3 ){
// ENCRYPT( len(IA)), ENCRYPT(IA)
read_buffer.flip();
byte[] data = new byte[read_buffer.remaining()];
read_buffer.get( data );
data = read_cipher.update( data );
int ia_len = 0xffff & ((( data[data.length-2] & 0xff ) << 8 ) + ( data[data.length-1] & 0xff ));
if ( ia_len > 65535 ){
throw( new IOException( "Invalid IA length '" + ia_len + "'" ));
}
initial_data_in_len = ia_len;
read_buffer = null;
protocol_state = PS_OUTBOUND_4;
break;
}
}
}else if ( protocol_state == PS_OUTBOUND_4 ){
// B->A: ENCRYPT(VC, crypto_select, len(padD), padD, // len(IB)), ENCRYPT(IB)
if ( write_buffer == null ){
int pad_max = getPaddingMax();
byte[] padding_b = getRandomPadding( pad_max/2 ); // half padding b sent here
byte[] padding_d = getZeroPadding( pad_max );
write_buffer = ByteBuffer.allocate( padding_b.length + VC.length + 4 + 2 + padding_d.length ); // + 2 + initial_data_out.length );
write_buffer.put( padding_b );
write_buffer.put( write_cipher.update( VC ));
write_buffer.put( write_cipher.update( new byte[]{ 0, 0, 0, selected_protocol }));
write_buffer.put( write_cipher.update( new byte[]{ (byte)(padding_d.length>>8),(byte)padding_d.length }));
write_buffer.put( write_cipher.update( padding_d ));
//write_buffer.put( write_cipher.update( new byte[]{ (byte)(initial_data_out.length>>8),(byte)initial_data_out.length }));
//write_buffer.put( write_cipher.update( initial_data_out ));
write_buffer.flip();
}
write( write_buffer );
if ( !write_buffer.hasRemaining()){
write_buffer = null;
handshakeComplete();
}
}else if ( protocol_state == PS_INBOUND_4 ){
// B->A: ENCRYPT(VC, crypto_select, len(padD), padD // , len(IB)), ENCRYPT(IB)
if ( read_buffer == null ){
read_buffer = ByteBuffer.allocate( VC.length + PADDING_MAX );
read_buffer.limit( VC.length );
padding_skip_marker = new byte[VC.length];
padding_skip_marker = read_cipher.update( padding_skip_marker );
protocol_substate = 1;
}
while( true ){
read( read_buffer );
if ( read_buffer.hasRemaining()){
break;
}
if ( protocol_substate == 1 ){
//skip up to marker
int limit = read_buffer.limit();
read_buffer.position( limit - VC.length );
boolean match = true;
for (int i=0;i<VC.length;i++){
if ( read_buffer.get() != padding_skip_marker[i] ){
match = false;
break;
}
}
if ( match ){
read_buffer = ByteBuffer.allocate( 4 + 2 );
protocol_substate = 2;
break;
}else{
if ( limit == read_buffer.capacity()){
throw( new IOException( "PHE skip to SHA1 marker failed" ));
}
read_buffer.limit( limit + 1 );
read_buffer.position( limit );
}
}else if ( protocol_substate == 2 ){
// ENCRYPT( crypto_select, len(padD))
read_buffer.flip();
byte[] crypted = new byte[4 + 2];
read_buffer.get( crypted );
byte[] plain = read_cipher.update( crypted );
selected_protocol = plain[3];
if (( selected_protocol & my_supported_protocols ) == 0 ){
throw( new IOException(
"Selected protocol has nothing in common: mine = " +
Integer.toHexString((byte)my_supported_protocols) + ", theirs = " +
Integer.toHexString((byte)selected_protocol)));
}
int pad_len = 0xffff&((( plain[4] & 0xff ) << 8 ) + ( plain[5] & 0xff ));
if ( pad_len > 65535 ){
throw( new IOException( "Invalid pad length '" + pad_len + "'" ));
}
read_buffer = ByteBuffer.allocate( pad_len ); // + 2 );
protocol_substate = 3;
}else if ( protocol_substate == 3 ){
read_buffer.flip();
byte[] data = new byte[read_buffer.remaining()];
read_buffer.get( data );
data = read_cipher.update( data );
handshakeComplete();
read_buffer = null;
break;
/*
int ib_len = 0xffff & ((( data[data.length-2] & 0xff ) << 8 ) + ( data[data.length-1] & 0xff ));
if ( ib_len > 65535 ){
throw( new IOException( "Invalid IB length '" + ib_len + "'" ));
}
read_buffer = ByteBuffer.allocate( ib_len );
protocol_substate = 4;
}else{
read_buffer.flip();
byte[] data = new byte[read_buffer.remaining()];
read_buffer.get( data );
initial_data_in = read_cipher.update( data );
handshakeComplete();
read_buffer = null;
break;
*/
}
}
}
if ( handshake_complete ){
transport.cancelReadSelects();
transport.cancelWriteSelects();
loop = false;
complete();
}else{
if ( read_buffer == null ){
transport.pauseReadSelects();
}else{
transport.resumeReadSelects();
loop = false;
}
if ( write_buffer == null ){
transport.pauseWriteSelects();
}else{
transport.resumeWriteSelects();
loop = false;
}
}
}
}catch( Throwable e ){
failed( e );
if ( e instanceof IOException ){
throw((IOException)e);
}else{
throw( new IOException( Debug.getNestedExceptionMessage(e)));
}
}finally{
process_mon.exit();
}
}
/*
**** OUTBOUND_1
A sends B odd/even byte + Ya + Pa
**** INBOUND_1
B receives Ya
B computes Yb
B computes S and HS
**** OUTBOUND_2
B sends A Yb + HS( "supported methods" + len(Pb)) + Pb
**** INBOUND_2
A receives Yb
A computes S and HS
A receives HS( "supported methods" + len(Pb)) and decrypts using HS
A skips len(Pb) random bytes
**** OUTBOUND_3
A sends SHA1(S) + HS( "selected method" + len(Pc)) + Pc + selectedCrypt( payload )
**** INBOUND_3
B skips Pa bytes until receives SHA1(S)
B decrypts "selected method" + len(Pc) and skips len(Pc) bytes to get to selectedCrypt( payload... )
B sends A selectedCrypt( payload... )
*/
/*
protected void
process()
throws IOException
{
try{
process_mon.enter();
if ( handshake_complete ){
Debug.out( "Handshake process already completed" );
return;
}
boolean loop = true;
while( loop ){
if ( protocol_state == PS_OUTBOUND_1 ){
if ( write_buffer == null ){
// A sends B odd/even Ya + Pa
byte[] padding = getPadding();
write_buffer = ByteBuffer.allocate( dh_public_key_bytes.length + padding.length );
write_buffer.put( dh_public_key_bytes );
write_buffer.put( padding );
write_buffer.flip();
}
write( write_buffer );
if ( !write_buffer.hasRemaining()){
write_buffer = null;
protocol_state = PS_INBOUND_2;
}
}else if ( protocol_state == PS_OUTBOUND_2 ){
// B sends A Yb + HS( "supported methods" + len(Pb)) + Pb
if ( write_buffer == null ){
byte[] padding = getPadding();
write_buffer = ByteBuffer.allocate( dh_public_key_bytes.length + 4 + 2 + padding.length );
write_buffer.put( dh_public_key_bytes );
// 4 bytes for my supported protocols
write_buffer.put( write_cipher.update( new byte[]{ 0, 0, 0, my_supported_protocols }));
write_buffer.put( write_cipher.update( new byte[]{ (byte)(padding.length>>8),(byte)padding.length }));
write_buffer.put( padding );
write_buffer.flip();
}
write( write_buffer );
if ( !write_buffer.hasRemaining()){
write_buffer = null;
protocol_state = PS_INBOUND_3;
}
}else if ( protocol_state == PS_OUTBOUND_3 ){
// A sends SHA1(S) + HS( "selected method" + len(Pc)) + Pc + selectedCrypt( payload )
if ( write_buffer == null ){
byte[] padding = getPadding();
write_buffer = ByteBuffer.allocate( 20 + 4 + 2 + padding.length );
write_buffer.put( sha1_secret_bytes );
write_buffer.put( write_cipher.update( new byte[]{ 0, 0, 0, selected_protocol }));
write_buffer.put( write_cipher.update( new byte[]{ (byte)(padding.length>>8),(byte)padding.length }));
write_buffer.put( padding );
write_buffer.flip();
}
write( write_buffer );
if ( !write_buffer.hasRemaining()){
write_buffer = null;
handshakeComplete();
}
}else if ( protocol_state == PS_INBOUND_1 ){
// B receives marker + Ya
read( read_buffer );
if ( !read_buffer.hasRemaining()){
read_buffer.flip();
byte[] other_dh_public_key_bytes = new byte[read_buffer.remaining()];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -