JAVACARD開發基礎規則

參考Java Card & STK Applet Development Guidelines文檔。

  遵從以下規則能夠讓你的程序更加標準化和減少出現問題的可能性。

  1.儘可能使用API,而不是造輪子。

  使用API可以減少重複代碼,而且API可以提供的強大功能。

  2.爲了確保卡的安全性,PIN碼以及祕鑰不能存儲在基本數組中。可以採取以下方法存儲。

複製代碼
OwnerPIN pin; 
Pin = new OwnerPIN (tryLimitApplet, maxPINSizeApplet); 
Pin.update( pinApplet offset, length ) 
Key rsaPrivateKey; 
rsaPrivateKey = (RSAPPrivateKey) KeyBuilder.buildKey 
(KeyBuilder.TYPE_RSA_PRIVATE, KeyBuilder.LENGTH_RSA_512, False); 
rsaPrivateKey.setExponent(bufferExp, offsetExp, lengthExp); 
rsaPrivateKey.setModulus(bufferMod, offsetMod, lengthMod);
複製代碼

  3.敏感的數據應該在會話開始初始化,會話結束後清除,(該規則適用於全局數組,祕鑰更新和會話對象)。

  注意:要重置一個key,需要使用clear()方法,而不是使用0或者其他值覆蓋。因爲使用clear()方法,祕鑰的初始化狀態重置爲false。

複製代碼
sessionflags = 
JCSystem.makeTransientByteArray 
((short)13,JCSystem.CLEAR_ON_RESET); 
sessionflags = 
JCSystem.makeTransientByteArray 
((short)13,JCSystem.CLEAR_ON_DESELECT);
sessionKey = (DESKey)KeyBuilder.buildKey( 
KeyBuilder.TYPE_DES_TRANSIENT_RESET, 
KeyBuilder.LENGTH_DES3_2KEY, 
false); 
sessionKey = (DESKey)KeyBuilder.buildKey( 
KeyBuilder.TYPE_DES_TRANSIENT_DESELECT, 
KeyBuilder.LENGTH_DES3_2KEY, 
false);
複製代碼

   藍色的代碼表示數據會在卡復位的時候清除,即卡斷電或者重啓的時候。而紅色的代碼表示數據會在該應用斷開選擇的時候清除數據。

  4.敏感的數據應該存儲在臨時數據類型中,並且避免存儲在APDU的buffer中。  

sessionflags = 
JCSystem.makeTransientByteArray
((short)13,JCSystem.CLEAR_ON_DESELECT);

  5.保護你的敏感數據,防止回滾攻擊(Rollback attack)

  回滾(Rollback)指的是程序或數據處理錯誤,將程序或數據恢復到上一次正確狀態的行爲。回滾包括程序回滾和數據回滾等類型。

  當你的代碼正在處於transaction(事務,程序執行單元)中突然斷電,卡狀態將會回滾到舊值,攻擊者可以利用這點進行攻擊。當處理敏感數據的時候,一定要引入計數管理器,以應對處理敏感數據時的回滾攻擊。

規則:假如預防機制需要依靠計數器的話,並且該機制需要被管理,需要按照以下行爲進行執行。

  (1)檢查計數器的值,如果被置爲0的話,返回錯誤;

  (2)原子操作(不可打斷)遞減計數器的值;

  (3)驗證這個代碼不處於transaction(事務,程序執行單元);

  (4)運行“try”函數;

  (5)假如“try”運行成功,原子操作增加計數器的值。

  6.所有初始化的buffer,一定要定義爲靜態數據。

  初始化數組定義爲靜態數據有以下好處:

  (1)節省執行時間,在初始化的過程中;

  (2)節省代碼空間;

  (3)在初始化的過程中防止錯誤(transction 緩存滿了)。

  7.全局變量和局部變量

  在javacard應用程序中有許多變量:實例變量(全局變量),在對象初始化的時候創建;局部變量,他只能在申明他們的函數或者快中使用。

一些基本的規則:

  (1)當能夠使用靜態變量的時候,儘量不要使用全局變量。他可以減少類實例的冗餘。

  (2)儘量少使用全局變量。

  (3)不可變的常量必須申明爲static final。

  (4)不要申明太多參數,在一個方法中。非常消耗內存(RAM)。

  (5)局部變量的訪問速度比全局變量快:

     Working variables(像循環計數器,臨時存儲變量),一定要在方法中申明爲局部變量而不是類中的全局變量,這樣可以防止超過NVM的容量;

     Working buffers應該儘可能申明爲transient 數組(可以鎖定在RAM區域),這樣可以避免超過NVM容量限制。假如缺少RAM資源,一定要注意 Working buffers的更新頻率(更新時間點以及更新次數)。

    RAM空間應該需要時才使用,因爲RAM是一個稀缺資源。

  (6)方法參數分解,使用全局變量代替參數,並且傳遞一個對象而不是一個參數列表。

  (7)最大化局部變量使用效率,儘量複用局部變量;

  儘量減少類和對象的數量以及大小,可以有助於解決bug,增強程序可讀性。

  (8)禁止存儲臨時入口對象的引用。

    在javacard標準中指定了一些JCRE的entry point objects(EPO)入口對象。在這些EPOS中,這些臨時的EPO是禁止存儲在類變量、全局變量或則數組陣列中。JCRE檢測和禁止將這些對象的引用存儲在程序中,作爲應用防火牆的一部分。如果這麼做的話系統會拋出安全異常。

    一些主要的臨時EPO:APDU, EnvelopeHandler, ProactiveHandler, EnvelopeResponseHandler, ProactiveResponseHandler 。

    紅色標註的代碼有問題,因爲它使用全局變量來存儲EPO。

複製代碼
public class exampleD8 extends Applet implements
ToolkitInterface {
byte[] apduBuffer;
byte[] envHandler;
void process(APDU apdu){
byte[] buffer;
apduBuffer = apdu.getBuffer();
buffer = apdu.getBuffer();
}
void processToolkit(byte event){
byte[] handler;
envHandler = EnvelopeHandler.getTheHandler();
handler = EnvelopeHandler.getTheHandler();
}
複製代碼

  (9)方法的代碼不要太複雜。

    儘量保持方法的代碼簡單,最大不要超過300個字節。較複雜的方法最好拆分成幾個較小的方法。方法的代碼少可以提高可讀性,並且更容易調試bug。

  (10)確保每個類方法的數量不要超過256個。

    每個類的方法數量限制在256個之內,更多的方法意味着更大的常量池

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章