FileDocCategorySizeDatePackage
CryptoSTSEngineImpl.javaAPI DocAzureus 3.0.3.49071Sun Jul 09 04:32:14 BST 2006com.aelitis.azureus.core.security.impl

CryptoSTSEngineImpl

public final class CryptoSTSEngineImpl extends Object implements com.aelitis.azureus.core.security.CryptoSTSEngine
STS authentication protocol using a symmetric 4 message ECDH/ECDSA handshake

Fields Summary
public static final int
VERSION
private CryptoHandlerECC
handler
private KeyPair
ephemeralKeyPair
private PublicKey
myPublicKey
private PrivateKey
myPrivateKey
private PublicKey
remotePubKey
private byte[]
sharedSecret
private InternalDH
ecDH
Constructors Summary
CryptoSTSEngineImpl(CryptoHandlerECC _handler, PublicKey _myPub, PrivateKey _myPriv)

param
myIdent keypair representing our current identity

	
	        	 
	
	
			
					
					 
		
		 
	
		handler			= _handler;
		myPublicKey		= _myPub;
		myPrivateKey	= _myPriv;
				
		ephemeralKeyPair = handler.createKeys();
		
		try{
			ecDH = new InternalDH();
			
			//ecDH = KeyAgreement.getInstance("ECDH", "BC");
			
			ecDH.init(ephemeralKeyPair.getPrivate());
			
		}catch (Exception e){
			
			throw new CryptoManagerException("Couldn't initialize crypto handshake", e);
		}
	
Methods Summary
public voidgetAuth(java.nio.ByteBuffer message)

		getMessage( message, false );
	
protected byte[]getBytes(java.nio.ByteBuffer buffer, int max_size)

		int	len = getInt( buffer, max_size );
		
		if ( len > max_size ){
			
			throw( new CryptoManagerException( "Invalid length" ));
		}
		
		try{
			byte[]	res = new byte[len];
			
			buffer.get( res );
			
			return( res );
			
		}catch( Throwable e ){
			
			throw( new CryptoManagerException( "Failed to get byte[]", e ));
		}
	
protected intgetInt(java.nio.ByteBuffer buffer, int max_size)

		try{
			if ( max_size < 256 ){
				
				return( buffer.get() & 0xff);
				
			}else if ( max_size < 65536 ){
				
				return( buffer.getShort() & 0xffff);
				
			}else{
				
				return( buffer.getInt());
			}
		}catch( Throwable e ){
			
			throw( new CryptoManagerException( "Failed to get int", e ));
		}
	
public voidgetKeys(java.nio.ByteBuffer message)

		getMessage( message, true );
	
public voidgetMessage(java.nio.ByteBuffer buffer, boolean keys)

		// System.out.println( "get( " + keys + ") " + this );

		try{
			putInt( buffer, VERSION, 255 );
						
			SecureRandom random = SecureRandom.getInstance("SHA1PRNG");

			Signature sig = handler.getSignature(myPrivateKey);
			
			if ( keys ){
								
				final byte[] rawMyPubkey = handler.keyToRawdata(myPublicKey);
				
				final byte[] rawEphemeralPubkey = handler.keyToRawdata(ephemeralKeyPair.getPublic());
				
				sig.update(rawMyPubkey);
					
				sig.update(rawEphemeralPubkey);
					
				final byte[] rawSign = sig.sign();
				
				final byte[] pad = new byte[random.nextInt(32)];
				
				random.nextBytes(pad);
				
				putBytes( buffer, rawMyPubkey, 65535 );
				
				putBytes( buffer, rawEphemeralPubkey, 65535 );
				
				putBytes( buffer, rawSign, 65535 );
				
				putBytes( buffer, pad, 65535 );
	
			}else{
					
				if ( sharedSecret == null ){
					
					throw( new CryptoManagerException( "phase error: keys not received" ));
				}
				
				final byte[] IV = new byte[20 + random.nextInt(32)];
				
				random.nextBytes(IV);

				sig.update(IV);
				
				sig.update(sharedSecret);
				
				final byte[] rawSig = sig.sign();

				putBytes( buffer, IV, 65535 );

				putBytes( buffer, rawSig, 65535 );
			}
		}catch( CryptoManagerException	e ){
						
			throw( e );
			
		}catch( Throwable e ){
						
			throw( new CryptoManagerException( "Failed to generate message" ));
		}
	
