Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> Java Web項目RSA加密,javawebrsa加密

Java Web項目RSA加密,javawebrsa加密

編輯:關於android開發

Java Web項目RSA加密,javawebrsa加密


最近做的一個項目,服務器為Java,采用SSH框架,客戶端為Android和IOS。當用戶登錄時,從客戶端向服務器提交用戶名和密碼。這就存在一個問題,如果數據包在網絡上被其他人截取了,密碼就有可能洩露。

可以采用Base64對密碼編碼,但是Base64要進行解碼是很容易的事。

另一種方法是對密碼進行MD5加密,MD5是不可逆的,只能加密不能解密。但是其他人截取了密碼的MD5字符串以後,可以原封不動的將MD5加密後的字符串提交給服務器,服務器肯定會判斷這是正確的密碼,這樣還是可以登錄進去。

解決的方法就只能采用加密算法了。加密算法分為對稱加密和非對稱加密。對稱加密算法,加密和解密使用相同的密鑰,密鑰在網絡傳輸的過程中有可能被截取,所以不是很安全。非對稱加密,使用公鑰加密,只能使用私鑰解密,公鑰是公開的,私鑰是不公開的。即使在傳遞的過程中,公鑰被其他人獲取了也無所謂,因為公鑰是用來加密的,只有私鑰才能解密,而私鑰是不會傳遞的,也就不可能被其他人獲取。

非對稱加密最常用的就是RSA算法,RSA算法是由羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一起提出的,取了他們姓的第一個字母來命名。RSA算法的原理就不講了。密鑰長度為768的RSA算法有可能被破解,密鑰長度為1024的RSA算法還沒有被破解,所以可以認為密鑰長度為1024的RSA算法是比較安全的。但是RSA算法的計算量大,一般只用於關鍵信息的加密,如密碼、對稱加密算法的密鑰等。在我們的項目中,就使用RSA算法對用戶密碼進行加密。具體的步驟如下:

1. 客戶端向服務器申請密鑰;

2. 服務器接收到客戶端的申請以後,生成一對密鑰,將公鑰發給客戶端,私鑰自己保存;

3. 客戶端接收到公鑰以後,使用公鑰對密碼加密,然後將密文發給服務器;

4. 服務器接收到密文以後,使用私鑰解密,判斷是否是正確的密碼。

下面是關鍵代碼。

生成密鑰和加密、解密的代碼:

/** 
     * 生成公鑰和私鑰 
     * @throws NoSuchAlgorithmException  
     * 
     */  
    public static HashMap<String, Object> getKeys() throws NoSuchAlgorithmException{  
        HashMap<String, Object> map = new HashMap<String, Object>();  
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");  
        keyPairGen.initialize(1024);  
        KeyPair keyPair = keyPairGen.generateKeyPair();  
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();  
        map.put("public", publicKey);  
        map.put("private", privateKey);  
        return map;  
    } 
    
    /** 
     * 使用模和指數生成RSA公鑰 
     * 注意:【此代碼用了默認補位方式,為RSA/None/PKCS1Padding,不同JDK默認的補位方式可能不同,如Android默認是RSA 
     * /None/NoPadding】 
     *  
     * @param modulus 
     *            模 
     * @param exponent 
     *            指數 
     * @return 
     */  
    public static RSAPublicKey getPublicKey(String modulus, String exponent) {  
        try {  
            BigInteger b1 = new BigInteger(modulus);  
            BigInteger b2 = new BigInteger(exponent);  
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");  
            RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2);  
            return (RSAPublicKey) keyFactory.generatePublic(keySpec);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  
  
    /** 
     * 使用模和指數生成RSA私鑰 
     * 注意:【此代碼用了默認補位方式,為RSA/None/PKCS1Padding,不同JDK默認的補位方式可能不同,如Android默認是RSA 
     * /None/NoPadding】 
     *  
     * @param modulus 
     *            模 
     * @param exponent 
     *            指數 
     * @return 
     */  
    public static RSAPrivateKey getPrivateKey(String modulus, String exponent) {  
        try {  
            BigInteger b1 = new BigInteger(modulus);  
            BigInteger b2 = new BigInteger(exponent);  
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");  
            RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(b1, b2);  
            return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  
  
    /** 
     * 公鑰加密 
     *  
     * @param data 
     * @param publicKey 
     * @return 
     * @throws Exception 
     */  
    public static String encryptByPublicKey(String data, RSAPublicKey publicKey)  
            throws Exception {  
        Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");  
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);  
        // 模長  
        int key_len = publicKey.getModulus().bitLength() / 8;  
        // 加密數據長度 <= 模長-11  
        String[] datas = splitString(data, key_len - 11);  
        String mi = "";  
        //如果明文長度大於模長-11則要分組加密  
        for (String s : datas) {  
            mi += bcd2Str(cipher.doFinal(s.getBytes()));  
        }  
        return mi;  
    }  
  
    /** 
     * 私鑰解密 
     *  
     * @param data 
     * @param privateKey 
     * @return 
     * @throws Exception 
     */  
    public static String decryptByPrivateKey(String data, RSAPrivateKey privateKey)  
            throws Exception {  
        Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");  
        cipher.init(Cipher.DECRYPT_MODE, privateKey);  
        //模長  
        int key_len = privateKey.getModulus().bitLength() / 8;  
        byte[] bytes = data.getBytes();  
        byte[] bcd = ASCII_To_BCD(bytes, bytes.length);  
        System.err.println(bcd.length);  
        //如果密文長度大於模長則要分組解密  
        String ming = "";  
        byte[][] arrays = splitArray(bcd, key_len);  
        for(byte[] arr : arrays){  
            ming += new String(cipher.doFinal(arr));  
        }  
        return ming;  
    } 

服務器收到客戶端的請求時,生成一對密鑰:

                HashMap<String, Object> mymap = RSAUtils.getKeys();
                // 生成公鑰和私鑰  
                RSAPublicKey publicKey = (RSAPublicKey) mymap.get("public");  
                RSAPrivateKey privateKey = (RSAPrivateKey) mymap.get("private"); 
                // 模  
                String modulus = publicKey.getModulus().toString();  
                // 公鑰指數  
                String public_exponent = publicKey.getPublicExponent().toString();  
                // 私鑰指數  
                String private_exponent = privateKey.getPrivateExponent().toString(); 
                // 使用模和指數生成公鑰和私鑰  
                RSAPublicKey pubKey = RSAUtils.getPublicKey(modulus, public_exponent);  
                RSAPrivateKey priKey = RSAUtils.getPrivateKey(modulus, private_exponent);

將其中的模和私鑰指數發給客戶端,客戶端收到以後,使用getPrivateKey(String modulus, String exponent)生成私鑰,使用私鑰對密碼加密,然後發給服務器。服務器收到密文以後,使用decryptByPrivateKey(String data, RSAPrivateKey privateKey)解密,獲得密碼明文,然後就可以判斷密碼是否正確。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved