RSA加解密及簽名的用法

加密分為對稱加密非對稱加密肛宋, 不可逆加密州藕。

對稱加密
描述: 加密解密使用同樣的密鑰。
特點: 速度快酝陈,安全性一般床玻。
舉例:DES、3DES沉帮、AES
使用場景:對大量數(shù)據(jù)進行加解密锈死。
非對稱加密:
描述:加解密使用不同的密鑰。
特點:速度慢穆壕,安全性較高待牵。
舉例:RSA
使用場景:在對稱加密前,使用非對稱加密傳輸公共的密鑰粱檀。
不可逆加密:
描述:只能加密洲敢,不能解密,加密過程不可逆茄蚯。
特點:不可逆加密压彭。
舉例:md5
使用場景:使用md5(md5(password)),使用雙重不可逆加密對用戶密碼加密渗常,并存入數(shù)據(jù)庫壮不。在驗證用戶密碼的時候,將待驗證的數(shù)據(jù)進行雙重加密后與數(shù)據(jù)庫中的數(shù)據(jù)作比較即可皱碘。

RSA加解密

RSA元素:
公鑰:發(fā)給對方
私鑰:自己保留
說明:
a 公鑰加密后询一,私鑰可以解密。
b 私鑰加密后公鑰可以解密癌椿。
c 私鑰簽名后健蕊,公鑰可以驗簽。
d 密鑰長度一般有:1024bits(128bytes) 2048bits(256bytes) 3072bits 4096bits踢俄。
e 密文長度一般等于密鑰長度缩功。(128bytes 256bytes)
f 待加密數(shù)據(jù)的長度:
RSA_PKCS1_PADDING RSA_size(128bytes) - 11 padding(11bytes) =117bytes
RSA_NO_PADDING RSA_size(128bytes) - 0 = 128bytes
RSA_X931_PADDING RSA_size(128bytes) - 2 padding(2bytes) = 126bytes
常用用法:
a. 公鑰加密,私鑰解密都办。
b. 私鑰加密并簽名嫡锌,公鑰驗簽并解密虑稼。
常見問題:
RSA對待加密的數(shù)據(jù)有長度限制(Data must not be longer than 117 bytes),需要分塊加密势木。
實際應用場景:
1--通信雙方A和B各自生成一對密鑰對(公鑰蛛倦,私鑰)。
2--A和B交換公鑰啦桌。
3--根據(jù)DH算法計算出一個A和B共有的共享密鑰
(原理:shareKey = A_privateKey * B_publicKey = A_publicKey * B_privateKey)溯壶。這只是示意,實際的DH運算是:
設(shè)有這么一個二元組 (q, p) = (3, 7)
我們定義Alice和Bob這么一個運算:
(1)Alice 選擇一個范圍在[1, p-1]的隨機數(shù)震蒋,為da= 5
(2)Alice 計算Pa = q^da mod p = 3^5 mod 7 = 5
(3)Bob選擇一個范圍在[1, p-1]的隨機數(shù)茸塞,為db = 6
(4)Bob計算Pb = q^db mod p = 3^6 mod 7 = 1
(5)Alice和Bob交換Pa和Pb
(6)Alice計算共享密鑰S = Pb ^da mod p = 1^5 mod 7 = 1
(7)Bob計算共享密鑰S = Pa ^db mod p = 5^6 m 7 = 1
4--使用shareKey來進行對稱加密。
有證書應用場景:
1--通信雙方A和B各自生成一對密鑰對(公鑰查剖,私鑰)钾虐。
2--使用證書系統(tǒng)根私鑰對公鑰進行簽名生成公鑰證書A和公鑰證書B。
3--A笋庄,B交換公鑰證書效扫。
4--A和B使用證書系統(tǒng)根證書對公鑰證書進行驗簽。
5--驗簽通過后提取公鑰直砂。
6--根據(jù)DH算法計算出一個A和B共有的共享密鑰
(原理:shareKey = A_privateKey * B_publicKey = A_publicKey * B_privateKey)菌仁。
7--使用shareKey來進行對稱加密。

RSA 加解密實例程序

代碼:

依賴第三方類庫:javabase64-1.3.1.jar
下載地址:https://sourceforge.net/projects/java-base64/files/

Base64Utils.java

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
 
import it.sauronsoftware.base64.Base64;
 
/** *//**
 * <p>
 * BASE64編碼解碼工具包
 * </p>
 * <p>
 * 依賴javabase64-1.3.1.jar
 * </p>
 * 
 * @author IceWee
 * @date 2012-5-19
 * @version 1.0
 */
public class Base64Utils {
 
    /** *//**
     * 文件讀取緩沖區(qū)大小
     */
    private static final int CACHE_SIZE = 1024;
    
    /** *//**
     * <p>
     * BASE64字符串解碼為二進制數(shù)據(jù)
     * </p>
     * 
     * @param base64
     * @return
     * @throws Exception
     */
    public static byte[] decode(String base64) throws Exception {
        return Base64.decode(base64.getBytes());
    }
    
    /** *//**
     * <p>
     * 二進制數(shù)據(jù)編碼為BASE64字符串
     * </p>
     * 
     * @param bytes
     * @return
     * @throws Exception
     */
    public static String encode(byte[] bytes) throws Exception {
        return new String(Base64.encode(bytes));
    }
    
    /** *//**
     * <p>
     * 將文件編碼為BASE64字符串
     * </p>
     * <p>
     * 大文件慎用静暂,可能會導致內(nèi)存溢出
     * </p>
     * 
     * @param filePath 文件絕對路徑
     * @return
     * @throws Exception
     */
    public static String encodeFile(String filePath) throws Exception {
        byte[] bytes = fileToByte(filePath);
        return encode(bytes);
    }
    
    /** *//**
     * <p>
     * BASE64字符串轉(zhuǎn)回文件
     * </p>
     * 
     * @param filePath 文件絕對路徑
     * @param base64 編碼字符串
     * @throws Exception
     */
    public static void decodeToFile(String filePath, String base64) throws Exception {
        byte[] bytes = decode(base64);
        byteArrayToFile(bytes, filePath);
    }
    
    /** *//**
     * <p>
     * 文件轉(zhuǎn)換為二進制數(shù)組
     * </p>
     * 
     * @param filePath 文件路徑
     * @return
     * @throws Exception
     */
    public static byte[] fileToByte(String filePath) throws Exception {
        byte[] data = new byte[0];
        File file = new File(filePath);
        if (file.exists()) {
            FileInputStream in = new FileInputStream(file);
            ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
            byte[] cache = new byte[CACHE_SIZE];
            int nRead = 0;
            while ((nRead = in.read(cache)) != -1) {
                out.write(cache, 0, nRead);
                out.flush();
            }
            out.close();
            in.close();
            data = out.toByteArray();
         }
        return data;
    }
    
    /** *//**
     * <p>
     * 二進制數(shù)據(jù)寫文件
     * </p>
     * 
     * @param bytes 二進制數(shù)據(jù)
     * @param filePath 文件生成目錄
     */
    public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {
        InputStream in = new ByteArrayInputStream(bytes);   
        File destFile = new File(filePath);
        if (!destFile.getParentFile().exists()) {
            destFile.getParentFile().mkdirs();
        }
        destFile.createNewFile();
        OutputStream out = new FileOutputStream(destFile);
        byte[] cache = new byte[CACHE_SIZE];
        int nRead = 0;
        while ((nRead = in.read(cache)) != -1) {   
            out.write(cache, 0, nRead);
            out.flush();
        }
        out.close();
        in.close();
    }
    
    
}
 

RSAUtils.java

改進點:
1 增加了try catch 济丘,不用將異常拋出。這樣可以給類的變量賦值洽蛀。生成密鑰對的時候使用摹迷。
2 增加了將公鑰和私鑰存儲到文件的功能。

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.Key;
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.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

