Java中使用OpenSSL生成公鑰私鑰進行數據加解密

本文參考https://www.cnblogs.com/linjiqin/p/11133435.html,做了簡化,修改了例子中Base64的引用.
當前使用的是Linux系統,已經安裝OpenSSL軟件包
一、使用OpenSSL來生成私鑰和公鑰
1、執行命令openssl version -a 驗證機器上已經安裝openssl
$ openssl version -a
2、生成私鑰
$ openssl genrsa -out rsa_private_key.pem 2048
3、根據私鑰生成公鑰:C:\Users\PC\rsa_public_key.pem
$ openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
注意:此時的私鑰還不能直接被使用,需要進行PKCS#8編碼
4、PKCS#8編碼:指明輸入私鑰文件爲rsa_private_key.pem,輸出私鑰文件爲pkcs8_rsa_private_key.pem,不採用任何二次加密(-nocrypt)
$ openssl pkcs8 -topk8 -in rsa_private_key.pem -out pkcs8_rsa_private_key.pem -nocrypt
至此:可用的密鑰對已經生成好了,私鑰使用pkcs8_rsa_private_key.pem,公鑰採用rsa_public_key.pem
二、java使用
在Linux生成的私鑰 pkcs8_rsa_private_key.pem,公鑰rsa_public_key.pem 文件可以考到windows開發機器上測試.

package ca;
import java.util.Base64;
import java.util.Base64.Encoder;
import java.util.Base64.Decoder;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.;
import java.security.
;
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;

public class RSAEncrypt {
/**

  • 字節數據轉字符串專用集合
    */
    private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6',
    '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    private static final String PRIVATE_KEY = "/pkcs8_rsa_private_key.pem";

    private static final String PUBLIC_KEY = "/rsa_public_key.pem";

