DES和RSA算法的java實現

1、對稱加密算法

      對稱加密算法是應用較早的加密算法,技術成熟。在對稱加密算法中,數據發信方將明文(原始數據)和加密密鑰一塊兒通過特殊加密算法處理後,使其變成複雜的加密密文發送出去。收信方收到密文後,若想解讀原文,則須要使用加密用過的密鑰及相同算法的逆算法對密文進行解密,才能使其恢復成可讀明文。在對稱加密算法中,使用的密鑰只有一個,發收信雙方都使用這個密鑰對數據進行加密和解密,這就要求解密方事先必須知道加密密鑰。java

      對稱加密算法的優勢是:算法公開、計算量小、加密速度快、加密效率高。缺點是:首先,交易雙方都使用一樣鑰匙,安全性得不到保證。其次,每對用戶每次使用對稱加密算法時,都須要使用其餘人不知道的唯一鑰匙,這會使得發收信雙方所擁有的鑰匙數量呈幾何級數增加,密鑰管理成爲用戶的負擔。對稱加密算法在分佈式網絡系統上使用較爲困難,主要是由於密鑰管理困難,使用成本較高。算法

1.DES算法

      DES算法是最流行的對稱加密算法,全稱是Data Encryption Standard,即數據加密算法,它是IBM公司於1975年研究成功並公開發表的。DES算法的入口參數有三個:Key、Data、Mode。其中Key爲8個字節共64位,是DES算法的工做密鑰;Data也爲8個字節64位,是要被加密或被解密的數據;Mode爲DES的工做方式,有兩種:加密或解密。編程

      能夠對數據進行三次DES算法,從而造成3DES算法。此算法至關因而對每一個數據塊應用三次DES加密算法。因爲計算機運算能力的加強,原版DES密碼的密鑰長度變得容易被暴力破解;3DES便是設計用來提供一種相對簡單的方法,即經過增長DES的密鑰長度來避免相似的攻擊,而不是設計一種全新的塊密碼算法。對此算法的介紹,本文後面再也不贅述。數組

a.算法原理安全

      DES算法把64位的明文輸入塊變爲64位的密文輸出塊,它所使用的密鑰也是64位,其算法主要分爲兩步:網絡

1.初始置換框架

      其功能是把輸入的64位數據塊按位從新組合,並把輸出分爲L0、R0兩部分,每部分各長32位,其置換規則爲將輸入的第58位換到第一位,第50位換到第2位……依此類推,最後一位是原來的第7位。L0、R0則是換位輸出後的兩部分,L0是輸出的左32位,R0是右32位,例:設置換前的輸入值爲D1D2D3……D64,則通過初始置換後的結果爲:L0=D58D50……D8;R0=D57D49……D7。dom

2.逆置換編程語言

      通過16次迭代運算後,獲得L1六、R16,將此做爲輸入,進行逆置換,逆置換正好是初始置換的逆運算,由此即獲得密文輸出。分佈式

b.DES算法在Java中的實現及運用

      Java中爲安全框架提供類和接口。JDK 安全 API 是 Java 編程語言的核心 API,位於 java.security 包(及其子包),以及sun.securityAPI包(及其子包)中。設計用於幫助開發人員在程序中同時使用低級和高級安全功能。

應用實例:

    

    private static int parse(char c) {
        if (c >= 'a')
            return (c - 'a' + 10) & 0x0f;
        if (c >= 'A')
            return (c - 'A' + 10) & 0x0f;
        return (c - '0') & 0x0f;
    }

    // 從十六進制字符串到字節數組轉換
    public static byte[] HexString2Bytes(String hexstr) {
        byte[] b = new byte[hexstr.length() / 2];
        int j = 0;
        for (int i = 0; i < b.length; i++) {
            char c0 = hexstr.charAt(j++);
            char c1 = hexstr.charAt(j++);
            b[i] = (byte) ((parse(c0) << 4) | parse(c1));
        }
        return b;
    }

    private static SecretKey keyGenerator(String keyStr) throws Exception {
        byte input[] = HexString2Bytes(keyStr);
        DESKeySpec desKey = new DESKeySpec(input);
        // 建立一個密匙工廠,而後用它把DESKeySpec轉換成
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey securekey = keyFactory.generateSecret(desKey);
        return securekey;
    }

    // 加密
    public static String encrypt(String data, String key) throws Exception {
        Key deskey = keyGenerator(key);
        // 實例化Cipher對象,它用於完成實際的加密操做
        Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
        SecureRandom random = new SecureRandom();
        // 初始化Cipher對象,設置爲加密模式
        cipher.init(Cipher.ENCRYPT_MODE, deskey, random);
        byte[] results = cipher.doFinal(data.getBytes());
        // 執行加密操做。加密後的結果一般都會用Base64編碼進行傳輸
        return Base64.encodeBase64String(results);
    }

    // 解密
    public static String decrypt(String data, String key) throws Exception {
        Key deskey = keyGenerator(key);
        Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
        // 初始化Cipher對象,設置爲解密模式
        cipher.init(Cipher.DECRYPT_MODE, deskey);
        // 執行解密操做
        return new String(cipher.doFinal(Base64.decodeBase64(data)));
    }

 

2、非對稱加密算法

      非對稱加密算法的核心源於數學問題,它存在公鑰和私鑰的概念,要完成加解密操做,須要兩個密鑰同時參與。

      非對稱密碼體制的特色:算法強度複雜、安全性依賴於算法與密鑰可是因爲其算法複雜,而使得加密解密速度沒有對稱加密解密的速度快。對稱密碼體制中只有一種密鑰,而且是非公開的,若是要解密就得讓對方知道密鑰。因此保證其安全性就是保證密鑰的安全,而非對稱密鑰體制有兩種密鑰,其中一個是公開的,這樣就能夠不須要像對稱密碼那樣傳輸對方的密鑰了。這樣安全性就大了不少。

