Android數(shù)據(jù)Rsa加密

———————RSA非對(duì)稱可逆加密———————
RSA加密原理概述:
RSA的安全性依賴于大數(shù)的分解,公鑰和私鑰都是兩個(gè)大素?cái)?shù)(大于100的十進(jìn)制位)的函數(shù)。從一個(gè)密鑰和密文推斷出明文的難度等同于分解兩個(gè)大素?cái)?shù)的積

  • 1.選擇兩個(gè)大素?cái)?shù) p,q ,計(jì)算 n=p*q;
  • 2.隨機(jī)選擇加密密鑰 e ,要求 e 和 (p-1)*(q-1)互質(zhì)
  • 3.利用 Euclid算法計(jì)算解密密鑰 d , 使其滿足 ed = 1(mod(p-1)(q-1)) (其中 n,d 也要互質(zhì))
  • 4:至此得出公鑰為 (n,e) 私鑰為 * (n,d) 加解密方法:
    • 1.首先將要加密的信息 m(二進(jìn)制表示) 分成等長(zhǎng)的
      數(shù)據(jù)塊 m1,m2,…,mi 塊長(zhǎng) s(盡可能大) ,其中2^s< n
    • 2:對(duì)應(yīng)的密文是: ci = mi^e(mod n)
    • 3:解密時(shí)作如下計(jì)算: mi = ci^d(mod n)

RSA速度:
由于進(jìn)行的都是大數(shù)計(jì)算贩挣,使得RSA最快的情況也比DES慢上100倍,無(wú)論 是軟件還是硬件實(shí)現(xiàn)。 速度一直是RSA的缺陷痒蓬。一般來(lái)說(shuō)只用于少量數(shù)據(jù) 加密童擎。

RSAUtils工具類:

package com.example.rsa;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;


public final class RSAUtils
{
    private static String RSA = "RSA";
    private static final String TransForMation = "RSA/None/PKCS1Padding";

    /**
     * 隨機(jī)生成RSA密鑰對(duì)(默認(rèn)密鑰長(zhǎng)度為1024)
     * 
     * @return
     */
    public static KeyPair generateRSAKeyPair()
    {
        return generateRSAKeyPair(1024);
    }

    /**
     * 隨機(jī)生成RSA密鑰對(duì)
     * 
     * @param keyLength
     *            密鑰長(zhǎng)度,范圍:512~2048<br>
     *            一般1024
     * @return
     */
    public static KeyPair generateRSAKeyPair(int keyLength)
    {
        try
        {
            KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);
            kpg.initialize(keyLength);
            return kpg.genKeyPair();
        } catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 用公鑰加密 <br>
     * 每次加密的字節(jié)數(shù)攻晒,不能超過(guò)密鑰的長(zhǎng)度值減去11
     * 
     * @param data
     *            需加密數(shù)據(jù)的byte數(shù)據(jù)
     * @param pubKey
     *            公鑰
     * @return 加密后的byte型數(shù)據(jù)
     */
    public static byte[] encryptData(byte[] data, PublicKey publicKey)
    {
        try
        {
            Cipher cipher = Cipher.getInstance(TransForMation);
            // 編碼前設(shè)定編碼方式及密鑰
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            // 傳入編碼數(shù)據(jù)并返回編碼結(jié)果
            return cipher.doFinal(data);
        } catch (Exception e)
        {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 用私鑰解密
     * 
     * @param encryptedData
     *            經(jīng)過(guò)encryptedData()加密返回的byte數(shù)據(jù)
     * @param privateKey
     *            私鑰
     * @return
     */
    public static byte[] decryptData(byte[] encryptedData, PrivateKey privateKey)
    {
        try
        {
            Cipher cipher = Cipher.getInstance(TransForMation);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return cipher.doFinal(encryptedData);
        } catch (Exception e)
        {
            return null;
        }
    }

    /**
     * 通過(guò)公鑰byte[](publicKey.getEncoded())將公鑰還原顾复,適用于RSA算法
     * 
     * @param keyBytes
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    public static PublicKey getPublicKey(byte[] keyBytes) throws NoSuchAlgorithmException,
            InvalidKeySpecException
    {
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }

    /**
     * 通過(guò)私鑰byte[]將公鑰還原,適用于RSA算法
     * 
     * @param keyBytes
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    public static PrivateKey getPrivateKey(byte[] keyBytes) throws NoSuchAlgorithmException,
            InvalidKeySpecException
    {
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }

    /**
     * 使用N鲁捏、e值還原公鑰
     * 
     * @param modulus
     * @param publicExponent
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    public static PublicKey getPublicKey(String modulus, String publicExponent)
            throws NoSuchAlgorithmException, InvalidKeySpecException
    {
        BigInteger bigIntModulus = new BigInteger(modulus);
        BigInteger bigIntPrivateExponent = new BigInteger(publicExponent);
        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus, bigIntPrivateExponent);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }

    /**
     * 使用N芯砸、d值還原私鑰
     * 
     * @param modulus
     * @param privateExponent
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    public static PrivateKey getPrivateKey(String modulus, String privateExponent)
            throws NoSuchAlgorithmException, InvalidKeySpecException
    {
        BigInteger bigIntModulus = new BigInteger(modulus);
        BigInteger bigIntPrivateExponent = new BigInteger(privateExponent);
        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus, bigIntPrivateExponent);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }

    /**
     * 從字符串中加載公鑰
     * 
     * @param publicKeyStr
     *            公鑰數(shù)據(jù)字符串
     * @throws Exception
     *             加載公鑰時(shí)產(chǎn)生的異常
     */
    public static PublicKey loadPublicKey(String publicKeyStr) throws Exception
    {
        try
        {
            byte[] buffer = Base64Utils.decode(publicKeyStr);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
            return (RSAPublicKey) keyFactory.generatePublic(keySpec);
        } catch (NoSuchAlgorithmException e)
        {
            throw new Exception("無(wú)此算法");
        } catch (InvalidKeySpecException e)
        {
            throw new Exception("公鑰非法");
        } catch (NullPointerException e)
        {
            throw new Exception("公鑰數(shù)據(jù)為空");
        }
    }

    /**
     * 從字符串中加載私鑰<br>
     * 加載時(shí)使用的是PKCS8EncodedKeySpec(PKCS#8編碼的Key指令)。
     * 
     * @param privateKeyStr
     * @return
     * @throws Exception
     */
    public static PrivateKey loadPrivateKey(String privateKeyStr) throws Exception
    {
        try
        {
            byte[] buffer = Base64Utils.decode(privateKeyStr);
            // X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
            return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
        } catch (NoSuchAlgorithmException e)
        {
            throw new Exception("無(wú)此算法");
        } catch (InvalidKeySpecException e)
        {
            throw new Exception("私鑰非法");
        } catch (NullPointerException e)
        {
            throw new Exception("私鑰數(shù)據(jù)為空");
        }
    }

    /**
     * 從文件中輸入流中加載公鑰
     * 
     * @param in
     *            公鑰輸入流
     * @throws Exception
     *             加載公鑰時(shí)產(chǎn)生的異常
     */
    public static PublicKey loadPublicKey(InputStream in) throws Exception
    {
        try
        {
            return loadPublicKey(readKey(in));
        } catch (IOException e)
        {
            throw new Exception("公鑰數(shù)據(jù)流讀取錯(cuò)誤");
        } catch (NullPointerException e)
        {
            throw new Exception("公鑰輸入流為空");
        }
    }

    /**
     * 從文件中加載私鑰
     * 
     * @param keyFileName
     *            私鑰文件名
     * @return 是否成功
     * @throws Exception
     */
    public static PrivateKey loadPrivateKey(InputStream in) throws Exception
    {
        try
        {
            return loadPrivateKey(readKey(in));
        } catch (IOException e)
        {
            throw new Exception("私鑰數(shù)據(jù)讀取錯(cuò)誤");
        } catch (NullPointerException e)
        {
            throw new Exception("私鑰輸入流為空");
        }
    }

    /**
     * 讀取密鑰信息
     * 
     * @param in
     * @return
     * @throws IOException
     */
    private static String readKey(InputStream in) throws IOException
    {
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        String readLine = null;
        StringBuilder sb = new StringBuilder();
        while ((readLine = br.readLine()) != null)
        {
            if (readLine.charAt(0) == '-')
            {
                continue;
            } else
            {
                sb.append(readLine);
                sb.append('\r');
            }
        }

        return sb.toString();
    }

    /**
     * 打印公鑰信息
     * 
     * @param publicKey
     */
    public static void printPublicKeyInfo(PublicKey publicKey)
    {
        RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
        System.out.println("----------RSAPublicKey----------");
        System.out.println("Modulus.length=" + rsaPublicKey.getModulus().bitLength());
        System.out.println("Modulus=" + rsaPublicKey.getModulus().toString());
        System.out.println("PublicExponent.length=" + rsaPublicKey.getPublicExponent().bitLength());
        System.out.println("PublicExponent=" + rsaPublicKey.getPublicExponent().toString());
    }

    public static void printPrivateKeyInfo(PrivateKey privateKey)
    {
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey;
        System.out.println("----------RSAPrivateKey ----------");
        System.out.println("Modulus.length=" + rsaPrivateKey.getModulus().bitLength());
        System.out.println("Modulus=" + rsaPrivateKey.getModulus().toString());
        System.out.println("PrivateExponent.length=" + rsaPrivateKey.getPrivateExponent().bitLength());
        System.out.println("PrivatecExponent=" + rsaPrivateKey.getPrivateExponent().toString());
    }
}

特別說(shuō)明:
1.以上的加解密只是針對(duì)單個(gè)Block塊的给梅,如果需要支持N個(gè)塊假丧,則需要自己?jiǎn)为?dú)對(duì)數(shù)據(jù)進(jìn)行切分。
比如1024位加解密动羽,單個(gè)block的size是128個(gè)字節(jié)包帚。
2.注意密鑰填充方式,這里用的是PKCS1运吓。