    /**

  • 隨機生成密鑰對
    */
    public static void genKeyPair(String filePath) {
    // KeyPairGenerator類用於生成公鑰和私鑰對,基於RSA算法生成對象
    KeyPairGenerator keyPairGen = null;
    try {
    keyPairGen = KeyPairGenerator.getInstance("RSA");
    } catch (NoSuchAlgorithmException e) {
    e.printStackTrace();
    }
    // 初始化密鑰對生成器,密鑰大小爲96-1024位
    keyPairGen.initialize(1024, new SecureRandom());
    // 生成一個密鑰對,保存在keyPair中
    KeyPair keyPair = keyPairGen.generateKeyPair();
    // 得到私鑰
    RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
    // 得到公鑰
    RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
    try {
    // 得到公鑰字符串
    Encoder encoder=Base64.getMimeEncoder();//.getEncoder();
    String publicKeyString =encoder.encodeToString(publicKey.getEncoded());
    // 得到私鑰字符串
    String privateKeyString=encoder.encodeToString(privateKey.getEncoded());
    // 將密鑰對寫入到文件
    FileWriter pubfw = new FileWriter(filePath + PUBLIC_KEY);
    FileWriter prifw = new FileWriter(filePath + PRIVATE_KEY);
    BufferedWriter pubbw = new BufferedWriter(pubfw);
    BufferedWriter pribw = new BufferedWriter(prifw);
    pubbw.write(publicKeyString);
    pribw.write(privateKeyString);
    pubbw.flush();
    pubbw.close();
    pubfw.close();
    pribw.flush();
    pribw.close();
    prifw.close();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    /**

  • 從文件中輸入流中加載公鑰
  • @param path 公鑰輸入流
  • @throws Exception 加載公鑰時產生的異常
    */
    public static String loadPublicKeyByFile(String path) throws Exception {
    try {
    BufferedReader br = new BufferedReader(new FileReader(path

    • PUBLIC_KEY));
      String readLine = null;
      StringBuilder sb = new StringBuilder();
      while ((readLine = br.readLine()) != null) {
      if (readLine.charAt(0) == '-') {
      continue;
      } else {
      sb.append(readLine);
      sb.append('\r');
      }
      }
      br.close();
      return sb.toString();
      } catch (IOException e) {
      throw new Exception("公鑰數據流讀取錯誤");
      } catch (NullPointerException e) {
      throw new Exception("公鑰輸入流爲空");
      }
      }

    /**

  • 從字符串中加載公鑰
  • @param publicKeyStr 公鑰數據字符串
  • @throws Exception 加載公鑰時產生的異常
    */
    public static RSAPublicKey loadPublicKeyByStr(String publicKeyStr)
    throws Exception {
    try {
    Decoder decoder=Base64.getMimeDecoder();
    byte[] buffer =decoder.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("公鑰數據爲空");
    }

    }

    /**

  • 從文件中加載私鑰
  • @param path 私鑰文件名
  • @return 是否成功
  • @throws Exception
    */
    public static String loadPrivateKeyByFile(String path) throws Exception {
    try {
    BufferedReader br = new BufferedReader(new FileReader(path

    • PRIVATE_KEY));
      String readLine = null;
      StringBuilder sb = new StringBuilder();
      while ((readLine = br.readLine()) != null) {
      if (readLine.charAt(0) == '-') {
      continue;
      } else {
      sb.append(readLine);
      sb.append('\r');
      }
      }
      br.close();
      return sb.toString();
      } catch (IOException e) {
      throw new Exception("私鑰數據讀取錯誤");
      } catch (NullPointerException e) {
      throw new Exception("私鑰輸入流爲空");
      }
      }

    public static RSAPrivateKey loadPrivateKeyByStr(String privateKeyStr)
    throws Exception {
    try {
    Decoder decoder=Base64.getMimeDecoder();
    byte[] buffer =decoder.decode(privateKeyStr);

        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("私鑰數據爲空");
    }

    }

    /**

  • 公鑰加密過程
  • @param publicKey 公鑰
  • @param plainTextData 明文數據
  • @return
  • @throws Exception 加密過程中的異常信息
    */
    public static byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData)
    throws Exception {
    if (publicKey == null) {
    throw new Exception("加密公鑰爲空, 請設置");
    }
    Cipher cipher = null;
    try {
    // 使用默認RSA
    cipher = Cipher.getInstance("RSA");
    // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
    cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    byte[] output = cipher.doFinal(plainTextData);
    return output;
    } catch (NoSuchAlgorithmException e) {
    throw new Exception("無此加密算法");
    } catch (NoSuchPaddingException e) {
    e.printStackTrace();
    return null;
    } catch (InvalidKeyException e) {
    throw new Exception("加密公鑰非法,請檢查");
    } catch (IllegalBlockSizeException e) {
    throw new Exception("明文長度非法");
    } catch (BadPaddingException e) {
    throw new Exception("明文數據已損壞");
    }
    }

    /**

  • 私鑰加密過程
  • @param privateKey 私鑰
  • @param plainTextData 明文數據
  • @return
  • @throws Exception 加密過程中的異常信息
    */
    public static byte[] encrypt(RSAPrivateKey privateKey, byte[] plainTextData)
    throws Exception {
    if (privateKey == null) {
    throw new Exception("加密私鑰爲空, 請設置");
    }
    Cipher cipher = null;
    try {
    // 使用默認RSA
    cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, privateKey);
    byte[] output = cipher.doFinal(plainTextData);
    return output;
    } catch (NoSuchAlgorithmException e) {
    throw new Exception("無此加密算法");
    } catch (NoSuchPaddingException e) {
    e.printStackTrace();
    return null;
    } catch (InvalidKeyException e) {
    throw new Exception("加密私鑰非法,請檢查");
    } catch (IllegalBlockSizeException e) {
    throw new Exception("明文長度非法");
    } catch (BadPaddingException e) {
    throw new Exception("明文數據已損壞");
    }
    }