1.RSA算法

      RSA加密算法是一種典型的非對稱加密算法,它基於大數的因式分解數學難題,它也是應用最普遍的非對稱加密算法,於1978年由美國麻省理工學院(MIT)的三位學着:Ron Rivest、Adi Shamir 和 Leonard Adleman 共同提出。

a.算法原理

      RSA的原理較爲簡單。咱們假設有消息發送方A和消息接收方B,經過下面的幾個步驟,咱們就能夠完成消息的加密傳遞:

         1)消息發送方A在本地構建密鑰對,公鑰和私鑰;

         2)消息發送方A將產生的公鑰發送給消息接收方B;

         3)B向A發送數據時,經過公鑰進行加密,A接收到數據後經過私鑰進行解密,完成一次通訊;

         4)反之,A向B發送數據時,經過私鑰對數據進行加密,B接收到數據後經過公鑰進行解密。

      因爲公鑰是消息發送方A暴露給消息接收方B的,因此這種方式也存在必定的安全隱患,若是公鑰在數據傳輸過程當中泄漏,則A經過私鑰加密的數據就可能被解密。

      若是要創建更安全的加密消息傳遞模型,須要消息發送方和消息接收方各構建一套密鑰對,並分別將各自的公鑰暴露給對方,在進行消息傳遞時,A經過B的公鑰對數據加密,B接收到消息經過B的私鑰進行解密,反之,B經過A的公鑰進行加密,A接收到消息後經過A的私鑰進行解密。

      固然,這種方式可能存在數據傳遞被模擬的隱患,咱們能夠經過數字簽名等技術進行安全性的進一步提高。因爲存在屢次的非對稱加解密,這種方式帶來的效率問題也更加嚴重。

DES算法在Java中的實現及運用:   

 // 用私鑰對信息生成數字簽名
    public static String sign(byte[] data, String privateKey) throws Exception {
        // 解密由base64編碼的私鑰
        byte[] keyBytes = decryptBASE64(privateKey);
        // 構造PKCS8EncodedKeySpec對象
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        // 取私鑰匙對象
        PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
        // 用私鑰對信息生成數字簽名
        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initSign(priKey);
        signature.update(data);
        return encryptBASE64(signature.sign());
    }

    // 校驗數字簽名
    public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {
        // 解密由base64編碼的公鑰
        byte[] keyBytes = decryptBASE64(publicKey);
        // 構造X509EncodedKeySpec對象
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        // 取公鑰匙對象
        PublicKey pubKey = keyFactory.generatePublic(keySpec);
        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initVerify(pubKey);
        signature.update(data);
        // 驗證簽名是否正常
        return signature.verify(decryptBASE64(sign));
    }

    // 對私鑰解密
    public static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception {
        // 對密鑰解密
        byte[] keyBytes = decryptBASE64(key);
        // 取得私鑰
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        // 對數據解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(data);
    }

    // 用公鑰解密
    public static byte[] decryptByPublicKey(byte[] data, String key) throws Exception {
        // 對密鑰解密
        byte[] keyBytes = decryptBASE64(key);
        // 取得公鑰
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        Key publicKey = keyFactory.generatePublic(x509KeySpec);
        // 對數據解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        return cipher.doFinal(data);
    }

    // 用公鑰加密
    public static byte[] encryptByPublicKey(byte[] data, String key) throws Exception {
        // 對公鑰解密
        byte[] keyBytes = decryptBASE64(key);
        // 取得公鑰
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        Key publicKey = keyFactory.generatePublic(x509KeySpec);
        // 對數據加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(data);
    }

    // 用私鑰加密
    public static byte[] encryptByPrivateKey(byte[] data, String key) throws Exception {
        // 對密鑰解密
        byte[] keyBytes = decryptBASE64(key);
        // 取得私鑰
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        // 對數據加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        return cipher.doFinal(data);
    }

    // 取得私鑰
    public static String getPrivateKey(Map<String, Object> keyMap) throws Exception {
        Key key = (Key) keyMap.get("RSAPrivateKey");
        return encryptBASE64(key.getEncoded());
    }

    // 取得公鑰
    public static String getPublicKey(Map<String, Object> keyMap) throws Exception {
        Key key = (Key) keyMap.get("RSAPublicKey");
        return encryptBASE64(key.getEncoded());
    }

    // 初始化密鑰
    public static Map<String, Object> initKey() throws Exception {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        keyPairGen.initialize(1024);
        KeyPair keyPair = keyPairGen.generateKeyPair();
        // 公鑰
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        // 私鑰
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        Map<String, Object> keyMap = new HashMap<String, Object>(2);
        keyMap.put("RSAPublicKey", publicKey);
        keyMap.put("RSAPrivateKey", privateKey);
        return keyMap;
    }
    /**  
     * BASE64解密  
     *   
     * @param key  
     * @return  
     * @throws Exception  
     */    
    public static byte[] decryptBASE64(String key) throws Exception {    
        return (new BASE64Decoder()).decodeBuffer(key);    
    }    
        
    /**  
     * BASE64加密  
     *   
     * @param key  
     * @return        * @throws Exception        */         public static String encryptBASE64(byte[] key) throws Exception {             return (new BASE64Encoder()).encodeBuffer(key);         }    

相關文章
相關標籤/搜索