public byte[]getRemotePublicKey()

		if ( remotePubKey == null ){
			
			throw( new CryptoManagerException( "key not yet available" ));
		}
		
		return( handler.keyToRawdata( remotePubKey ));
	
public byte[]getSharedSecret()

		if ( sharedSecret == null ){
			
			throw( new CryptoManagerException( "secret not yet available" ));
		}
		
		return sharedSecret;
	
public voidputAuth(java.nio.ByteBuffer message)

		putMessage( message, false );
	
protected voidputBytes(java.nio.ByteBuffer buffer, byte[] value, int max_size)

		putInt( buffer, value.length, max_size );
		
		try{
			buffer.put( value );
			
		}catch( Throwable e ){
			
			throw( new CryptoManagerException( "Failed to put byte[]", e ));
		}
	
protected voidputInt(java.nio.ByteBuffer buffer, int value, int max_size)

		try{
			if ( max_size < 256 ){
				
				buffer.put((byte)value);
				
			}else if ( max_size < 65536 ){
				
				buffer.putShort((short)value );
				
			}else{
				
				buffer.putInt( value );
			}
		}catch( Throwable e ){
			
			throw( new CryptoManagerException( "Failed to put int", e ));
		}
	
public voidputKeys(java.nio.ByteBuffer message)

		putMessage( message, true );
	
public voidputMessage(java.nio.ByteBuffer message, boolean keys)

		// System.out.println( "put( " + keys + ") " + this );
		
		try{
			int	version = getInt( message, 255 );
			
			if ( version != VERSION ){
				
				throw( new CryptoManagerException( "invalid version (" + version + ")" ));
			}
							
			if ( keys ){
			
				if ( sharedSecret != null ){
					
					throw( new CryptoManagerException( "phase error: keys already received" ));
				}
				
				final byte[] rawRemoteOtherPubkey = getBytes( message, 65535 );
				
				final byte[] rawRemoteEphemeralPubkey = getBytes( message, 65535 );
	
				final byte[] remoteSig = getBytes( message, 65535 );
				
				final byte[] pad = getBytes( message, 65535 );
				
				remotePubKey = handler.rawdataToPubkey(rawRemoteOtherPubkey);
				
				Signature check = handler.getSignature(remotePubKey);
	
				check.update(rawRemoteOtherPubkey);
				
				check.update(rawRemoteEphemeralPubkey);
				
				if ( check.verify(remoteSig)){
										
					ecDH.doPhase(handler.rawdataToPubkey(rawRemoteEphemeralPubkey), true);
					
					sharedSecret = ecDH.generateSecret();
					
				}else{
												
					throw( new CryptoManagerException( "Signature check failed" ));
				}
				
			}else{
				
				if ( sharedSecret == null ){
					
					throw( new CryptoManagerException( "phase error: keys not received" ));
				}
				
				final byte[] IV = getBytes( message, 65535 );
				
				final byte[] remoteSig = getBytes( message, 65535);
							
				Signature check = handler.getSignature( remotePubKey );
				
				check.update(IV);
					
				check.update(sharedSecret);
					
				if ( !check.verify(remoteSig)){
	
					throw( new CryptoManagerException( "Signature check failed" ));
				}
			}
		}catch( CryptoManagerException	e ){
						
			throw( e );
			
		}catch( Throwable e ){
						
			throw( new CryptoManagerException( "Failed to generate message" ));
		}