Public Member Functions | Static Public Member Functions | Static Private Member Functions | Private Attributes | Static Private Attributes

crypto.PublicEncryptor Class Reference

Implements public part of the asymmetric cipher (with public key) used to send encrypted local secret key (used for symmetric ciphering of peer-to-peer datagram packets) to remote peer. More...

Collaboration diagram for crypto.PublicEncryptor:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 PublicEncryptor (String serializedPublicKey, String remoteUserId)
 Deserializes public key from the Base64 string and instantiates PublicEncryptor.
boolean isActive ()
 Returns if cipher is properly initialized.
boolean isVerified ()
 Returns if public key was verified.
String getVerificatorName ()
 Returns if name of the verificator from authorized keys that verified this public key.
byte[] encrypt (byte[] plainText)
 Encrypts plain text using public key.
String encryptAndSerialize (Serializable object)
 Returns Base64 of encrypted (using our public key) object.

Static Public Member Functions

static void loadAuthorizedPublicKeys ()
 Loads authorized keys.
static String verifyObject (SignedObject object)
 Verifies signed object with a public key from the authorized public keys.

Static Private Member Functions

static void createEmptyAuthorizedPublicKeys (String filename)
 Create empty authorized keys file if it does not exist and adjust permissions.

Private Attributes

PublicKey publicKey = null
 Public key.
Cipher cipher = null
 Instance of the encrypting engine based on remote public key.
String serializedPublicKey = null
 Remote public key: serialized and encoded as Base64 string.
String verificator = null
 Contains name of the verificator (i.e the name associated with authorized public key that has verified this public key).

Static Private Attributes

static final String padding = "/ECB/PKCS1PADDING"
 Padding to be used when ciphering/deciphering JCE does not support RSA/CBC so the CBC mode is built on the top of ECB in PublicEncryptor.encrypt().
static final String digest = "SHA1"
 Message digest used for creating/validating signatures.
static final String authorizedKeysFile = "mykf-authorized-keys.txt"
 The name of the file holding authorized public keys of remote peers.
static ArrayList< NamedPublicKeyauthorizedKeys = null
 Authorized public keys (loaded from file)

Detailed Description

Implements public part of the asymmetric cipher (with public key) used to send encrypted local secret key (used for symmetric ciphering of peer-to-peer datagram packets) to remote peer.

The class holds also list of authorized public keys, which is used to verify signed objects received from peers.

Author:
Mikica B Kocic

Definition at line 34 of file PublicEncryptor.java.


Constructor & Destructor Documentation

crypto.PublicEncryptor.PublicEncryptor ( String  serializedPublicKey,
String  remoteUserId 
)

Deserializes public key from the Base64 string and instantiates PublicEncryptor.

Verifies public key with the public key retrieved from the authorized keys.

Definition at line 84 of file PublicEncryptor.java.

References crypto.PublicEncryptor.cipher, crypto.PublicEncryptor.padding, crypto.PublicEncryptor.publicKey, crypto.PublicEncryptor.serializedPublicKey, crypto.PublicEncryptor.verificator, and crypto.PublicEncryptor.verifyObject().

    {
        /* Deserialize and verify public key used for encryption.
         */
        this.serializedPublicKey = serializedPublicKey;

        try
        {
            Object object = Base64.decodeToObject( this.serializedPublicKey );
            SignedObject signedObject = null;

            if ( object instanceof SignedObject ) 
            {
                signedObject = (SignedObject) object;
                this.verificator = PublicEncryptor.verifyObject( signedObject );
                object = signedObject.getObject ();
            }
            
            if ( object instanceof PublicKey ) 
            {
                this.publicKey = (PublicKey)object;
                String algorithm = this.publicKey.getAlgorithm (); 
                this.cipher = Cipher.getInstance( algorithm + padding );
            }
        }
        catch( ClassNotFoundException e )
        {
            Log.exception( Log.WARN, e );
        }
        catch( NoSuchAlgorithmException e )
        {
            Log.exception( Log.WARN, e );
        }
        catch( NoSuchPaddingException e )
        {
            Log.exception( Log.WARN, e );
        }
        catch( IOException e )
        {
            Log.exception( Log.WARN, e );
        }

        /* If failed to create serializedPublicKey, then fail for good.
         */
        if ( this.publicKey == null )
        {
            this.cipher = null;
        }
    }

Member Function Documentation

static void crypto.PublicEncryptor.createEmptyAuthorizedPublicKeys ( String  filename ) [static, private]

Create empty authorized keys file if it does not exist and adjust permissions.

Definition at line 138 of file PublicEncryptor.java.

Referenced by crypto.PublicEncryptor.loadAuthorizedPublicKeys().

    {
        try
        {
            File file = new File( filename );

            if (  ! file.exists () ) {
                file.createNewFile ();
            }

            if (  file.exists () )
            {
                /* Change permissions using native OS 'chmod' command (ignoring Windows), 
                 * so that no one but the owner might read its contents.
                 */
                String osName = System.getProperty( "os.name" ).toLowerCase();
                if ( ! osName.matches( "^.*windows.*$" ) ) 
                {
                    try 
                    {
                        Runtime.getRuntime().exec( new String[] { "chmod", "go=", filename } );
                    }
                    catch( IOException e ) 
                    {
                        Log.trace( "Failed to do chmod; OS = " + osName );
                        Log.exception( Log.TRACE, e );
                    }
                }
            }
        }
        catch( Exception e )
        {
            Log.exception( Log.ERROR, e );
        }
    }
byte [] crypto.PublicEncryptor.encrypt ( byte[]  plainText )

Encrypts plain text using public key.

Emulates CBC (cipher-block chaining) using plain ECB. Why? -- Because JCE does not support RSA/CBC cipher (only RSA/ECB).

See Cipher-block chaining (CBC)

cbc_encryption.png
See also:
AsymmetricCipher.decrypt

Definition at line 342 of file PublicEncryptor.java.

References crypto.PublicEncryptor.cipher, and crypto.PublicEncryptor.publicKey.

Referenced by crypto.PublicEncryptor.encryptAndSerialize(), and crypto.AsymmetricCipher.sanityCheck().

    {
        if ( this.cipher == null ) {
            return null;
        }

        byte[] output = null;
        
        synchronized( this.cipher ) 
        {
            try 
            {
                this.cipher.init( Cipher.ENCRYPT_MODE, publicKey );
                
                /* cipher.getBlockSize () returns always 0, so for the RSA
                 * we can calculate block size as output size - 11 octets overhead.
                 * e.g. 117 octets for 1024-bit RSA key size (= 1024/8 - 11 )
                 */
                int blockSize = cipher.getOutputSize( 1 ) - 11;
                
                ByteArrayOutputStream bOut = new ByteArrayOutputStream ();
                
                byte[] xorBlock = new byte[ blockSize ];

                for ( int pos = 0; pos < plainText.length; pos += blockSize ) 
                {
                    int len = Math.min( plainText.length - pos, blockSize );
                    
                    for ( int i = 0; i < len; ++i ) {
                        xorBlock[i] = (byte)( xorBlock[i] ^ plainText[ pos + i ] );
                    }

                    byte[] cipherBlock = this.cipher.doFinal( xorBlock, 0, len );
                    bOut.write( cipherBlock );

                    System.arraycopy( cipherBlock, 0, xorBlock, 0, blockSize );
                }

                output = bOut.toByteArray ();
            }
            catch( Exception e )
            {
                Log.exception( Log.ERROR, e );
            }
        }

        return output;
    }
String crypto.PublicEncryptor.encryptAndSerialize ( Serializable  object )

Returns Base64 of encrypted (using our public key) object.

Definition at line 394 of file PublicEncryptor.java.

References crypto.PublicEncryptor.encrypt().

Referenced by CryptoPhoneApp.acceptIncomingCall().

    {
        // TODO sign object first with our public key !

        String result = null;
        
        /* Serialize instance of the secret key into secret key file
         */
        ByteArrayOutputStream bOut = null; 
        ObjectOutputStream oOut = null;
        
        try
        {
            bOut = new ByteArrayOutputStream ();
            oOut = new ObjectOutputStream( bOut );
            oOut.writeObject( object );
            
            byte[] plainText = bOut.toByteArray ();
            
            oOut.close ();
            bOut.close ();
            
            result = Base64.encodeBytes( encrypt( plainText ), Base64.GZIP );
        }
        catch( Exception e ) 
        {
            Log.exception( Log.ERROR, e );
        }
        
        return result;
    }
String crypto.PublicEncryptor.getVerificatorName (  )

Returns if name of the verificator from authorized keys that verified this public key.

Returns:
name of the verificator; May be null indicating not verified public key

Definition at line 326 of file PublicEncryptor.java.

References crypto.PublicEncryptor.verificator.

Referenced by CryptoPhoneApp.deferredOnRing(), and CryptoPhoneApp.tryToVerifyInvitingCall().

    {
        return this.verificator;
    }
boolean crypto.PublicEncryptor.isActive (  )

Returns if cipher is properly initialized.

Definition at line 308 of file PublicEncryptor.java.

References crypto.PublicEncryptor.cipher.

Referenced by CryptoPhoneApp.acceptIncomingCall(), CryptoPhoneApp.deferredOnRing(), and CryptoPhoneApp.tryToVerifyInvitingCall().

    {
        return this.cipher != null;
    }
boolean crypto.PublicEncryptor.isVerified (  )

Returns if public key was verified.

Definition at line 316 of file PublicEncryptor.java.

References crypto.PublicEncryptor.verificator.

Referenced by CryptoPhoneApp.acceptIncomingCall(), CryptoPhoneApp.deferredOnRing(), and CryptoPhoneApp.tryToVerifyInvitingCall().

    {
        return this.verificator != null;
    }
static void crypto.PublicEncryptor.loadAuthorizedPublicKeys (  ) [static]

Loads authorized keys.

Definition at line 177 of file PublicEncryptor.java.

References crypto.PublicEncryptor.authorizedKeys, crypto.PublicEncryptor.authorizedKeysFile, crypto.NamedPublicKey.comment, crypto.PublicEncryptor.createEmptyAuthorizedPublicKeys(), and crypto.CipherEngine.getPrivateKeyDirectory().

Referenced by crypto.CipherEngine.initialize(), and crypto.CipherEngine.reloadAuthorizedPublicKeys().

    {
        StringBuffer report = new StringBuffer ();

        ArrayList<NamedPublicKey> newAuthKeys = new ArrayList<NamedPublicKey> ();

        try 
        {
            String filePath = CipherEngine.getPrivateKeyDirectory ()
                            + authorizedKeysFile;
            
            createEmptyAuthorizedPublicKeys( filePath );

            FileReader inf = new FileReader( filePath );
            BufferedReader ins = new BufferedReader( inf );

            String line;
            while ( ( line = ins.readLine () ) != null ) 
            {
                /* Split line into 'words'; Our key should be the first word 
                 */
                String[] parts = line.trim().split( "\\s{1,}" );
                
                /* Skip empty lines
                 */
                if ( parts.length < 1 || parts[0].length () <= 0 ) {
                    continue;
                }

                /* Skip lines starting with '#' (comments) 
                 */
                if ( parts[0].equals( "#" ) ) {
                    continue;
                }

                /* Now, deserialize public key from the first word
                 */
                String encodedKey = parts[0];
                Object object = null;

                try {
                    object = Base64.decodeToObject( encodedKey.toString () );
                }
                catch( IOException e )
                {
                    Log.warn( "Failed to deserialize authorized key at line: [" + encodedKey + "]" );
                    Log.exception( Log.WARN, e );
                }
                catch( ClassNotFoundException e )
                {
                    Log.warn( "Failed to deserialize authorized key at line: [" + encodedKey + "]" );
                    Log.exception( Log.WARN, e );
                }

                if ( object != null && ( object instanceof NamedPublicKey ) ) 
                {
                    NamedPublicKey authKey = (NamedPublicKey) object; 
                    newAuthKeys.add( authKey );
                    if ( report.length () != 0 ) {
                        report.append( ", " );
                    }
                    report.append( authKey.comment );
                }
                else if ( object != null )
                {
                    Log.warn( "Line: [" + encodedKey + "]" );
                    Log.warn( "Ignored class: " + object.getClass().toString () );
                }
            }
        }
        catch( FileNotFoundException e )
        {
            Log.exception( Log.TRACE, e );
        }
        catch( IOException e )
        {
            Log.exception( Log.WARN, e );
        }

        if ( newAuthKeys.size() > 1 ) 
        {
            report.insert( 0,  "Loaded " + newAuthKeys.size() + " authorized keys: " );
            Log.attn( report.toString () );
        }
        else if ( newAuthKeys.size() == 1 ) 
        {
            report.insert( 0,  "Loaded authorized key: " );
            Log.attn( report.toString () );
        }

        authorizedKeys = newAuthKeys;
    }
static String crypto.PublicEncryptor.verifyObject ( SignedObject  object ) [static]

Verifies signed object with a public key from the authorized public keys.

Returns:
not null if verified with the name associated to authorized public key

Definition at line 275 of file PublicEncryptor.java.

References crypto.PublicEncryptor.authorizedKeys, crypto.PublicEncryptor.digest, and crypto.PublicEncryptor.verificator.

Referenced by crypto.AsymmetricCipher.deserializeEncryptedSecretKey(), and crypto.PublicEncryptor.PublicEncryptor().

    {
        if ( authorizedKeys == null ) {
            return null;
        }

        String verificator = null;

        for ( NamedPublicKey authKey : authorizedKeys )
        {
            try 
            {
                String signAlgorithm = digest + "with" + authKey.publicKey.getAlgorithm ();
                
                Signature signature = Signature.getInstance( signAlgorithm );
                
                if ( object.verify( authKey.publicKey, signature ) ) {
                    verificator = authKey.comment;
                    break;
                }
            }
            catch( Exception e )
            {
                /* ignore all errors; search until exhausted keys or verify succeeds */
            }
        }
        
        return verificator;
    }

Member Data Documentation

ArrayList<NamedPublicKey> crypto.PublicEncryptor.authorizedKeys = null [static, private]

Authorized public keys (loaded from file)

Definition at line 56 of file PublicEncryptor.java.

Referenced by crypto.PublicEncryptor.loadAuthorizedPublicKeys(), and crypto.PublicEncryptor.verifyObject().

final String crypto.PublicEncryptor.authorizedKeysFile = "mykf-authorized-keys.txt" [static, private]

The name of the file holding authorized public keys of remote peers.

Definition at line 51 of file PublicEncryptor.java.

Referenced by crypto.PublicEncryptor.loadAuthorizedPublicKeys().

Cipher crypto.PublicEncryptor.cipher = null [private]

Instance of the encrypting engine based on remote public key.

Definition at line 66 of file PublicEncryptor.java.

Referenced by crypto.PublicEncryptor.encrypt(), crypto.PublicEncryptor.isActive(), and crypto.PublicEncryptor.PublicEncryptor().

final String crypto.PublicEncryptor.digest = "SHA1" [static, private]

Message digest used for creating/validating signatures.

Definition at line 46 of file PublicEncryptor.java.

Referenced by crypto.PublicEncryptor.verifyObject().

final String crypto.PublicEncryptor.padding = "/ECB/PKCS1PADDING" [static, private]

Padding to be used when ciphering/deciphering JCE does not support RSA/CBC so the CBC mode is built on the top of ECB in PublicEncryptor.encrypt().

Definition at line 41 of file PublicEncryptor.java.

Referenced by crypto.PublicEncryptor.PublicEncryptor().

PublicKey crypto.PublicEncryptor.publicKey = null [private]

Public key.

Definition at line 61 of file PublicEncryptor.java.

Referenced by crypto.PublicEncryptor.encrypt(), and crypto.PublicEncryptor.PublicEncryptor().

Remote public key: serialized and encoded as Base64 string.

Definition at line 71 of file PublicEncryptor.java.

Referenced by crypto.PublicEncryptor.PublicEncryptor().

String crypto.PublicEncryptor.verificator = null [private]

Contains name of the verificator (i.e the name associated with authorized public key that has verified this public key).

Not null indicates that the public key was successfully verified.

Definition at line 78 of file PublicEncryptor.java.

Referenced by crypto.PublicEncryptor.getVerificatorName(), crypto.PublicEncryptor.isVerified(), crypto.PublicEncryptor.PublicEncryptor(), and crypto.PublicEncryptor.verifyObject().


The documentation for this class was generated from the following file: