openssl在java端的加解密和簽名驗證
一、前言
二、openssl下載
三、openssl使用
綠色版bin目錄下openssl.exe開啟執行,有個warning,可以不用理會。
下面命令不需要開啟頭的“openssl”
- 生成私鑰:
openssl genrsa -out rsa_private_key.pem 1024
儲存在當前資料夾下的rsa_private_key.pem檔案中,以下同理。 - 根據私鑰生成公鑰:
openssl rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout
- 此時的私鑰還不能直接被java使用(但可以被openssl使用),需要進行PKCS#8編碼:
openssl pkcs8 -topk8 -in rsa_private_key.pem -out pkcs8_rsa_private_key.pem -nocrypt
- openssl生成簽名檔案:因為java端簽名驗證使用sha1演算法做摘要。故openssl使用sha1簽名:
openssl sha1 -sign rsa_private_key.pem -out rsasign.bin tos.txt
tos.txt為自己建立的需要簽名的文字,裡面可以隨意寫點字元。為了和後面程式碼匹配文字內容為:helloadsfdsfaasdfasffffffffffffdsafdasfasdfsafzxvxzvasfs
四、程式碼參考—— jdk1.5
cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
改為
cipher = Cipher.getInstance("RSA");
本機執行時,起初加解密太慢,去掉BouncyCastleProvider後速度明顯提升。而且加密結果一致,不明所以啊(可能和jdk版本有關)。
DEFAULT_PUBLIC_KEY 為rsa_public_key.pem內容。(去掉空格和換行符,頭尾的—–PUBLIC KEY—–)
DEFAULT_PRIVATE_KEY 內容為pkcs8_rsa_private_key.pem的內容,格式處理同上。
package com.haiyisoft.lwsp.dto.login;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
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.Date;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import sun.misc.BASE64Decoder;
/**
* 生成私鑰:openssl genrsa -out rsa_private_key.pem 1024
* 根據私鑰生成公鑰:openssl rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout
* 私鑰還不能直接被使用,需要進行PKCS#8編碼:openssl pkcs8 -topk8 -in rsa_private_key.pem -out pkcs8_rsa_private_key.pem -nocrypt
* sha1簽名 openssl sha1 -sign rsa_private_key.pem -out rsasign.bin tos.txt
* pkcs8_rsa_private_key 私鑰
* java可以使用
*/
public class RsaEncrypt {
// openssl 產生的鑰 私鑰為pkcs8形式
private final String DEFAULT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxrbbBo9Zkd4uQ16/cx0LJwUJpUHAYHRnSwM8uPgoRkPEXXRFR9sWvZ3WAFdjSB/3KSd8LAK34P8sq49BouUxCJw0h6o2uv0wKIy70k3mTc4KVF12iClPfZR1fQ3FmJrOPr35AiuZTz+YsMp24WageIVz3VZ7qYmzMZ8dH0Ez+ZQIDAQAB";
private final String DEFAULT_PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALGttsGj1mR3i5DXr9zHQsnBQmlQcBgdGdLAzy4+ChGQ8RddEVH2xa9ndYAV2NIH/cpJ3wsArfg/yyrj0Gi5TEInDSHqja6/TAojLvSTeZNzgpUXXaIKU99lHV9DcWYms4+vfkCK5lPP5iwynbhZqB4hXPdVnupibMxnx0fQTP5lAgMBAAECgYBkxQH+pt4kEszb9Afwri5J4Mq6kf1RH8gSiHm4X0U0m0CxIH5/Pvb1OTch0sIqtI+Sl/zg75y7S+r9Q0Fi85y0ghkbLFmmZgv8bGzh4k34WWFCyPMRmexOhsi+IGpTOYkbRnJbycxuY0TXJHHYvEcS0I14fUvI8gbflf12l6DCwQJBANoPXAjHF4TQm0h+qTyFmB4NoGlV3DNH2yk2D2UlKJ+9o7YqjMmw/jNQyeNb65Dj62ij57FQrbn4yfHLBWlkxnECQQDQl7g4kNtDzh0eMMcZYVKU7W/eEkd/G8WeldH26RWE1kZzYBIHeQJiujASDFodM3pqbJ3ssOCizoN1Acy+LPk1AkBvBXjvQyZXSbp1238gwEflrTxpxPw646/SuKJ39cZMJkpu2hUaL1INIGnZpxg1icV2XlT9cz0wPVncEGit81ARAkBkhrnhiO4i31JpGljZgm2qGEOxYl3ShC/ZHZryw6H7QsjxEXue3lKoAdLo38sOB6EXaQEy8ItR6vSvjw59GG+BAkBWwm0ObgH9LJ4eF3ZLCLvViScML3QJr2vAOh3GBsa1avWu/ffD5e3xZGdpmkfEMxWW8nTErFAL46xn8XBLsZqs";
/**
* rsa簽名
*
* @param content
* 待簽名的字串
* @param privateKey
* rsa私鑰字串
* @param charset
* 字元編碼
* @return 簽名結果
* @throws Exception
* 簽名失敗則丟擲異常
*/
public byte[] rsaSign(String content, RSAPrivateKey priKey)
throws SignatureException {
try {
Signature signature = Signature.getInstance("SHA1withRSA");
signature.initSign(priKey);
signature.update(content.getBytes("utf-8"));
byte[] signed = signature.sign();
return signed;
} catch (Exception e) {
throw new SignatureException("RSAcontent = " + content
+ "; charset = ", e);
}
}
/**
* rsa驗籤
*
* @param content
* 被簽名的內容
* @param sign
* 簽名後的結果
* @param publicKey
* rsa公鑰
* @param charset
* 字符集
* @return 驗簽結果
* @throws SignatureException
* 驗籤失敗,則拋異常
*/
boolean doCheck(String content, byte[] sign, RSAPublicKey pubKey)
throws SignatureException {
try {
Signature signature = Signature.getInstance("SHA1withRSA");
signature.initVerify(pubKey);
signature.update(content.getBytes("utf-8"));
return signature.verify((sign));
} catch (Exception e) {
throw new SignatureException("RSA驗證簽名[content = " + content
+ "; charset = " + "; signature = " + sign + "]發生異常!", e);
}
}
/**
* 私鑰
*/
private RSAPrivateKey privateKey;
/**
* 公鑰
*/
private RSAPublicKey publicKey;
/**
* 位元組資料轉字串專用集合
*/
private static final char[] HEX_CHAR = { '0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
/**
* 獲取私鑰
*
* @return 當前的私鑰物件
*/
public RSAPrivateKey getPrivateKey() {
return privateKey;
}
/**
* 獲取公鑰
*
* @return 當前的公鑰物件
*/
public RSAPublicKey getPublicKey() {
return publicKey;
}
/**
* 隨機生成金鑰對
*/
public void genKeyPair() {
KeyPairGenerator keyPairGen = null;
try {
keyPairGen = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
keyPairGen.initialize(1024, new SecureRandom());
KeyPair keyPair = keyPairGen.generateKeyPair();
this.privateKey = (RSAPrivateKey) keyPair.getPrivate();
this.publicKey = (RSAPublicKey) keyPair.getPublic();
}
/**
* 從字串中載入公鑰
*
* @param publicKeyStr
* 公鑰資料字串
* @throws Exception
* 載入公鑰時產生的異常
*/
public void loadPublicKey(String publicKeyStr) throws Exception {
try {
BASE64Decoder base64Decoder = new BASE64Decoder();
byte[] buffer = base64Decoder.decodeBuffer(publicKeyStr);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
this.publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (NoSuchAlgorithmException e) {
throw new Exception("無此演算法");
} catch (InvalidKeySpecException e) {
throw new Exception("公鑰非法");
} catch (IOException e) {
throw new Exception("公鑰資料內容讀取錯誤");
} catch (NullPointerException e) {
throw new Exception("公鑰資料為空");
}
}
/**
* 載入私鑰
*
* @param keyFileName
* 私鑰檔名
* @return 是否成功
* @throws Exception
*/
public void loadPrivateKey(String privateKeyStr) throws Exception {
try {
BASE64Decoder base64Decoder = new BASE64Decoder();
byte[] buffer = base64Decoder.decodeBuffer(privateKeyStr);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
this.privateKey = (RSAPrivateKey) keyFactory
.generatePrivate(keySpec);
} catch (NoSuchAlgorithmException e) {
throw new Exception("無此演算法");
} catch (InvalidKeySpecException e) {
throw new Exception("私鑰非法");
} catch (IOException e) {
throw new Exception("私鑰資料內容讀取錯誤");
} catch (NullPointerException e) {
throw new Exception("私鑰資料為空");
}
}
/**
* 加密過程
*
* @param publicKey
* 公鑰
* @param plainTextData
* 明文資料
* @return
* @throws Exception
* 加密過程中的異常資訊
*/
public byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData)
throws Exception {
if (publicKey == null) {
throw new Exception("加密公鑰為空, 請設定");
}
Cipher cipher = null;
try {
cipher = Cipher.getInstance("RSA");
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 cipherData
* 密文資料
* @return 明文
* @throws Exception
* 解密過程中的異常資訊
*/
public byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData)
throws Exception {
if (privateKey == null) {
throw new Exception("解密私鑰為空, 請設定");
}
Cipher cipher = null;
try {
// , new BouncyCastleProvider()
cipher = Cipher.getInstance("RSA");
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 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();
}
// btye轉換hex函式
public static String ByteToHex(byte[] byteArray) {
StringBuffer StrBuff = new StringBuffer();
for (int i = 0; i < byteArray.length; i++) {
if (Integer.toHexString(0xFF & byteArray[i]).length() == 1) {
StrBuff.append("0").append(
Integer.toHexString(0xFF & byteArray[i]));
} else {
StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
}
}
return StrBuff.toString();
}
/**
* 以位元組為單位讀取檔案,常用於讀二進位制檔案,如圖片、聲音、影像等檔案。
*/
public static byte[] readFileByBytes(String fileName) {
File file = new File(fileName);
InputStream in = null;
byte[] txt = new byte[(int) file.length()];
try {
// 一次讀一個位元組
in = new FileInputStream(file);
int tempbyte;
int i = 0;
while ((tempbyte = in.read()) != -1) {
txt[i] = (byte) tempbyte;
i++;
}
in.close();
return txt;
} catch (IOException e) {
e.printStackTrace();
return txt;
}
}
public static void main(String[] args) {
RsaEncrypt RsaEncrypt = new RsaEncrypt();
// RsaEncrypt.genKeyPair();
// 載入公鑰
try {
RsaEncrypt.loadPublicKey(RsaEncrypt.DEFAULT_PUBLIC_KEY);
System.out.println("載入公鑰成功");
} catch (Exception e) {
System.err.println(e.getMessage());
System.err.println("載入公鑰失敗");
}
// 載入私鑰
try {
RsaEncrypt.loadPrivateKey(RsaEncrypt.DEFAULT_PRIVATE_KEY);
System.out.println("載入私鑰成功");
} catch (Exception e) {
System.err.println(e.getMessage());
System.err.println("載入私鑰失敗");
}
// 測試字串
String encryptStr = "12321dsfasf1321312fsfdsafsdafasfsadf";
try {
System.out.println(new Date());
// 加密
byte[] cipher = RsaEncrypt.encrypt(RsaEncrypt.getPublicKey(),
encryptStr.getBytes());
// 解密
byte[] plainText = RsaEncrypt.decrypt(RsaEncrypt.getPrivateKey(),
cipher);
System.out.println(new Date());
// System.out.println("密文長度:"+ cipher.length);
// System.out.println(RsaEncrypt.byteArrayToString(cipher));
// System.out.println("明文長度:"+ plainText.length);
// System.out.println(RsaEncrypt.byteArrayToString(plainText));
System.out.println(new String(plainText));
// 簽名驗證
byte[] signbyte = RsaEncrypt.rsaSign("helloadsfdsfaasdfasffffffffffffdsafdasfasdfsafzxvxzvasfs",
RsaEncrypt.getPrivateKey());
System.out.println("簽名-----:" + ByteToHex(signbyte));
Boolean isok = RsaEncrypt.doCheck("helloadsfdsfaasdfasffffffffffffdsafdasfasdfsafzxvxzvasfs", signbyte,
RsaEncrypt.getPublicKey());
System.out.println("驗證:" + isok);
// 讀取驗證檔案
byte[] read = readFileByBytes("C:/openssl-1.0.2c-static-x86/bin/rsasign.bin");
System.out.println("讀取簽名檔案:" + ByteToHex(read));
Boolean isfok = RsaEncrypt.doCheck("helloadsfdsfaasdfasffffffffffffdsafdasfasdfsafzxvxzvasfs", read,
RsaEncrypt.getPublicKey());
System.out.println("檔案驗證:" + isfok);
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
相關推薦
openssl在java端的加解密和簽名驗證
一、前言 二、openssl下載 三、openssl使用 綠色版bin目錄下openssl.exe開啟執行,有個warning,可以不用理會。 下面命令不需要開啟頭的“openssl” 生成私鑰:openssl genrsa -out r
基於密鑰庫和數字證書的加密解密和簽名驗證操作
return 產生 初始 www. 數字證書 ray get put 庫文件 package com.szzs; import java.io.FileInputStream; import java.security.KeyStore; import java.sec
RSA加密解密和簽名驗證機制以及其區別和聯絡
https://blog.csdn.net/wangjianno2/article/details/68965299 1.RSA的加密解密機制原理RSA公鑰加密體制包含如下3個演算法:KeyGen(金鑰生成演算法),Encrypt(加密演算法)以及Decrypt(解密演算法)。詳細如下:
[Python3] RSA的加解密和簽名/驗籤實現 -- 使用Crypto
前言 關於非對稱加密演算法我就不過多介紹了,本文著重於python3對RSA演算法的實現。 正文 from Crypto.PublicKey import RSA import Crypto.Signature.PKCS1_v1_5 as sign_PKCS1_v1_5 #用於簽名/
go實現橢圓曲線加解密、簽名驗證演算法(go ecdsa庫的運用),及生成比特幣地址過程講解、base58實現
go實現橢圓曲線加解密、簽名驗證演算法(go ecdsa庫的運用),及生成比特幣地址過程講解、BASE58實現 前言 本文主要講解使用Go的ecdsa庫實現橢圓曲線加解密、簽名、驗證演算法,同時通過公鑰生成比特幣地址,具體程式碼邏輯參考bitcoin0
Fabric ENCChaincode 賬本資料AES256加密解密和簽名驗證
目錄 六、總結 一、加密方式 AES256分組對稱加密是指將明文資料分解為多個16位元組的明文塊,利用金鑰分別對每個明文塊進行加密,得到相同個數的16位元組密文塊,如下圖所示: 如果分解後有明文塊不足16位元組,就需
AES加解密工具類,Android端和服務端加解密一致
別處找的AES工具類太坑,用過之後發現明明祕鑰一致,前端和後端加解密出來的結果卻不一樣。下面這個工具類通過了驗證,祕鑰一致則兩個端的加解密一致。 import java.io.UnsupportedEncodingException; import java.
獲得session_key和openId(加解密、簽名系列)
1:session_key和openId是什麼?session_key 官方說明為: session_key是微信伺服器生成的針對使用者資料進行加密簽名的金鑰 session_key的用途 (1)對wx.getUserInfo()介面得到“使用者資訊中的密文”進行解密。
nodejs中微信公眾號開發-介面配置和簽名驗證
意外金喜的部落格 : http://blog.csdn.net/zzwwjjdj1 -- 建立專案 nodejs微信開發,本文介紹的是在express中使用 express命令列建立專案 :點選這裡, 建立專案 : weixin_ex
區塊鏈教程區塊鏈資訊保安3橢圓曲線加解密及簽名演算法的技術原理一
區塊鏈教程區塊鏈資訊保安3橢圓曲線加解密及簽名演算法的技術原理一,2018年下半年,區塊鏈行業正逐漸褪去發展之初的浮躁、迴歸理性,表面上看相關人才需求與身價似乎正在回落。但事實上,正是初期泡沫的漸退,讓人們更多的關注點放在了區塊鏈真正的技術之上。 橢圓曲線加解密及簽名演算法的技術原理及其Go語言實現
區塊鏈教程區塊鏈信息安全3橢圓曲線加解密及簽名算法的技術原理一
rsa 回歸 語言 集合 規則 區塊 連續 rsa加密 對稱加密 區塊鏈教程區塊鏈信息安全3橢圓曲線加解密及簽名算法的技術原理一,2018年下半年,區塊鏈行業正逐漸褪去發展之初的浮躁、回歸理性,表面上看相關人才需求與身價似乎正在回落。但事實上,正是初期泡沫的漸退,讓人們更多
c語言通過openssl aes對稱加解密和base64編解碼將密碼儲存成密文
今天遇到這樣一個問題,將客戶端中的一個密碼儲存到檔案中以供下次使用,但是儲存的密碼不能直接儲存明文,需要進行加密處理,再三考慮之後,這個加密的過程需要雙向的可逆的過程,MD5等方式是不適用的,因為記住密碼意味著下次我還需要還原這個密碼進行使用,所以最後選擇了openssl的aes演算法,然而ae
RSA加密/解密和簽名/驗簽過程理解
轉自:https://www.jianshu.com/p/8dc4a5f64e06 這裡將A理解為客戶端,B理解為服務端,可以比較好理解. 加解密過程簡述 A和B進行通訊加密,B要先生成一對RSA金鑰,B自己持有私鑰,給A公鑰 --->A使用B的公鑰加密要傳送的內容,然後
Python pycryptodome的加解密、簽名驗籤使用心得
1、載入金鑰 key = Crypto.PublicKey.RSA.import_key(open(key_path).read()) 2、簽名與驗籤 用RSA-PSS using SHA-256舉例 def Rsa256_sign_data(data, rsa_key): try
C#實現RSA公鑰加密私鑰解密、私鑰加密公鑰解密以及Pcks12、X509證書加解密、簽名驗籤
RSA的私鑰簽名公鑰驗籤可以見http://blog.csdn.net/starfd/article/details/51917916,所以這裡就沒提供對應程式碼,具體程式碼如下: using Org.BouncyCastle.Asn1; using Org.B
【開發筆記】支付專案:1、證書加解密、簽名驗籤
最近做到了支付系統,由於對接第三方系統,涉及到證書籤名的問題,就抽時間瞭解了證書、私鑰、公鑰、簽名、驗籤等概念! 一、應用場景 首先需要了解HTTP和HTTPS http就是網路的一種協議,伺服器與伺服器之間的資料互動,就用h
講講在銀聯電子支付工作時加解密、簽名驗籤的那些事(純粹的乾貨)。
今天我們來講講系統間的互動需要哪些必要的東西才能確保互相通訊會沒有問題呢?首先來看看最傳統的系統互動,即兩者直接互相明文傳送,在這種情況下,若是被第三方攔截,會造成不可預估的影響。那麼針對這種情況我們應該如何避免呢?那好,我們來看看銀聯電子支付公司是如何解決這
java加密解密和簽名的問題
注意:加密:先用公鑰加密再用私鑰解密 解密:先用私鑰解密再用公鑰解密 因為公鑰加密長度<127 私鑰》127 關於簽名: debug--除錯 release--釋出--正式簽名--android.keystore 應用升級:包名相同 簽名
RSA加解密及簽名使用介紹
RSA概要介紹 1976年以前,所有的加密方法都是同一種模式: 甲方選擇某一種加密規則,對資訊進行加密; 乙方使用同一種規則,對資訊進行解密 由於加密和解密使用同樣的規則(簡稱“祕鑰”),這種被稱為“對稱加密演算法”。這種加密模式有個最大的弱點:甲方必
RSA加解密與簽名驗籤
1.RSA介紹 1.訊息摘要 如果訊息改變了,那麼改變之後的訊息的指紋和原訊息的指紋將不匹配,如果訊息的指紋和訊息是分開傳送的。那麼接收者就可以檢查訊息是否被篡改過。但是,如果我同時知道了訊息和指