/** *//**
* <p>
* RSA公鑰/私鑰/簽名工具包
* </p>
* <p>
* 羅納德·李維斯特(Ron [R]ivest)郊供、阿迪·薩莫爾(Adi [S]hamir)和倫納德·阿德曼(Leonard [A]dleman)
* </p>
* <p>
* 字符串格式的密鑰在未在特殊說明情況下都為BASE64編碼格式<br/>
* 由于非對稱加密速度極其緩慢峡碉,一般文件不使用它來加密而是使用對稱加密,<br/>
* 非對稱加密算法可以用來對對稱加密的密鑰加密驮审,這樣保證密鑰的安全也就保證了數(shù)據(jù)的安全
* </p>
* 
* @author IceWee
* @date 2012-4-26
* @version 1.0
*/
public class RSAUtils {

   /** *//**
    * 加密算法RSA
    */
   public static final String KEY_ALGORITHM = "RSA";
   
   /** *//**
    * 簽名算法
    */
   public static final String SIGNATURE_ALGORITHM = "MD5withRSA";

   /** *//**
    * 獲取公鑰的key
    */
   private static final String PUBLIC_KEY = "RSAPublicKey";
   
   /** *//**
    * 獲取私鑰的key
    */
   private static final String PRIVATE_KEY = "RSAPrivateKey";
   
   /** *//**
    * RSA最大加密明文大小
    */
   private static final int MAX_ENCRYPT_BLOCK = 117;
   
   /** *//**
    * RSA最大解密密文大小
    */
   private static final int MAX_DECRYPT_BLOCK = 128;