更多詳情可以參考:
Android傳輸數(shù)據(jù)時(shí)加密詳解
Android使用RSA加密和解密

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末婴噩,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子羽德,更是在濱河造成了極大的恐慌几莽,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宅静,死亡現(xiàn)場(chǎng)離奇詭異章蚣,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)姨夹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門纤垂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人磷账,你說(shuō)我怎么就攤上這事峭沦。” “怎么了逃糟?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵吼鱼,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我绰咽,道長(zhǎng)菇肃,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任取募,我火速辦了婚禮琐谤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘玩敏。我一直安慰自己斗忌,他們只是感情好质礼,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著织阳,像睡著了一般几苍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上陈哑,一...
    開(kāi)封第一講書(shū)人閱讀 49,760評(píng)論 1 289
  • 那天妻坝,我揣著相機(jī)與錄音,去河邊找鬼惊窖。 笑死刽宪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的界酒。 我是一名探鬼主播圣拄,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼毁欣!你這毒婦竟也來(lái)了庇谆?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤凭疮,失蹤者是張志新(化名)和其女友劉穎饭耳,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體执解,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡寞肖,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了衰腌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片新蟆。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖右蕊,靈堂內(nèi)的尸體忽然破棺而出琼稻,到底是詐尸還是另有隱情,我是刑警寧澤饶囚,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布帕翻,位于F島的核電站,受9級(jí)特大地震影響坯约,放射性物質(zhì)發(fā)生泄漏熊咽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一闹丐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧被因,春花似錦卿拴、人聲如沸衫仑。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)文狱。三九已至,卻和暖如春缘挽,著一層夾襖步出監(jiān)牢的瞬間瞄崇,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工壕曼, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留苏研,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓腮郊,卻偏偏與公主長(zhǎng)得像摹蘑,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子轧飞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348