NO IMAGE

 

PIN加密有3個要素,PIN-KEY,PIN,PAN。
PIN-KEY也就是加密的金鑰,這裡採用的3DES加密,所以PIN-KEY長度要麼是16個位元組要麼是24個位元組,也即是要麼採用128位長金鑰要麼採用192長位元組;PIN也就是要加密的明文,這裡可能是賬戶密碼,也可能是登入密碼的明文;使用PIN加密,在加密之前,首先使用一串數字和PIN異或,然後將異或後的資料拿來進行3DES加密,這樣加密出來的資料就是PIN加密結果。通常每次加密時採用的PAN不一樣。當時解密的時候也需要取得該PAN進行解密。使用策略模式以方便以後擴充套件其他加密演算法。對介面不滿足的可適當通過Adapter調整
實現示例:
/**
 *@(#)EncryRule.java1.02007-10-23
 */
package com.security;
 
/**
 * 資料加密Strategy
 *
 * @author tsimgsong
 * @version 1.0,2007-10-15
 *
 */
public abstract class EncryRule {
      
       /**
        * 明文
        */
       protected String plainText = “”;
      
       /**
        * 密文
        */
       protected String encryedText = “”;
      
       /**
        * 取密文
        * @return String 密文
        */
       public String getEncryedText(){
              return encryedText;
       }
      
       /**
        * 設定密文
        * @param encryedText 密文
        */
       public void setEncryedText(String encryedText) {
              this.encryedText = encryedText;
       }
      
       /**
        * 取明文
        * @return String 明文
        */
       public String getPlainText(){
              return plainText;
       }
      
       /**
        * 設定明文
        * @param plainText 明文
        */
       public void setPlainText(String plainText){
              this.plainText = plainText;
       }
      
       /**
        * 加密操作
        *
        */
       public abstract void encry();
      
       /**
        * 解密操作
        *
        */
       public abstract void deEncry();
}
 
/**
 *@(#)PinEncry.java1.02007-10-23
 */
package com.security;
import java.lang.reflect.Array;
 
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
 
/**
 * PIN碼加密,加密報文通訊中需要傳輸的客戶密碼
 * <br>
 *
 * @author tsimgsong
 * @version 1.0,2007-10-15
 *
 */
public class PinEncry extends EncryRule {
 
       private static boolean initialized = false;
//     金鑰24個位元組,192位
       private static String key_pin ;
//     pin和pan的長度,值域長度為30,前面2位長度表示值域的長度
       private static final int LENGTH_PIN = 32;
       private static final int LENGTH_PAN = 32;
       private static final int LENGTH_PWD = 0;
      
//     加密3DES變數
       private static Cipher cipher = null;
//     解密3DES變數
       private static Cipher deCipher = null;
//     加密演算法
       private static final String ALGORITHM = “DESede”;
      
       private static SecretKey key = null;
       /**
        * “00” 網銀流水號 交易日期 客戶號 操作員編號
        * <br>&nbsp;&nbsp;&nbsp;&nbsp;前面兩位為資料長度,設為定值00,資料30位長,不足左補0,超過30位保留後30個位元組
        */
       private String pan = “”;
       static {
              if (!initialized) {
                     pinEncryInit();
                     initialized = true;
              }
       }
      
       /**
        *初始化加密要素,從資料庫中提取PIN密碼
        *
        */
       private static void pinEncryInit() {
                      System.out.println(“Pin Encry Parameters Initialize complete:success”);
       }
   
       /**
        * 重置加密金鑰,從下次使用該功能時生效
        *
        */
       private static void reset() {
              initialized = false;
              System.out.println(“Reset Pin Encry Parameters”);
              pinEncryInit();
       }
 
       /**
        * PIN碼加密
        * <br>對明文進行3DES加密,沒8個位元組處理一次,對第一個8位元組進行3DES加密,後面每8個位元組都和前面的加密結果進行異或後3DES加密</br>
        *
        */
       public void encry() {
              encryedText = plainText;
              // PIN nor PAN
              byte[] toBeEncry = null;
              toBeEncry = norProcess(plainText, pan);
//            System.out.println(“Before 3DES:” encryedText “Base64:” new sun.misc.BASE64Encoder().encode(encryedText.getBytes()));
              try {                    
//                   明文
//                   密文 存放計算後的資料
                     byte[] encryedData = new byte[toBeEncry.length];
                    
//                   本次需要進行處理的資料 一次最多處理8個位元組
                     byte[] encrying = new byte[8];
                    
//                   3DeS需要以位元組陣列的方式進行加密
                  
              } catch (Exception e) {
                     e.printStackTrace();
 
              }
 
       }
      
