BlackBerry 应用程序开发者指南 第二卷:高级--第14章 增加对智能卡(smart card)的支持
作者:Confach 发表于 2006-04-28 22:28 pm
版权信息:可以任意转载, 转载时请务必以超链接形式标明文章原始出处 和作者信息.
http://www.cnblogs.com/confach/articles/388978.html
14
第14章 增加对智能卡(smart card)的支持
| 使用智能卡 创建一个智能卡驱动 | 
使用智能卡
智能卡和信用卡一般大,可以安全的存储和传输敏感数据.BlackBerry设备支持下面的智能卡:
- 普通访问卡(CAC,Common Access Card)
- SafeNet智能卡(Datakey Model 330)
如果你使用的智能卡不是CAC或SageNet智能卡,你也可以利用智能卡的API编写一个BlackBerry设备驱动来支持你的智能卡.智能卡API提供了一个组件库,它们在net.rim.device.api.smartcard 包中,用来和智能卡以及智能卡读卡器进行交互.
对智能卡API恰当实现了的驱动,可以和BlackBerry设备上已经启动的S/MIME一起工作.它包括从智能卡导入认证,以及对卡进行私有键操作(签名和解密消息)
  注:为获取关于S/MIME的更多信息,参看带有S/MIME支持包的BlackBerry。 
创建一个智能卡驱动
为创建一个智能卡驱动,完成下面的步骤:
1. 扩展CryptoSmartCard类,实现一个新的智能卡类.
2. 在新的智能卡里,实现libmain()方法,在启动的时候调用它.
3. 扩展CryptoSmartCardSession类,未智能卡类实现一个新的对话.
4. 扩展Crypto环(token)类,为RSA, DSA, ECC操作实现一个环。
      5.    存储私有键文件位置.
       注:为得到更多关于net.rim.device.api.crypto包的信息,参看API参考.
