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)制表示) 分成等長的
      數(shù)據(jù)塊 m1,m2,…,mi 塊長 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倍,無論 是軟件還是硬件實(shí)現(xiàn)。 速度一直是RSA的缺陷。一般來說只用于少量數(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)密鑰長度為1024)
     * 
     * @return
     */
    public static KeyPair generateRSAKeyPair()
    {
        return generateRSAKeyPair(1024);
    }

    /**
     * 隨機(jī)生成RSA密鑰對(duì)
     * 
     * @param keyLength
     *            密鑰長度,范圍: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ù),不能超過密鑰的長度值減去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)過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;
        }
    }

    /**
     * 通過公鑰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;
    }

    /**
     * 通過私鑰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("無此算法");
        } 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("無此算法");
        } 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());
    }
}

特別說明:
1.以上的加解密只是針對(duì)單個(gè)Block塊的,如果需要支持N個(gè)塊,則需要自己單獨(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)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容