       public void deEncry(){
                 byte[] deEncryed = null;
                     try {                    
                           
                            byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(encryedText);     
                            byte[] mDec = new byte[8];
                            deEncryed = new byte[dec.length];
                           
                            System.arraycopy(dec,0,deEncryed,0,dec.length);
                           
                            }
                            encryedText = new sun.misc.BASE64Encoder().encode(deEncryed);
//                          System.out.println(“After De3DES :” encryedText);
                     } catch (Exception e) {
                            e.printStackTrace();
 
                     }
             
             
             
             
              plainText = denorProcess(deEncryed,pan);
       }
      
       /**
        * 資料異或處理<br>
        *
        * @param pin 密碼長度(2Byte) 客戶密碼<br>&nbsp;&nbsp;&nbsp;&nbsp;金鑰最長不超過30位,不足部分右補0
        * @param pan “00” 網銀流水號 交易日期 客戶號 操作員編號
        * <br>&nbsp;&nbsp;&nbsp;&nbsp;前面兩位為資料長度,設為定值00,資料30位長,不足左補0,超過30位保留後30個位元組
        * @return PIN String Block
        */
       private byte[] norProcess(String pin,String pan){
             
//            異或結果存放
        int[] norNum=new int[LENGTH_PIN];
        byte[] norRes = new byte[LENGTH_PIN];
        byte bb;
        String temp = “”;
        String result=””;
//        System.out.println(“PIN:” pin);
//        System.out.println(“PAN:” pan);
//        密碼不足30位右補0
        for(int i = pin.length() ;i <LENGTH_PIN ;i ){
               pin = pin “0”;
        }
//        pan不足30位左補0
        for(int i = pan.length() ;i<LENGTH_PAN ;i ){
               pan = “0” pan;
        }
//        pan超過30位去後30位
        if(pan.length() > LENGTH_PAN){
               pan = pan.substring(pan.length()-LENGTH_PAN,pan.length());
        }
 
        for(int i=0;i<LENGTH_PIN;i ){
             norRes[i] =(byte) (pin.charAt(i)^pan.charAt(i));
        }
//        System.out.print(“Nor Result:”);
//        for(int i = 0 ;i<norRes.length ;i ){
//             System.out.print(Integer.toHexString(norRes[i]) ” “);
//        }
//        System.out.println();
        return norRes;//new String(norRes);
    }
 
       /**
        * 異或結果還原處理
        *
        * @param norStr 異或值
        * @param pan “00” 交易日期 交易時間 客戶號 操作員編號
        * <br>&nbsp;&nbsp;&nbsp;&nbsp;前面兩位為資料長度,設為定值00,資料30位長,不足左補0,超過30位保留後30個位元組
        * @return String 異或原串
        */
 private String denorProcess(byte[] norStr,String pan){
        byte[] snNum=norStr;
       
        String result=””;
       
//      pan不足30位左補0
        for(int i = pan.length() ;i<LENGTH_PAN ;i ){
               pan = “0” pan;
        }
       
//        pan超過30位去後30位
        if (pan.length() > LENGTH_PAN) {
                     pan = pan.substring(pan.length() – LENGTH_PAN, pan.length());
              }
             
        int n = 0;
        for(int i=0;i<norStr.length;i ){
            snNum[i]=(byte)(norStr[i]^pan.charAt(i));
        }
 
        for(int k=0;k< norStr.length;k ){
            result =(char)snNum[k];
        }
//        System.out.println(“DeNcry result:” result);
        return result;
    }
 
 /**
   * 取Pan值
   * @return String
   */
       public String getPan() {
              return pan;
       }
      
       /**
        * 設定Pan值
        * @param pan
        */
       public void setPan(String pan) {
              this.pan = pan;
       }
 
 
}
 
/**
 *@(#)PinEncry.java1.02007-10-23
 */
Package com.security;
/**
 * 資料加密策略
 *
 * @author tsimgsong
 * @version 1.0,2007-10-15
 *
 */
public class EncrySolve {
      
//     加密策略
       static EncryRule rule ;
      
       /**
        * 加密運算
        * @param r 加密策略
        * @param plainText 明文
        * @return String 加密後資料
        */
       public static String encry(EncryRule r,String plainText){
              rule = r;
              rule.setPlainText(plainText);
              rule.encry();
              return rule.getEncryedText();
       }
      
       /**
        * 解密運算
        * @param r 解密策略
        * @param encryedText 密文
        * @return String 明文
        */
       public static String deEncry(EncryRule r,String encryedText){
              rule = r;
              rule.setEncryedText(encryedText);
              rule.deEncry();
              return rule.getPlainText();
       }
      
       /**
        * 取密文
        * @return
        */
       public String getEncryedText(){
              return rule.getEncryedText();
       }
      
       /**
        * 取明文
        * @return
        */
       public String getPlainText(){
              return rule.getPlainText();
       }
 
}
Junit測試:
PinEncry pe = new PinEncry();
              String passwd = “000001”;
              int length_passwd = passwd.length() ;
              if(length_passwd<10){
                     passwd = “0” length_passwd passwd;
              }else{
                   passwd = “” length_passwd passwd;
              }
              PinEncry pe = new PinEncry();
//            組織Pan值 交易日期YYYYMMDD 企業客戶號 操作員編號
              String pan = “00”;
              pan = “383090020071022799070001”;
              pe.setPan(pan);
加密:   
              passwd = (EncrySolve.encry(pe,passwd)); 
        assertEquals(‘X065VL nZV6/jP8XjJq6FmMH18egeDW852gA2RzTF0Q=’,passwd);
       解密:
passwd=EncrySolve.deEncry(pe,”X065VL nZV6/jP8XjJq6FmMH18egeDW852gA2RzTF0Q=”);
loger.debug(passwd);
 
密碼進行加密之前必須計算出密碼原文的長度,並以兩個位元組的長度放置在明文的前面,後面根據密碼的長度進行擷取。加密後的資料進行了Base64編碼。
3DES演算法就是進行了3次DES計算,用第一個金鑰進行一次加密,用第二個金鑰進行一次解密,之後再用第3個金鑰進行一次加密,DES加密的金鑰長度是64位,如果採用192位密碼加密,那個三個金鑰分別取依次的64位,如果採用128位金鑰,第一個和第三個的金鑰相同