实现一个智能卡
扩展抽象类CryptoSmartCard.此类的扩展允许子类作为一个智能卡驱动在SmartCardFactory里注册.子类必须实现下面SmartCard和CryptoSmartCard抽象类的方法:
| SmartCard 方法 | 描述 | 
| openSessionImpl(SmartCardReaderSession) | 建立一个和智能卡的通信. | 
| checkAnswerToResetImpl(AnswerToReset) | 验证智能卡和一个指定的ATR的兼容性. | 
| displaySettingsImpl(Object) | 允许智能卡驱动显示设置或属性. | 
| isDisplaySettingsAvailableImpl(Object) | 描述驱动是否支持显示设置. | 
| getCapabilitiesImpl() | 获取智能卡的能力. | 
| getLabelImpl() | 获取智能卡的类型. | 
| toString() | 得到智能卡的字符串描述. | 
| CryptoSmartCard 方法 | 描述 | 
| getAlgorithms() | 得到智能卡支持的所有算法名.例如“RSA”, “DSA” | 
| getCryptoToken(String) | 获取一个支持给定算法的加密环. | 
代码实例
.下面的实例描述了通过扩展CryptoSmartCard类,如何创建一个智能卡对象.
例: MyCryptoSmartCard.java
 /**
* MyCryptoSmartCard.java
* Copyright (C) 2001-2005 Research In Motion Limited. All rights reserved.
*/
package com.rim.samples.device.smartcard;
import net.rim.device.api.smartcard.*;
import net.rim.device.api.util.*;
import net.rim.device.api.crypto.*;
import net.rim.device.api.ui.component.*;
/**
* This class represents a kind (or model or family) of a physical smart card.
* There should only be one instance of this class in the system at one time. The instance
* is managed by the SmartCardFactory.
*/
public class MyCryptoSmartCard extends CryptoSmartCard implements Persistable
{
    private final static byte MY_ATR [] = {
       (byte)0x3b, (byte)0x7d, (byte)0x11,
       (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x31,
       (byte)0x80, (byte)0x71, (byte)0x8e, (byte)0x64,
       (byte)0x86, (byte)0xd6, (byte)0x01, (byte)0x00,
       (byte)0x81, (byte)0x90, (byte)0x00 };
    
    private final static AnswerToReset _myATR = new AnswerToReset( MY_ATR );
    private static final String LABEL = "RIM Sample";
    private static final String DISPLAY_SETTINGS = "Show driver properties/settings now";
    private static final String RSA = "RSA";
    
    /**
     *A smart card factory’s list of known smart cards.
     *Called on startup of the device. Register this driver with the
     */
    
    public static void libMain( String args[] )
    {
       SmartCardFactory.addSmartCard( new MyCryptoSmartCard() );
    }
    
    /**
     *Retrieve the session handler for this smart card.
     *Implementations of this method should not bring up UI.
     */
    
    protected SmartCardSession openSessionImpl( SmartCardReaderSession readerSession ) 
          throws SmartCardException {
       return new MyCryptoSmartCardSession( this, readerSession );
       }
    
    /**
     * Determine if the file system should use this smart card object
     * to communicate with a physical smart card.
     * that has the given AnswerToReset.
     * The system invokes this method to ascertain which smart card implementation it should
     * use to communicate with a physical smart card found in a reader.
     */
    protected boolean checkAnswerToResetImpl( AnswerToReset atr )
    {
       return _myATR.equals( atr );
    }
    
    /**
     *Retrieve a label associated with this smart card.
     *The string should not include the words "smart card", as the file system uses this
     *this method to generate strings such as "Please insert your smart card".
     */
    
    protected String getLabelImpl()
    {
       return LABEL;
    }
    
    /**
     * Retrieves this smart card’s capabilities
     */
    protected SmartCardCapabilities getCapabilitiesImpl()
    {
       return new SmartCardCapabilities( SmartCardCapabilities.PROTOCOL_T0 );
    }
    
    /**
     *Determine if this smart card can display its settings.
     */
    protected boolean isDisplaySettingsAvailableImpl( Object context )
    {
       return true;
    }
    
    /**
     *Display this smart card’s settings.
     *This method will be invoked from the smart card options screen when
     *the user selects the driver and chooses to view the settings of that driver.
     *
     *This method could be called from the event thread. The driver should not block
     *the event thread for long periods of time.
     *
     *@param context Reserved for future use.
     **/
    protected void displaySettingsImpl( Object context )
    {
       Dialog.alert( DISPLAY_SETTINGS );
    }
    
    /**
     * Retrieve the algorithms supported by this smart card.
     * 
     * @return one of "RSA", "DSA", or "ECC"
     */ 
    public String[] getAlgorithms()
    {
       return new String [] { RSA };
    }
    
    /** Retrieve a crypto token that supports the given algorithm.
     *  @param algorithm Name of the algorithm.   *  
     *  @return Crypto Token supporting the named algorithm.
     *  @throws NoSuchAlgorithmException If the specified algorithm is invalid.
     *  @throws CryptoTokenException If there is a token-related problem.
     */
    public CryptoToken getCryptoToken( String algorithm )
    throws NoSuchAlgorithmException, CryptoTokenException
    {
       if ( algorithm.equals( RSA ) )
       {
           return new MyRSACryptoToken();
       }
       throw new NoSuchAlgorithmException();
       }
    }
在启动时打开libMain()
当扩展CryptoSmartCard类时,你需要创建一个libMain()方法.为了使此方法恰当的运行,设置BlackBerry IDE在启动时运行此方法:
1.启动BlackBerry IDE.
2.为你正在设计的智能卡驱动创建一个新的工程
 注: 参看BlackBerryIDE在线帮助获得更多信息.
3.在Workspace窗口,右击你创建的工程.
4.选择 Properties.
5.选择Application标签..
6.在Project type 域, 输入Library.
7.务必选择 Auto-run on startup.
8.在Startup Tier域, 选择7(Last; 3rd party apps only) 选项.
9.单击OK.
实现一个智能卡对话
扩展CryptoSmartCardSession抽象类.你的子类必须实现下列SmartCardSession和CryptoSmartCardSession抽象类的方法.
| SmartCardSession 方法 | 描述 | 
| closeImpl() | 结束一个智能卡对话。 | 
| getMaxLoginAttemptsImpl() | 获取试图登录的最大次数。 | 
| getRemainingLoginAttemptsImpl() | 获取试图登录的剩余次数。 | 
| getSmartCardIDImpl() | 获取智能卡ID。 | 
| loginImpl(String) | 试图用一个给定的密码将用户记录到智能卡。 | 
| CryptoSmartCardSession 方法 | 描述 | 
| getKeyStoreDataArrayImpl() | 获取与卡上存储的键相关联的键存储数据. | 
| getRandomBytesImpl(int maxNumBytes) | 获取一些来自智能卡内部随机数生成器生成的随机数据. | 
代码实例
下面的实例描述了如何扩展CryptoSmartCardSession类创建一个智能卡对话:
例: MyCryptoSmartCardSession.java
/**
* MyCryptoSmartCardSession.java
* Copyright (C) 2001-2005 Research In Motion Limited. All rights reserved.
*/
package com.rim.samples.device.smartcard;
import net.rim.device.api.crypto.*;
import net.rim.device.api.crypto.certificate.*;
import net.rim.device.api.crypto.certificate.x509.*;
import net.rim.device.api.crypto.keystore.*;
import net.rim.device.api.smartcard.*;
import net.rim.device.api.util.*;
/**
* This class represents a communication session with a physical smart card.
* Over this session, Application Protocol Data Units may be exchanged with the smart card
* to provide the desired functionality.
* Do not hold open sessions when not using them; they should be short-lived.
* As a security precaution, only one open session is allowed to exist per SmartCardReader;
* subsequent openSession() requests will block until the current session is closed.
*/
public class MyCryptoSmartCardSession extends CryptoSmartCardSession
{
    public static final byte ID_PKI = (byte)0x00;
       public static final byte SIGNING_PKI = (byte)0x01;
       public static final byte ENCRYPTION_PKI = (byte)0x02;
       private static final String WAITING_MSG = "Please Wait";
       private static final String ID_STRING = "John H. Smith";
       private static final String ID_CERT = "ID Certificate";
       private static final String SIGNING_CERT = "Signing Certificate";
       private static final String ENCRYPTION_CERT = "Encryption Certificate";
       
