⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 protocoldecoderphe.java

📁 这是一个基于java编写的torrent的P2P源码
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
	        DHPublicKey	dh_public_key = (DHPublicKey)key_pair.getPublic();
	        
	        BigInteger	dh_y = dh_public_key.getY();
	        
	        dh_public_key_bytes = bigIntegerToBytes( dh_y, DH_SIZE_BYTES );
	        
		}catch( Throwable e ){
			
			throw( new IOException( Debug.getNestedExceptionMessage(e)));
		}
	}
	
	protected void
	completeDH(
		byte[]	buffer )
	
		throws IOException
	{
		try{			
	        BigInteger	other_dh_y = bytesToBigInteger( buffer, 0, DH_SIZE_BYTES );
	        
	        KeyFactory dh_key_factory = KeyFactory.getInstance("DH");
	        	    
		    PublicKey other_public_key = dh_key_factory.generatePublic( new DHPublicKeySpec( other_dh_y, DH_P_BI, DH_G_BI ));
	        		
		    key_agreement.doPhase( other_public_key, true );
		    
		    secret_bytes = key_agreement.generateSecret();
			    
		    adapter.gotSecret( secret_bytes );
		    
		    // System.out.println( "secret = " + ByteFormatter.encodeString( secret_bytes ));
		    
		}catch( Throwable e ){
			
			throw( new IOException( Debug.getNestedExceptionMessage(e)));
		}
	}
	
	protected void
	setupCrypto()
	
		throws IOException
	{
		try{
		    //"HASH('keyA', S, SKEY)" if you're A
		    //"HASH('keyB', S, SKEY)" if you're B

		    SHA1Hasher	hasher = new SHA1Hasher();
		    
		    hasher.update( KEYA_IV );
		    hasher.update( secret_bytes );
		    hasher.update( shared_secret );
		    	
		    byte[]	a_key = hasher.getDigest();
		    
		    hasher = new SHA1Hasher();
		    
		    hasher.update( KEYB_IV );
		    hasher.update( secret_bytes );
		    hasher.update( shared_secret );
		    	
		    byte[]	b_key = hasher.getDigest();
		    
		    SecretKeySpec	secret_key_spec_a = new SecretKeySpec( a_key, RC4_STREAM_ALG );
		        
		    SecretKeySpec	secret_key_spec_b = new SecretKeySpec( b_key, RC4_STREAM_ALG );
		        	        
		    write_cipher 	= new TransportCipher( RC4_STREAM_CIPHER, Cipher.ENCRYPT_MODE, outbound?secret_key_spec_a:secret_key_spec_b );
			    
		    read_cipher 	= new TransportCipher( RC4_STREAM_CIPHER, Cipher.DECRYPT_MODE, outbound?secret_key_spec_b:secret_key_spec_a );
		    
		}catch( Throwable e ){
			
			e.printStackTrace();
			
			throw( new IOException( Debug.getNestedExceptionMessage(e)));
		}
	}
	
	/*
	protected void
	completeDH(
		byte[]	buffer )
	
		throws IOException
	{
		try{			
	        BigInteger	other_dh_y = bytesToBigInteger( buffer, 0, DH_SIZE_BYTES );
	        
	        KeyFactory dh_key_factory = KeyFactory.getInstance("DH");
	        	    
		    PublicKey other_public_key = dh_key_factory.generatePublic( new DHPublicKeySpec( other_dh_y, DH_P_BI, DH_G_BI ));
	        		
		    key_agreement.doPhase( other_public_key, true );
		    
		    byte[]	secret_bytes_64 = key_agreement.generateSecret();
	
		    	// we only want the first 32 bytes of the secret
		    
		    secret_bytes = new byte[32];
		    
		    System.arraycopy( secret_bytes_64, 0, secret_bytes, 0, 32 );
		    
		    sha1_secret_bytes	= new SHA1Simple().calculateHash( secret_bytes );
		    		    	
		    SecretKeySpec	secret_key_spec_a = new SecretKeySpec( secret_bytes, 0, RC4_STREAM_KEY_SIZE_BYTES, RC4_STREAM_ALG );
		        
		    SecretKeySpec	secret_key_spec_b = new SecretKeySpec( secret_bytes, 16, RC4_STREAM_KEY_SIZE_BYTES, RC4_STREAM_ALG );
		        	        
		    write_cipher 	= new TCPTransportCipher( RC4_STREAM_CIPHER, Cipher.ENCRYPT_MODE, outbound?secret_key_spec_a:secret_key_spec_b );
			    
		    read_cipher 	= new TCPTransportCipher( RC4_STREAM_CIPHER, Cipher.DECRYPT_MODE, outbound?secret_key_spec_b:secret_key_spec_a );
		    
		}catch( Throwable e ){
			
			throw( new IOException( Debug.getNestedExceptionMessage(e)));
		}
	}
	*/
	
	protected void
	handshakeComplete()
	
		throws IOException
	{		
		if ( selected_protocol == CRYPTO_PLAIN ){
			
			filter = new TransportHelperFilterTransparent( transport, true );
									
		}else if ( selected_protocol == CRYPTO_XOR ){
		
			filter = new TransportHelperFilterStreamXOR( transport, secret_bytes );
						
		}else if ( selected_protocol == CRYPTO_RC4 ){
		
			filter = new TransportHelperFilterStreamCipher( 
						transport,
						read_cipher,
						write_cipher );

			/*
		}else if ( selected_protocol == CRYPTO_AES ){
			
			try{
		        SecretKeySpec	secret_key_spec = new SecretKeySpec( secret_bytes, 32, AES_STREAM_KEY_SIZE_BYTES, AES_STREAM_ALG );
			        		        
		        AlgorithmParameterSpec	spec = 	new IvParameterSpec( secret_bytes, 48, AES_STREAM_KEY_SIZE_BYTES );
		        
		        write_cipher 	= new TCPTransportCipher( AES_STREAM_CIPHER, Cipher.ENCRYPT_MODE, secret_key_spec, spec );
				    
		        read_cipher 	= new TCPTransportCipher( AES_STREAM_CIPHER, Cipher.DECRYPT_MODE, secret_key_spec, spec );
		        
				filter = new TCPTransportHelperFilterStreamCipher( 
						helper,
						read_cipher,
						write_cipher );
				
			}catch( Throwable e ){
				
				throw( new IOException( "AES crypto init failed: " + Debug.getNestedExceptionMessage(e)));
			}
		*/
		
		
		}else{
			
			throw( new IOException( "Invalid selected protocol '" + selected_protocol + "'" ));
		}	
			
		if ( selected_protocol != CRYPTO_RC4 ){
			
			filter = 
				new TransportHelperFilterSwitcher(
					 new TransportHelperFilterStreamCipher( transport, read_cipher,	write_cipher ),
					 filter,
					 initial_data_in_len,
					 0 );	// any initial data out is dealt with entirely during cryto phase
		}
		
		handshake_complete	= true;
	}
	
	
	/*
	  		X_1
	  		
	  	A->B: Diffie Hellman Ya, PadA
	  	
	  		X_2
	  		
		B->A: Diffie Hellman Yb, PadB
		
			X_3
			
		A->B: HASH('req1', S), HASH('req2', SKEY)^HASH('req3', S), ENCRYPT(VC, crypto_provide, len(PadC), PadC, len(IA)), ENCRYPT(IA)
		
			X_4
			
		B->A: ENCRYPT(VC, crypto_select, len(padD), padD ) // , len(IB)), ENCRYPT(IB)
	*/

	
	protected void
	process()
	
		throws IOException
	{
		try{
			process_mon.enter();
			
			if ( handshake_complete ){
				
				Debug.out( "Handshake process already completed" );
				
				return;
			}
			
			boolean	loop = true;
		
			while( loop ){
					
				// System.out.println( this + ":" + (outbound?"out: ":"in : ") + protocol_state + "/" + protocol_substate + ": r " + bytes_read + " - " + read_buffer + ", w " + bytes_written + " - " + write_buffer );
				
				if ( protocol_state == PS_OUTBOUND_1 ){
					
					if ( write_buffer == null ){
						
							// A sends B Ya + Pa
						
						byte[]	padding_a = getRandomPadding(getPaddingMax()/2);	// note that /2 also used in calculating max initial packet size above									
						
						write_buffer = ByteBuffer.allocate( dh_public_key_bytes.length + padding_a.length );
												
						write_buffer.put( dh_public_key_bytes );
						
						write_buffer.put( padding_a );
						
						write_buffer.flip();
					}
					
					write( write_buffer );
						
					if ( !write_buffer.hasRemaining()){
					
						write_buffer	= null;
					
						protocol_state	= PS_INBOUND_2;
					}
	
				}else if ( protocol_state == PS_INBOUND_1 ){
					
						// B receives Ya 
	
					read( read_buffer );
						
					if ( !read_buffer.hasRemaining()){
											
						read_buffer.flip();
						
						byte[] other_dh_public_key_bytes = new byte[read_buffer.remaining()];
						
						read_buffer.get( other_dh_public_key_bytes );
							
						completeDH( other_dh_public_key_bytes );
						
				        read_buffer	= null;
				        		        
						protocol_state	= PS_OUTBOUND_2;
					}
					
				}else if ( protocol_state == PS_OUTBOUND_2 ){
					
						// B->A: Yb PadB

					if ( write_buffer == null ){
						
						byte[]	padding_b = getRandomPadding( getPaddingMax()/2 );
						
						write_buffer = ByteBuffer.allocate( dh_public_key_bytes.length + padding_b.length );
						
						write_buffer.put( dh_public_key_bytes );

						write_buffer.put( padding_b );
						
						write_buffer.flip();
					}
					
					write( write_buffer );
					
					if ( !write_buffer.hasRemaining()){
					
						write_buffer	= null;
					
						protocol_state	= PS_INBOUND_3;
					}
					
				}else if ( protocol_state == PS_INBOUND_2 ){
					
						// A receives: Yb
						
					if ( read_buffer == null ){
												
						read_buffer = ByteBuffer.allocate( dh_public_key_bytes.length );
					}					
						
					read( read_buffer );

					if ( !read_buffer.hasRemaining()){
						
						read_buffer.flip();
						
						byte[] other_dh_public_key_bytes = new byte[read_buffer.remaining()];
						
						read_buffer.get( other_dh_public_key_bytes );
							
						completeDH( other_dh_public_key_bytes );
						
							// A initiates SKEY so we can now set up crypto
						
						setupCrypto();
						
				        read_buffer	= null;
				        		        
						protocol_state	= PS_OUTBOUND_3;
					}
					
				}else if ( protocol_state == PS_OUTBOUND_3 ){
					
						// A->B: HASH('req1', S), HASH('req2', SKEY)^HASH('req3', S), ENCRYPT(VC, crypto_provide, len(PadC), PadC, len(IA)), ENCRYPT(IA)
		
					if ( write_buffer == null ){
						
							// padding_a here is half of the padding from before
						
						int	pad_max = getPaddingMax();
						
						byte[]	padding_a = getRandomPadding(pad_max/2);									

						byte[]	padding_c = getZeroPadding(pad_max);
						
						write_buffer = ByteBuffer.allocate( padding_a.length + 20 + 20 + ( VC.length + 4 + 2 + padding_c.length + 2 ) + initial_data_out_len );
						
						write_buffer.put( padding_a );
						
							// HASH('req1', S)
						
						SHA1Hasher	hasher = new SHA1Hasher();
						
						hasher.update( REQ1_IV );
						hasher.update( secret_bytes );
						
						byte[] sha1 = hasher.getDigest();
						
						write_buffer.put( sha1 );
								
							// HASH('req2', SKEY)^HASH('req3', S)
						
						hasher = new SHA1Hasher();
						
						hasher.update( REQ2_IV );
						hasher.update( shared_secret );
						
						byte[] sha1_1 = hasher.getDigest();
						
						hasher = new SHA1Hasher();
						
						hasher.update( REQ3_IV );
						hasher.update( secret_bytes );
						
						byte[] sha1_2 = hasher.getDigest();
						
						for (int i=0;i<sha1_1.length;i++){
							
							sha1_1[i] ^= sha1_2[i];
						}
						
						write_buffer.put( sha1_1 );
						
							// ENCRYPT(VC, crypto_provide, len(PadC), PadC, len(IA)
						
						write_buffer.put( write_cipher.update( VC ));
						
						write_buffer.put( write_cipher.update( new byte[]{ 0, 0, 0, my_supported_protocols }));
						
						write_buffer.put( write_cipher.update( new byte[]{ (byte)(padding_c.length>>8),(byte)padding_c.length }));
					
						write_buffer.put( write_cipher.update( padding_c ));
						
						write_buffer.put( write_cipher.update( new byte[]{ (byte)(initial_data_out_len>>8),(byte)initial_data_out_len }));
								
						if ( initial_data_out_len > 0 ){
						
							int	save_pos = initial_data_out.position();
							
							write_cipher.update( initial_data_out, write_buffer );
							
								// reset in case buffer needs to be used again by caller
							
							initial_data_out.position( save_pos );
							
							initial_data_out = null;
						}
						
						write_buffer.flip();
					}
					
					write( write_buffer );
					
					if ( !write_buffer.hasRemaining()){
					
						write_buffer	= null;
					
						protocol_state	= PS_INBOUND_4;
					}
					
				}else if ( protocol_state == PS_INBOUND_3 ){
					
						// B receives: HASH('req1', S), HASH('req2', SKEY)^HASH('req3', S), ENCRYPT(VC, crypto_provide, len(PadC), PadC, len(IA)), ENCRYPT(IA)
						
					if ( read_buffer == null ){
												
						read_buffer = ByteBuffer.allocate( 20 + PADDING_MAX );
						
						read_buffer.limit( 20 );
						
						SHA1Hasher hasher = new SHA1Hasher();
						
						hasher.update( REQ1_IV );
						hasher.update( secret_bytes );
						
						padding_skip_marker = hasher.getDigest();

						protocol_substate	= 1;
					}					
					
					while( true ){
						
						read( read_buffer );
								
						if ( read_buffer.hasRemaining()){
						
							break;
						}
						
						if ( protocol_substate == 1 ){
							
							 	//skip up to HASH('req1', S)
							
							int	limit = read_buffer.limit();
							
							read_buffer.position( limit - 20 );
							
							boolean match	= true;
							
							for (int i=0;i<20;i++){
								
								if ( read_buffer.get() != padding_skip_marker[i] ){
									
									match	= false;
									
									break;
								}
							}
							
							if ( match ){
							
								read_buffer = ByteBuffer.allocate( 20 + VC.length + 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 ){
							
								// find SKEY using HASH('req2', SKEY)^HASH('req3', S)  , ENCRYPT(VC, crypto_provide, len(PadC),
							
							read_buffer.flip();
								
							final byte[]	decode = new byte[20];
							
							read_buffer.get( decode );
							
							SHA1Hasher hasher = new SHA1Hasher();
							
							hasher.update( REQ3_IV );
							hasher.update( secret_bytes );
							

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -