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

📄 dec01_ericg.txt

📁 TechTips j2me的常用技巧. 网络功能
💻 TXT
📖 第 1 页 / 共 2 页
字号:

 J 2 M E    T  E  C  H    T  I  P  S

                      TIPS, TECHNIQUES, AND SAMPLE CODE


WELCOME to the Java Developer Connection(sm) (JDC)
Java(tm) 2 Platform, Micro Edition (J2ME(tm)) 
Tech Tips, for December 17, 2001. This issue covers:

     * Data Encryption for J2ME Profiles
     * Validating Input Using the ItemStateListener Interface
         
The J2ME Tech Tips are written by Eric Giguere
(http://www.ericgiguere.com), an engineer at iAnywhere 
Solutions, inc. Eric is the author of the book "Java 2 Micro
Edition: Professional Developer's Guide" and co-author of the 
book "Mobile Information Device Profile for Java 2 Micro 
Edition," both books in John Wiley & Sons' Professional 
Developer's Guide series.

You can view this issue of the J2ME Tech Tips on the Web at
http://java.sun.com/jdc/J2METechTips/2001/tt1217.html

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
DATA ENCRYPTION FOR J2ME PROFILES

If your J2ME applications store or transmit sensitive or 
confidential data, you can make them more secure using data 
encryption. Devices that support the Mobile Information Device 
Profile (MIDP), for example, are only required (in version 1.0) 
to support HTTP, not the secure HTTP protocol, HTTPS. The 
security of your data therefore depends on the security of the 
network. Even applications that don't transmit confidential
data can benefit from data encryption. When run on a Palm 
OS-based device, for example, the record stores used by a MIDP 
application are actually Palm OS record databases. The MIDP 
runtime system controls access to the underlying record 
databases so that only applications running the same MIDlet 
suite can see each other's data. However, it's a trivial matter
for an experienced Palm OS user to view and copy the contents of 
those databases independently from the MIDP runtime system.  
Encrypting the contents of a record store can defeat all but
the most determined attackers.

Unfortunately, encryption is not a standard part of either the 
Connected Device Configuration (CDC) or the Connected Limited 
Device Configuration (CLDC). You must either write your own 
encryption/decryption code or else use a class library. Writing 
your own code is not a recommended approach because of the 
complexity involved in selecting and implementing the appropriate
algorithms. Instead, it's better to take advantage of existing
code. That's where the Legion of the Bouncy Castle comes in.

The Legion of the Bouncy Castle is an open source Java encryption 
project hosted at http://www.bouncycastle.org. Although primarily 
geared towards providing alternative encryption algorithms for 
J2SE(tm), the Legion has adapted some of its code to work with 
J2ME. Specifically, parts of the Bouncy Castle lightweight 
cryptography API work with both the CLDC and the CDC. The 
lightweight API supports all the common block and stream 
encryptions, such as DES, Blowfish, IDEA, Rijndael, and RC4, as 
well as digest generation and key exchange, although not
all these features are available for all J2ME platforms.

To use the cryptography API, go to the Bouncy Castle web site and 
download the latest release of the lightweight API for J2ME. 
Extract the archive into a suitable directory. Although a 
midp_classes.zip file is provided with classes compiled and 
preverified, you're better off copying the source files you need 
directly into your project. That's because some of the Bouncy 
Castle classes refer to classes that are not found in the CLDC or
the MIDP. Second, you get a better idea of how much of a space 
penalty you pay for adding encryption support to your application.

Here is an example of a simple encryption class built using the 
Bouncy Castle lightweight API:

import org.bouncycastle.crypto.*;
import org.bouncycastle.crypto.engines.*;
import org.bouncycastle.crypto.modes.*;
import org.bouncycastle.crypto.params.*;

// A simple example that uses the Bouncy Castle
// lightweight cryptography API to perform DES
// encryption of arbitrary data.

public class Encryptor {

    private BufferedBlockCipher cipher;
    private KeyParameter        key;

    // Initialize the cryptographic engine.
    // The key array should be at least 8 bytes long.

    public Encryptor( byte[] key ){
        cipher = new PaddedBlockCipher(
                    new CBCBlockCipher(
                       new DESEngine() ) );

        this.key = new KeyParameter( key );
    }

    // Initialize the cryptographic engine.
    // The string should be at least 8 chars long.

    public Encryptor( String key ){
        this( key.getBytes() );
    }

    // Private routine that does the gritty work.

    private byte[] callCipher( byte[] data )
                        throws CryptoException {
        int    size = 
                   cipher.getOutputSize( data.length );
        byte[] result = new byte[ size ];
        int    olen = cipher.processBytes( data, 0,
                              data.length, result, 0 );
        olen += cipher.doFinal( result, olen );

        if( olen < size ){
            byte[] tmp = new byte[ olen ];
            System.arraycopy( 
                             result, 0, tmp, 0, olen );
            result = tmp;
        }

        return result;
    }

    // Encrypt arbitrary byte array, returning the
    // encrypted data in a different byte array.

    public synchronized byte[] encrypt( byte[] data )
                  throws CryptoException {
        if( data == null || data.length == 0 ){
            return new byte[0];
        }

        cipher.init( true, key );
        return callCipher( data );
    }

    // Encrypts a string.

    public byte[] encryptString( String data )
                  throws CryptoException {
        if( data == null || data.length() == 0 ){
            return new byte[0];
        }

        return encrypt( data.getBytes() );
    }

    // Decrypts arbitrary data.

    public synchronized byte[] decrypt( byte[] data )
                  throws CryptoException {
        if( data == null || data.length == 0 ){
            return new byte[0];
        }

        cipher.init( false, key );
        return callCipher( data );
    }

    // Decrypts a string that was previously encoded
    // using encryptString.

    public String decryptString( byte[] data )
                    throws CryptoException {
        if( data == null || data.length == 0 ){
            return "";
        }

        return new String( decrypt( data ) );
    }
}

The constructor defines the encryption algorithm to use by 
instantiating the appropriate encryption engine, in this case 
DESEngine, which represents the 56-bit DES algorithm:  

    public Encryptor( byte[] key ){
            cipher = new PaddedBlockCipher(
                        new CBCBlockCipher(
                           new DESEngine() ) );

DES works with 8-byte blocks. In order to be able to encrypt or 
decrypt data of arbitrary length, the constructor wraps the 
engine using PaddedBlockCipher and CDCBlockCipher. This produces 
a "cipher" object that does the encryption or decryption. The
cipher object must be initialized before it is used so that it 
knows whether it should encrypt or decrypt, and what key to use.  

The callCipher routine is where the encryption or decryption
actually occurs.

    private byte[] callCipher( byte[] data )
                        throws CryptoException {
            int    size = 
                   cipher.getOutputSize( data.length ); ...
  
To encrypt or decrypt data in your application, create an 
instance of this class, passing in the secret key. The secret key
must be at least eight bytes or characters long:

    Encryptor encryptor = 
                new Encryptor( "ghk23rTX" );
   
Note that because the encryption algorithm used in the example 
Encryptor class is the DES 56-bit algorithm, only the first eight 
characters or bytes of the key are used. If you change the class
to use one of the other engines, different limits apply.

Call the encrypt and decrypt methods to encrypt or decrypt 
arbitrary binary data. The convenience methods encryptString and 
decryptString make it easy to encrypt or decrypt strings by 
automatically converting them to and from byte arrays.

Here is a simple MIDP application that uses the Encryptor class 
to encrypt and decrypt a string stored in a record store. The
application prompts the user for an eight-character key. It then 
encrypts a user-defined message. The user can then enter 
different keys and see the result: either gibberish or an 
exception. Only the correct key will decrypt and display the 
message.

import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
import javax.microedition.rms.*;

import org.bouncycastle.crypto.*;

// Simple test of encryption/decryption routines.

public class CryptoTest extends MIDlet {

    private Display display;
    private Command exitCommand =
                         new Command( "Exit",
                                     Command.EXIT, 1 ); 
    private Command okCommand =
                         new Command( "OK",
                                      Command.OK, 1 );

    private Encryptor   encryptor;
    private RecordStore rs;

    public CryptoTest(){
    }

    protected void destroyApp( boolean unconditional )
                    throws MIDletStateChangeException {
        exitMIDlet();
    }

    protected void pauseApp(){
    }

    protected void startApp()
                    throws MIDletStateChangeException {
        if( display == null ){ // first time called...
            initMIDlet();
        }
    }

    private void initMIDlet(){
        display = Display.getDisplay( this );

        // Open a record store here

        try {
            rs = RecordStore.openRecordStore( "test",
                                    true );
        }
        catch( RecordStoreException e ){
            // put in error handling here
        }

        display.setCurrent( new AskForKey() );
    }

    public void exitMIDlet(){
        try {
            if( rs != null ){
                rs.closeRecordStore();
            }
        }
        catch( RecordStoreException e ){
        }

        notifyDestroyed();
    }

    private void displayException( Exception e ){
        Alert a = new Alert( "Exception" );
        a.setString( e.toString() );
        a.setTimeout( Alert.FOREVER );
        display.setCurrent( a, new AskForKey() );
    }

    class AskForKey extends TextBox
                    implements CommandListener {
        public AskForKey(){
            super( "Enter a secret key:", "", 8, 0 );
            setCommandListener( this );
            addCommand( okCommand );
            addCommand( exitCommand );
        }

        public void commandAction( Command c,
                                   Displayable d ){
            if( c == exitCommand ){
                exitMIDlet();
            } 

            String key = getString();
            if( key.length() < 8 ){
                Alert a = new Alert( "Key too short" );
                a.setString( "The key must be " +
                             "8 characters long" );
                setString( "" );
                display.setCurrent( a, this );
                return;
            }

            encryptor = new Encryptor( key );

            try {
                if( rs.getNextRecordID() == 1 ){
                    display.setCurrent(
                                  new EnterMessage() );
                } else {
                    byte[] data = rs.getRecord( 1 );
                    String str = 
                       encryptor.decryptString( data );

                    Alert a = 
                             new Alert( "Decryption" );
                    a.setTimeout( Alert.FOREVER );
                    a.setString( 
                          "The decrypted string is '" +
                                 str + "'" );
                    display.setCurrent( a, this );
                }
            }
            catch( RecordStoreException e ){
                displayException( e );
            }
            catch( CryptoException e ){
                displayException( e );
            }
        }
    }

    class EnterMessage extends TextBox
                       implements CommandListener {
        public EnterMessage(){
            super( "Enter a message to encrypt:", "",
                   100, 0 );
            setCommandListener( this );
            addCommand( okCommand );
        }

        public void commandAction( Command c,
                                   Displayable d ){
            String msg = getString();

            try {
                byte[] data =
                      encryptor.encryptString( msg );
                rs.addRecord( data, 0, data.length );
            }
            catch( RecordStoreException e ){
                displayException( e );
            }
            catch( CryptoException e ){
                displayException( e );
            }

            display.setCurrent( new AskForKey() );
        }
    }
}

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
VALIDATING INPUT USING THE ITEMSTATELISTENER INTERFACE

The Mobile Information Device Profile's high-level user interface 
API defines several components for placement on Form objects.

⌨️ 快捷键说明

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