    /**

  • 私鑰解密過程
  • @param privateKey 私鑰
  • @param cipherData 密文數據
  • @return 明文
  • @throws Exception 解密過程中的異常信息
    */
    public static byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData)
    throws Exception {
    if (privateKey == null) {
    throw new Exception("解密私鑰爲空, 請設置");
    }
    Cipher cipher = null;
    try {
    // 使用默認RSA
    cipher = Cipher.getInstance("RSA");
    // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
    cipher.init(Cipher.DECRYPT_MODE, privateKey);
    byte[] output = cipher.doFinal(cipherData);
    return output;
    } catch (NoSuchAlgorithmException e) {
    throw new Exception("無此解密算法");
    } catch (NoSuchPaddingException e) {
    e.printStackTrace();
    return null;
    } catch (InvalidKeyException e) {
    throw new Exception("解密私鑰非法,請檢查");
    } catch (IllegalBlockSizeException e) {
    throw new Exception("密文長度非法");
    } catch (BadPaddingException e) {
    throw new Exception("密文數據已損壞");
    }
    }

    /**

  • 公鑰解密過程
  • @param publicKey 公鑰
  • @param cipherData 密文數據
  • @return 明文
  • @throws Exception 解密過程中的異常信息
    */
    public static byte[] decrypt(RSAPublicKey publicKey, byte[] cipherData)
    throws Exception {
    if (publicKey == null) {
    throw new Exception("解密公鑰爲空, 請設置");
    }
    Cipher cipher = null;
    try {
    // 使用默認RSA
    cipher = Cipher.getInstance("RSA");
    // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
    cipher.init(Cipher.DECRYPT_MODE, publicKey);
    byte[] output = cipher.doFinal(cipherData);
    return output;
    } catch (NoSuchAlgorithmException e) {
    throw new Exception("無此解密算法");
    } catch (NoSuchPaddingException e) {
    e.printStackTrace();
    return null;
    } catch (InvalidKeyException e) {
    throw new Exception("解密公鑰非法,請檢查");
    } catch (IllegalBlockSizeException e) {
    throw new Exception("密文長度非法");
    } catch (BadPaddingException e) {
    throw new Exception("密文數據已損壞");
    }
    }

    /**

  • 字節數據轉十六進制字符串
  • @param data 輸入數據
  • @return 十六進制內容
    */
    public static String byteArrayToString(byte[] data) {
    StringBuilder stringBuilder = new StringBuilder();
    for (int i = 0; i < data.length; i++) {
    // 取出字節的高四位 作爲索引得到相應的十六進制標識符 注意無符號右移
    stringBuilder.append(HEX_CHAR[(data[i] & 0xf0) >>> 4]);
    // 取出字節的低四位 作爲索引得到相應的十六進制標識符
    stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);
    if (i < data.length - 1) {
    stringBuilder.append(' ');
    }
    }
    return stringBuilder.toString();
    }
    }

package ca;
import java.security.PrivateKey;
import java.security.PublicKey;

public class RSASignature {
/**

  • 簽名算法
    */
    public static final String SIGN_ALGORITHMS = "hwU-gARp25KqMFVxw-9J3eCfRNXSN9QM0,ymavRvG0ByPpWEx-IJ{I0DE3w6LMP0fUwKDmSevTpFf=1Q}-h8B,14UGHs4-{flavC";

    /**

  • RSA簽名
  • @param content 待簽名數據
  • @param privateKey 商戶私鑰
  • @param encode 字符集編碼
  • @return 簽名值
    */
    public static String sign(String content, PrivateKey privateKey, String encode) {
    try {
    java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
    signature.initSign(privateKey);
    signature.update(content.getBytes(encode));
    byte[] signed = signature.sign();
    return byte2Hex(signed);
    } catch (Exception e) {
    e.printStackTrace();
    }

    return null;

    }

    public static String sign(String content, PrivateKey privateKey) {
    try {
    java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
    signature.initSign(privateKey);
    signature.update(content.getBytes());
    byte[] signed = signature.sign();
    return byte2Hex(signed);
    } catch (Exception e) {
    e.printStackTrace();
    }
    return null;
    }

    /**

  • 將byte[] 轉換成字符串
    */
    public static String byte2Hex(byte[] srcBytes) {
    StringBuilder hexRetSB = new StringBuilder();
    for (byte b : srcBytes) {
    String hexString = Integer.toHexString(0x00ff & b);
    hexRetSB.append(hexString.length() == 1 ? 0 : "").append(hexString);
    }
    return hexRetSB.toString();
    }

    /**

  • RSA驗簽名檢查
  • @param content 待簽名數據
  • @param sign 簽名值
  • @param publicKey 分配給開發商公鑰
  • @param encode 字符集編碼
  • @return 布爾值
    */
    public static boolean doCheck(String content, String sign, PublicKey publicKey, String encode) {
    try {
    java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);

        signature.initVerify(publicKey);
        signature.update(content.getBytes(encode));
    
        boolean bverify = signature.verify(hex2Bytes(sign));
        return bverify;
    
    } catch (Exception e) {
        e.printStackTrace();
    }
    
    return false;

    }

    public static boolean doCheck(String content, String sign, PublicKey publicKey) {
    try {
    java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
    signature.initVerify(publicKey);
    signature.update(content.getBytes());
    boolean bverify = signature.verify(hex2Bytes(sign));
    return bverify;
    } catch (Exception e) {
    e.printStackTrace();
    }

    return false;

    }

    /**

  • 將16進制字符串轉爲轉換成字符串
    /
    public static byte[] hex2Bytes(String source) {
    byte[] sourceBytes = new byte[source.length() / 2];
    for (int i = 0; i < sourceBytes.length; i++) {
    sourceBytes[i] = (byte) Integer.parseInt(source.substring(i
    2, i * 2 + 2), 16);
    }
    return sourceBytes;
    }
    }

package ca;

import java.util.Base64;
import java.util.Base64.Encoder;
import java.util.Base64.Decoder;

public class ApplicationTests {
public static void main(String[] args) throws Exception {
String publicPath = "D:/testfile/openssl"; //公匙存放位置
String privatePath = "D:/testfile/openssl"; //私匙存放位置

        System.out.println("--------------公鑰加密私鑰解密過程-------------------");
        String signKey = "ihep_公鑰加密私鑰解密";
        // 公鑰加密過程
        byte[] cipherData = RSAEncrypt.encrypt(RSAEncrypt.loadPublicKeyByStr(RSAEncrypt.loadPublicKeyByFile(publicPath)),signKey.getBytes());
        Encoder encoder=Base64.getEncoder();
        String cipher =encoder.encodeToString(cipherData);

        // 私鑰解密過程
        Decoder decoder=Base64.getMimeDecoder();

        byte[] res = RSAEncrypt.decrypt(RSAEncrypt.loadPrivateKeyByStr(RSAEncrypt.loadPrivateKeyByFile(privatePath)), decoder.decode(cipher));
        String restr = new String(res);
        System.out.println("原文:" + signKey);
        System.out.println("加密:" + cipher);
        System.out.println("解密:" + restr);
        System.out.println();

        System.out.println("--------------私鑰加密公鑰解密過程-------------------");
        // 私鑰加密過程
        cipherData = RSAEncrypt.encrypt(RSAEncrypt.loadPrivateKeyByStr(RSAEncrypt.loadPrivateKeyByFile(privatePath)), signKey.getBytes());
        cipher=encoder.encodeToString(cipherData);

        // 公鑰解密過程
        res = RSAEncrypt.decrypt(RSAEncrypt.loadPublicKeyByStr(RSAEncrypt.loadPublicKeyByFile(publicPath)),decoder.decode(cipher));
        restr = new String(res);
        System.out.println("原文:" + signKey);
        System.out.println("加密:" + cipher);
        System.out.println("解密:" + restr);
        System.out.println();
    }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章