   /** *//**
    * <p>
    * 生成密鑰對(公鑰和私鑰)
    * </p>
    * 
    * @return
    * @throws Exception
    */
   public static Map<String, Object> genKeyPair()  {
       try {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
           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(PUBLIC_KEY, publicKey);
           keyMap.put(PRIVATE_KEY, privateKey);
           return keyMap;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
   }
   
   /** *//**
    * <p>
    * 用私鑰對信息生成數(shù)字簽名
    * </p>
    * 
    * @param data 已加密數(shù)據(jù)
    * @param privateKey 私鑰(BASE64編碼)
    * 
    * @return
    * @throws Exception
    */
   public static String sign(byte[] data, String privateKey)   {
       try {
        byte[] keyBytes = Base64Utils.decode(privateKey);
           PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
           KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
           PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
           Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
           signature.initSign(privateK);
           signature.update(data);
           return Base64Utils.encode(signature.sign());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       return null;
   }

   /** *//**
    * <p>
    * 校驗數(shù)字簽名
    * </p>
    * 
    * @param data 已加密數(shù)據(jù)
    * @param publicKey 公鑰(BASE64編碼)
    * @param sign 數(shù)字簽名
    * 
    * @return
    * @throws Exception
    * 
    */
   public static boolean verify(byte[] data, String publicKey, String sign)
           throws Exception {
       byte[] keyBytes = Base64Utils.decode(publicKey);
       X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
       KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
       PublicKey publicK = keyFactory.generatePublic(keySpec);
       Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
       signature.initVerify(publicK);
       signature.update(data);
       return signature.verify(Base64Utils.decode(sign));
   }

   /** *//**
    * <P>
    * 私鑰解密
    * </p>
    * 
    * @param encryptedData 已加密數(shù)據(jù)
    * @param privateKey 私鑰(BASE64編碼)
    * @return
    * @throws Exception
    */
   public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)
   {
       try {
        byte[] keyBytes = Base64Utils.decode(privateKey);
           PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
           KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
           Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
           Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
           cipher.init(Cipher.DECRYPT_MODE, privateK);
           int inputLen = encryptedData.length;
           ByteArrayOutputStream out = new ByteArrayOutputStream();
           int offSet = 0;
           byte[] cache;
           int i = 0;
           // 對數(shù)據(jù)分段解密
           while (inputLen - offSet > 0) {
               if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                   cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
               } else {
                   cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
               }
               out.write(cache, 0, cache.length);
               i++;
               offSet = i * MAX_DECRYPT_BLOCK;
           }
           byte[] decryptedData = out.toByteArray();
           out.close();
           return decryptedData;
        } catch (InvalidKeyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (BadPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       return null;
   }

   /** *//**
    * <p>
    * 公鑰解密
    * </p>
    * 
    * @param encryptedData 已加密數(shù)據(jù)
    * @param publicKey 公鑰(BASE64編碼)
    * @return
    * @throws Exception
    */
   public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey)
   {
       try {
        byte[] keyBytes = Base64Utils.decode(publicKey);
           X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
           KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
           Key publicK = keyFactory.generatePublic(x509KeySpec);
           Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
           cipher.init(Cipher.DECRYPT_MODE, publicK);
           int inputLen = encryptedData.length;
           ByteArrayOutputStream out = new ByteArrayOutputStream();
           int offSet = 0;
           byte[] cache;
           int i = 0;
           // 對數(shù)據(jù)分段解密
           while (inputLen - offSet > 0) {
               if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                   cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
               } else {
                   cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
               }
               out.write(cache, 0, cache.length);
               i++;
               offSet = i * MAX_DECRYPT_BLOCK;
           }
           byte[] decryptedData = out.toByteArray();
           out.close();
           return decryptedData;
        } catch (InvalidKeyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (BadPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       return null;
   }

   /** *//**
    * <p>
    * 公鑰加密
    * </p>
    * 
    * @param data 源數(shù)據(jù)
    * @param publicKey 公鑰(BASE64編碼)
    * @return
    * @throws Exception
    */
   public static byte[] encryptByPublicKey(byte[] data, String publicKey)
   {

        try {
            byte[] keyBytes = Base64Utils.decode(publicKey);
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            Key publicK = keyFactory.generatePublic(x509KeySpec);
            // 對數(shù)據(jù)加密
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, publicK);
            int inputLen = data.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 對數(shù)據(jù)分段加密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptedData = out.toByteArray();
            out.close();
            return encryptedData;
        } catch (InvalidKeyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (BadPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
   }

   /** *//**
    * <p>
    * 私鑰加密
    * </p>
    * 
    * @param data 源數(shù)據(jù)
    * @param privateKey 私鑰(BASE64編碼)
    * @return
    * @throws Exception
    */
   public static byte[] encryptByPrivateKey(byte[] data, String privateKey)
   {
        try {
            byte[] keyBytes = Base64Utils.decode(privateKey);
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, privateK);
            int inputLen = data.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 對數(shù)據(jù)分段加密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptedData = out.toByteArray();
            out.close();
            return encryptedData;
        } catch (InvalidKeyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (BadPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       return null;
   }

   /** *//**
    * <p>
    * 獲取私鑰
    * </p>
    * 
    * @param keyMap 密鑰對
    * @return
    * @throws Exception
    */
   public static String getPrivateKey(Map<String, Object> keyMap)
   {
        try {
            Key key = (Key) keyMap.get(PRIVATE_KEY);
            return Base64Utils.encode(key.getEncoded());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       return null;
   }

   /** *//**
    * <p>
    * 獲取公鑰
    * </p>
    * 
    * @param keyMap 密鑰對
    * @return
    * @throws Exception
    */
   public static String getPublicKey(Map<String, Object> keyMap)
   {
        try {
            Key key = (Key) keyMap.get(PUBLIC_KEY);
            return Base64Utils.encode(key.getEncoded());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
   }
  
   /** *//**
    * <p>
    * 獲取私鑰
    * </p>
    * 
    * @param privateKeystore 讀取存儲私鑰的文件
    * @return
    * @throws Exception
    */
   public static String readPrivateKeyFile(String privateKeystore)
   {
       
        try {
            StringBuilder privateKey = new StringBuilder();
            FileReader fr = new FileReader(privateKeystore);
            BufferedReader br = new BufferedReader(fr);

            String line;
            while ((line = br.readLine()) != null) {
                privateKey.append(line);
            }
            br.close();
            fr.close();

            return privateKey.toString();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
   }
   
   /** *//**
    * <p>
    * 獲取公鑰
    * </p>
    * 
    * @param publicKeystore 存儲公鑰的文件
    * @return
    * @throws Exception
    */
   public static String readPublicKeyFile(String publicKeystore)
   {
        try {
            StringBuilder publicKey = new StringBuilder();
            FileReader fr = new FileReader(publicKeystore);
            BufferedReader br = new BufferedReader(fr);
            String line;
            while ((line = br.readLine()) != null) {
                publicKey.append(line);
            }
            br.close();
            fr.close();

            return publicKey.toString();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
   }
   
   /** *//**
    * <p>
    *  存儲私鑰到文件
    * </p>
    * 
    * @param privateKey      私鑰字符串
    * @param privateKeystore 存儲私鑰的文件
    * @return
    * @throws Exception
    */
   public static void writePrivateKeyFile(String  privateKey, String privateKeystore)
   {
        try {
            FileWriter fw = new FileWriter(privateKeystore);
            fw.write(privateKey);
            fw.flush();
            fw.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
   }
   
   /** *//**
    * <p>
    * 存儲公鑰到文件
    * </p>
    * 
    * @param publicKey 公鑰文件
    * @param publicKeystore 存儲公鑰的文件
    * @return
    * @throws Exception
    */
   public static void writePublicKeyFile(String publicKey, String publicKeystore)
   {
        try {
            FileWriter fw = new FileWriter(publicKeystore);
            fw.write(publicKey);
            fw.flush();
            fw.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
   }
   
   public static void testEncryptAndSignByPrivateKey(String publicKey, String privateKey) {
       System.err.println("私鑰加密<===>公鑰解密");
       String source = "1. 這是測試通過私鑰加密鲫寄,公鑰解密的測試源數(shù)據(jù)" + 
                       "2. 這是測試通過私鑰加密,公鑰解密的測試源數(shù)據(jù)" +
                       "3. 這是測試通過私鑰加密疯淫,公鑰解密的測試源數(shù)據(jù)" +
                       "4. 這是測試通過私鑰加密地来,公鑰解密的測試源數(shù)據(jù)" +
                       "5. 這是測試通過私鑰加密,公鑰解密的測試源數(shù)據(jù)" +
                       "6. 這是測試通過私鑰加密熙掺,公鑰解密的測試源數(shù)據(jù)" +
                       "7. 這是測試通過私鑰加密未斑,公鑰解密的測試源數(shù)據(jù)" +
                       "8. 這是測試通過私鑰加密,公鑰解密的測試源數(shù)據(jù)" +
                       "9. 這是測試通過私鑰加密适掰,公鑰解密的測試源數(shù)據(jù)" +
                       "10. 這是測試通過私鑰加密颂碧,公鑰解密的測試源數(shù)據(jù)" 
                       ;
       System.out.println("加密前的數(shù)據(jù):\r\n" + source);
       byte[] data = source.getBytes();
       try {
           
           byte[] encodeData = RSAUtils.encryptByPrivateKey(data, privateKey);
           System.out.println("加密后的數(shù)據(jù):\r\n" + new String(encodeData));
           byte[] decodeData = RSAUtils.decryptByPublicKey(encodeData, publicKey);
           System.out.println("解密后的數(shù)據(jù): \r\n" + new String(decodeData));
           System.err.println("私鑰簽名<===>公鑰驗簽");
           String sign = RSAUtils.sign(decodeData, privateKey);
           System.out.println("簽名數(shù)據(jù): \r\n" + sign);
           boolean status = RSAUtils.verify(decodeData, publicKey, sign);
           System.out.println("驗簽結(jié)果:\r\n" + status);
           
       } catch (Exception e) {
            // TODO: handle exception
           e.printStackTrace();
       }
   }

public static void testEncryptByPublicKey(String publicKey, String privateKey) {
       System.err.println("公鑰加密<===>私鑰解密");
       String source = "這是測試公鑰加密,私鑰解密的測試源數(shù)據(jù)";
       System.out.println("加密前的數(shù)據(jù):\r\n" + source);
//       byte[] data = source.getBytes();
       
       try {
           byte[] data = source.getBytes();
           byte[] encodedData = RSAUtils.encryptByPublicKey(data, publicKey);
           System.out.println("加密后的數(shù)據(jù): \r\n" + new String(encodedData));
           
           byte[] decodedData = RSAUtils.decryptByPrivateKey(encodedData, privateKey);
           System.out.println("解密后的數(shù)據(jù): \r\n" + new String(decodedData));
       } catch (Exception e) {
        // TODO Auto-generated catch block
           e.printStackTrace();
       }
   }


   public static void main(String[] args) {
       
       String publicKey;
       String privateKey;
       
       try {
           
           Map<String, Object> keyMap = RSAUtils.genKeyPair();
           publicKey = RSAUtils.getPublicKey(keyMap);
           privateKey = RSAUtils.getPrivateKey(keyMap);
           System.err.println("PublicKey: \r\n" + publicKey);
           System.err.println("PrivateKey: \r\n" + privateKey);
           
           Thread.sleep(100);
           testEncryptByPublicKey(publicKey, privateKey);
           Thread.sleep(100);
           testEncryptAndSignByPrivateKey(publicKey, privateKey);
           
           System.err.println("測試存儲公鑰文件: ");
           String publicKeystore = "D:\\test\\RSA\\publicKey.store";
           writePublicKeyFile(publicKey, publicKeystore);
           System.out.println("write ok");
           Thread.sleep(100);
           System.err.println("測試讀取公鑰文件: ");
           String readPublicKey = readPublicKeyFile(publicKeystore);
           System.out.println("讀取的公鑰文件:\r\n" + readPublicKey);
           
       } catch (Exception e) {
        // TODO: handle exception
           e.printStackTrace();
       }
           
   }

}


程序運行結(jié)果:

image.png

image.png

參考

DH算法:
https://blog.csdn.net/y_xianjun/article/details/81327943
MD5與對稱加密类浪、非對稱加密算法的比較:
https://blog.csdn.net/wangpeng322/article/details/84106548
java對稱加密與非對稱加密(DES载城、AES、RSA的實現(xiàn)):
https://blog.csdn.net/chengbinbbs/article/details/78640589
RSA密鑰長度费就、明文長度和密文長度
https://blog.csdn.net/luoluo_onion/article/details/78354799

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末诉瓦,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子力细,更是在濱河造成了極大的恐慌睬澡,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件眠蚂,死亡現(xiàn)場離奇詭異煞聪,居然都是意外死亡,警方通過查閱死者的電腦和手機逝慧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進店門昔脯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人笛臣,你說我怎么就攤上這事云稚。” “怎么了沈堡?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵静陈,是天一觀的道長。 經(jīng)常有香客問我诞丽,道長鲸拥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任率拒,我火速辦了婚禮崩泡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘猬膨。我一直安慰自己角撞,他們只是感情好,可當我...
    茶點故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布勃痴。 她就那樣靜靜地躺著谒所,像睡著了一般。 火紅的嫁衣襯著肌膚如雪沛申。 梳的紋絲不亂的頭發(fā)上劣领,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天,我揣著相機與錄音铁材,去河邊找鬼尖淘。 笑死奕锌,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的村生。 我是一名探鬼主播惊暴,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼亭引,長吁一口氣:“原來是場噩夢啊……” “哼胀屿!你這毒婦竟也來了如输?” 一聲冷哼從身側(cè)響起踊东,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤知残,失蹤者是張志新(化名)和其女友劉穎都毒,沒想到半個月后评凝,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體坯钦,經(jīng)...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡蟀苛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年益咬,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屹逛。...
    茶點故事閱讀 40,769評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡础废,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出罕模,到底是詐尸還是另有隱情评腺,我是刑警寧澤,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布淑掌,位于F島的核電站蒿讥,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏抛腕。R本人自食惡果不足惜芋绸,卻給世界環(huán)境...
    茶點故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望担敌。 院中可真熱鬧摔敛,春花似錦、人聲如沸全封。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刹悴。三九已至行楞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間土匀,已是汗流浹背子房。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人证杭。 一個月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓田度,卻偏偏與公主長得像,于是被迫代替她去往敵國和親解愤。 傳聞我的和親對象是個殘疾皇子每币,可洞房花燭夜當晚...
    茶點故事閱讀 45,781評論 2 361

推薦閱讀更多精彩內(nèi)容