       /**
        * Construct a new MyCryptoSmartCardSession object.
        * @param smartCard Smart card associated with this session
        * @param readerSession Reader session commands sent to this smart card.
        */
       protected MyCryptoSmartCardSession( SmartCard smartCard, SmartCardReaderSession readerSession )
       {
           super( smartCard, readerSession );
       }
       
       /**
        * Close this smart card session.
        * 
        * Implementations should not close the underlying SmartCardReaderSession. 
        * Use this method for cleaning up the session prior to its closure.
        */
       protected void closeImpl()
       {
           // Do any session cleanup needed here.
       }
       
       /**
        *  Retrieve the maximum number of allowed login attempts.
        *  The method returns Integer.MAX_VALUE if an infinite number of attempts are allowed.
        */
       protected int getMaxLoginAttemptsImpl() throws SmartCardException
        {
           return 5;
       }
       
       /**
        * Retrieve the remaining number of login attempts allowed (before the smart card will
        * lock, or Integer.MAX_VALUE if the smart card will not lock.)
        */
       protected int getRemainingLoginAttemptsImpl() throws SmartCardException
       {
           return 4;
       }
       
       /**
        * Log into the smart card with the given password.
        *  This method should not bring up the UI.
        */
       protected boolean loginImpl( String password ) throws SmartCardException
       {
           // Create a CommandAPDU which your smart card will understand
           CommandAPDU command = new CommandAPDU( (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x00 );
           command.setLcData( password.getBytes() );
           ResponseAPDU response = new ResponseAPDU();
           sendAPDU( command, response );
           
           // Check for response codes specific to your smart card
           if ( response.checkStatusWords( (byte)0x90, (byte)0x00 ) ) {
              return true;
              }
           else if ( response.checkStatusWords( (byte)0x64, (byte)0xF8 ) ) {
              throw new SmartCardLockedException();
               }
           else {
              // Authentication failed
              return false;
              }
           }
       
       /**
        * Retrieve an ID for this session’s associated smart card.
        */
       protected SmartCardID getSmartCardIDImpl() throws SmartCardException
       {
           // Retrieve a unique ID from the card
           byte [] uniqueCardData = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 
                                             0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b };
           
           // Convert byte array to a long
           SHA1Digest digest = new SHA1Digest();
           digest.update( uniqueCardData );
           byte [] bytesToUse = Arrays.copy( digest.getDigest(), 0, 8 );
           long idLong = CryptoByteArrayArithmetic.valueOf( bytesToUse );
           
           // Using friendly display name
           return new SmartCardID( idLong , ID_STRING, getSmartCard() );
           }
       /**
        *  Retrieve some random data from the smart cards internal Random Number Generator.
        */
       protected byte [] getRandomBytesImpl( int maxBytes ) throws SmartCardException
       {
           // Create a CommandAPDU which your smart card will understand
           CommandAPDU command = new CommandAPDU( (byte)0x00, (byte)0x4C, (byte)0x00, 
                                              (byte)0x00, maxBytes );
           ResponseAPDU response = new ResponseAPDU();
           sendAPDU( command, response );
           
           // Check for response codes specific to your smart card
           if( response.checkStatusWords( (byte)0x90, (byte)0x00 ) ) {
              // The appropriate response code containing the random data
              return response.getData();
              }
           return null;
           }
       
       /**
        * Retrieve certificates from the card.
        * @return An array of certificates which are present on the card.
        */
       protected CryptoSmartCardKeyStoreData[] getKeyStoreDataArrayImpl()
                      throws SmartCardException, CryptoTokenException
                      {
           try {
              // Show a progress dialog to the user as this operation
              //may take a long time.
              displayProgressDialog( WAITING_MSG, 4 );
              // The certificates need to be associated with a particular card.
              SmartCardID smartCardID = getSmartCardID();
              RSACryptoToken token = new MyRSACryptoToken();
              RSACryptoSystem cryptoSystem = new RSACryptoSystem( token, 1024 );
              RSAPrivateKey privateKey;
              CryptoSmartCardKeyStoreData[] keyStoreDataArray = new 
                        CryptoSmartCardKeyStoreData[ 3 ];
              
              // This encoding would be extracted from the card using a series of APDU commands.
              Certificate certificate = null;
              
              // Extract the certificate encoding from the card.
              byte [] certificateEncoding = new byte[0];
              try {
                  certificate = new X509Certificate( certificateEncoding );
                  }
              catch( CertificateParsingException e ) {
                  // invalid X509 certificate 
                  }
              stepProgressDialog( 1 );
              privateKey = new RSAPrivateKey( cryptoSystem, 
                               new MyCryptoTokenData( smartCardID, ID_PKI ) );
              keyStoreDataArray[ 0 ] = new CryptoSmartCardKeyStoreData( null, 
                              ID_CERT, privateKey, null, KeyStore.SECURITY_LEVEL_HIGH, 
                              certificate, null, null, 0 );
              stepProgressDialog( 1 );
              privateKey = new RSAPrivateKey( cryptoSystem, 
                                  new MyCryptoTokenData( smartCardID, SIGNING_PKI ) );
              keyStoreDataArray[ 1 ] = new CryptoSmartCardKeyStoreData( null, SIGNING_CERT, 
                                              privateKey, null, KeyStore.SECURITY_LEVEL_HIGH,
                                              certificate, null, null, 0 );
              stepProgressDialog( 1 );
              privateKey = new RSAPrivateKey( cryptoSystem, new MyCryptoTokenData( 
                                                 smartCardID, ENCRYPTION_PKI ) );
              keyStoreDataArray[ 2 ] = new CryptoSmartCardKeyStoreData( null, ENCRYPTION_CERT, 
                                         privateKey, null, KeyStore.SECURITY_LEVEL_HIGH,  
                                         certificate, null, null, 0 );
              stepProgressDialog( 1 );
              // Sleep so the user sees the last step of the progress dialog move to 100%
              try {
                  Thread.sleep( 250 );
              }
              catch ( InterruptedException e ) {               
               }
              dismissProgressDialog();
                return keyStoreDataArray;
              }
               catch ( CryptoUnsupportedOperationException e ) {
               
               } 
               catch ( UnsupportedCryptoSystemException e ) {
               
               } 
               catch ( CryptoTokenException e ) {
               
               }
               throw new SmartCardException();
              }
       /**
        *Send some data to the smart card for signing or decryption.
        */
       
       /*package*/ 
       void signDecrypt( RSACryptoSystem cryptoSystem,MyCryptoTokenData privateKeyData,
                          byte[] input, int inputOffset,
                        byte[] output, int outputOffset ) 
       throws SmartCardException
       {
           // Check for nulls
           if ( cryptoSystem == null || privateKeyData == null || input == null 
               || output == null) {
              throw new IllegalArgumentException();
              }
           // Validate the input parameters
           int modulusLength = cryptoSystem.getModulusLength();
           if ( ( input.length < inputOffset + modulusLength ) ||
                  ( output.length < outputOffset + modulusLength ) ) {
              throw new IllegalArgumentException();
              }
           
           // Construct the response Application Protocol Data Unit
           ResponseAPDU response = new ResponseAPDU();
           // Construct the command and set its information
           // Create a CommandAPDU which your smart card will understand
           CommandAPDU signAPDU = new CommandAPDU( (byte)0x80, (byte)0x56, (byte)0x00,
                                (byte)0x00, modulusLength );
           signAPDU.setLcData( input, inputOffset, input.length - inputOffset );
           // Send the command to the smartcard
           sendAPDU( signAPDU, response );
           // Validate the status words of the response
           // Check for response codes specific to your smart card
           if ( response.checkStatusWords( (byte)0x90, (byte)0x00 ) ) {
              byte [] responseData = response.getData();
              System.arraycopy( responseData, 0, output, outputOffset,
                     responseData.length );
              }
           else {
              throw new SmartCardException( "Invalid response code, sw1=" + 
                     Integer.toHexString( response.getSW1() & 0xff ) + "sw2="
                     + Integer.toHexString( response.getSW2() & 0xff ) );
              }
           }
       }
启动一个Crypto环
实现的环取决一卡的键类型((RSA, DSA, 或 ECC).参看API参考获得更多信息.
代码实例
下面的例子描述了如何为私有键RSA操作使用一个RSACryptoToken类的扩展.
 
例: MyRSACryptoToken.java
/* MyRSACryptoToken.java
* Copyright (C) 2001-2005 Research In Motion Limited. All rights reserved.
*/
package com.rim.samples.device.smartcard;
import net.rim.device.api.smartcard.*;
import net.rim.device.api.crypto.*;
import net.rim.device.api.crypto.keystore.*;
import net.rim.device.api.util.*;
import net.rim.device.api.crypto.certificate.x509.*;
import net.rim.device.api.crypto.certificate.*;
import net.rim.device.api.crypto.asn1.*;
import net.rim.device.api.compress.*;
import net.rim.device.api.i18n.*;
/**
* This class describes an implmentation of an RSA cryptographic token.
*
* The RIM Crypto API will use this object to perform a private key RSA operation.
* This object should delegate the operation to the smart card.
*/
final class MyRSACryptoToken extends RSACryptoToken implements Persistable
{
    private static final String DECRYPT_DESC = 
       "The private key will be used to decrypt encrypted data.";
    private static final String SIGN_DESC = "The private key will be used to generate a digital signature.";
    
    /**
     * Constructs a new MyRSACryptoToken object.
     */
    MyRSACryptoToken()
    {
       
    }
    
/**
* Determine if this token does the user authentication for the system.
*
* If not the KeyStore will prompt for the key store password when the user
* tries to access the private key.
* 
* @return True if this token will prompt for the necessary
* user authentication when private key access is requested.
*/
public boolean providesUserAuthentication()
{
    return true;
}
/**
* Determine if this token supports the chosen operation using the provided system.
*
* @param cryptoSystem Crypto System to check against.
* @param operation Operation to check: either KEY_GENERATION,
* PUBLIC_KEY_OPERATION, PRIVATE_KEY_OPERATION,* or some other value
* specific to the crypto system that indicates the operation to check.
*/
public boolean isSupported( CryptoSystem cryptoSystem, int operation )
{
    return ( operation == PRIVATE_KEY_OPERATION );   
}
/**
* Determines if the given key and crypto system
* support RSA encryption.
*
* @return True if the token supports RSA encryption.
* @param cryptoSystem Crypto system to check.
* @param privateKeyData Private key data.
* @throws CryptoTokenException If an error occurs with a crypto
* token or the crypto token is invalid.
*/
public boolean isSupportedDecryptRSA( RSACryptoSystem cryptoSystem, CryptoTokenPrivateKeyData privateKeyData )
              throws CryptoTokenException
{
    return privateKeyData instanceof MyCryptoTokenData;
}
/**
* Perform a raw RSA decryption.
*
* @param cryptoSystem Crypto system associated with the token.
* @param privateKeyData RSA private key.
* @param input Input data.
* @param inputOffset First byte of the input data to read.
* @param output Buffer for the output data.
* @param outputOffset Position in the output buffer to receive the first written byte.
*
* @throws CryptoTokenException Thrown if an error occurs with a crypto
* token or the crypto token is invalid.
*/
public void decryptRSA( RSACryptoSystem cryptoSystem,
       CryptoTokenPrivateKeyData privateKeyData,byte[] input, int inputOffset,
       byte[] output, int outputOffset )throws CryptoTokenException
       {
    try 
    {
       signDecryptHelper( cryptoSystem, privateKeyData, input, inputOffset, output, outputOffset, DECRYPT_DESC, SmartCardSession.DECRYPT_OPERATION );
    }
    catch ( CryptoUnsupportedOperationException e ) {
       throw new CryptoTokenException( e.toString() );
       }
    }
/**
* Perform a raw RSA signing.
*
* @param cryptoSystem Cypto system associated with the token.
* @param privateKeyData RSA private key.
* @param input Input data.
* @param inputOffset First byte of the input data to read.
* @param outputOffset Position in the output buffer to receive the first written byte.
* @throws CryptoTokenException If an error occurs with the crypto
* token or the crypto token is invalid.
* @throws CryptoUnsupportedOperationException If a call is made to
* an unsupported operation.
*/
public void signRSA( RSACryptoSystem cryptoSystem, 
       CryptoTokenPrivateKeyData privateKeyData, byte[] input, 
       int inputOffset,byte[] output, int outputOffset )
throws CryptoTokenException, CryptoUnsupportedOperationException
{
    signDecryptHelper( cryptoSystem, privateKeyData, input, inputOffset, 
           output, outputOffset, SIGN_DESC, SmartCardSession.SIGN_OPERATION );
}
/**
* Help signing and decryption operations.
* This helper method assists data signing and decryption because
* the operations are very similar.
*/
private void signDecryptHelper( RSACryptoSystem cryptoSystem,
       CryptoTokenPrivateKeyData privateKeyData, byte[] input, int inputOffset,
       byte[] output, int outputOffset,String accessReason,int operation )
         throws CryptoTokenException, CryptoUnsupportedOperationException
         {
    SmartCardSession smartCardSession = null;
    try {
       if( privateKeyData instanceof MyCryptoTokenData ) {
           SmartCardID smartCardID = ((MyCryptoTokenData) privateKeyData ).getSmartCardID();
           smartCardSession = SmartCardFactory.getSmartCardSession( smartCardID );
           if ( smartCardSession instanceof MyCryptoSmartCardSession ) {
              MyCryptoSmartCardSession mySmartCardSession = 
                  ( MyCryptoSmartCardSession )smartCardSession;
              // We must provide the user authentication since we returned true from
              //providesUserAuthentication()
              // Also, the smart card PIN is required for private key access.
              mySmartCardSession.loginPrompt( accessReason, operation );
              mySmartCardSession.signDecrypt( cryptoSystem,(MyCryptoTokenData)privateKeyData, 
                                             input, inputOffset,  output, outputOffset );
              return;
              }
           }
       throw new RuntimeException();
       }
    catch ( SmartCardSessionClosedException e ) {
       throw new CryptoTokenCancelException( e.toString() );
       }
    catch ( SmartCardCancelException e ) {
       throw new CryptoTokenCancelException( e.toString() );
       }
    catch( SmartCardRemovedException e ) {
       throw new CryptoTokenCancelException( e.toString() );
       }
    catch ( SmartCardException e ) {
       throw new CryptoTokenException( e.toString() );
       }
    finally {
       if ( smartCardSession != null ) {
           smartCardSession.close();
           }
       }
    }
}
存储私有键文件位置
你可以在智能卡的多个位置存储私有键文件.下面的实例描述如何使用一个CryptoTokenPrivateKeyData接口的实现存储智能卡私有键文件的位置.
代码实例
 
例: MyCryptoTokenData.java
/**
* MyCryptoTokenData.java
* Copyright (C) 2001-2005 Research In Motion Limited. All rights reserved.
*/
package com.rim.samples.device.smartcard;
import net.rim.device.api.crypto.*;
import net.rim.device.api.smartcard.*;
import net.rim.device.api.util.*;
/**
* This class stores the location of the private key file on the smart card.
*
*/
final class MyCryptoTokenData implements CryptoTokenPrivateKeyData, Persistable
{
    /**
     *Smart card containing the private key.
     */
    private SmartCardID _id;
    
    /**
     * Location of the private key file on the smart card.
     */
    private byte _file;
    
    /**
     * Constructs a new MyCryptoTokenData object
     *
     *@param id ID of the smart card containing the private key file
     *@param file Location of the private key file.
     */
    public MyCryptoTokenData( SmartCardID id, byte file )
    {
       _id = id;
       _file = file;
    }
    /**
     * Retrieve the ID of the key file containing the private key file.
     *  
     *@return ID of the smart card.
     */
    public SmartCardID getSmartCardID()
    {
       return _id;
    }
    /**
     * Retrieve the location of the private key file on the smart card.
     * 
     * @return Location of the private key file.
     */
    public byte getFile()
    {
       return _file;
    }
}
Last Updated:2007年2月5日
 
                    
                 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号