1. 用java編寫一個程序,生成公鑰和私鑰對
一:需要包含的包
import java.security.*;
import java.io.*;
import java.util.*;
import java.security.*;
import java.security.cert.*;
import sun.security.x509.*
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
二:從文件中讀取證書
用keytool將.keystore中的證書寫入文件中,然後從該文件中讀取證書信息
CertificateFactory cf=CertificateFactory.getInstance("X.509");
FileInputStream in=new FileInputStream("out.csr");
Certificate c=cf.generateCertificate(in);
String s=c.toString();
三:從密鑰庫中直接讀取證書
String pass="123456";
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,pass.toCharArray());
java.security.cert.Certificate c=ks.getCertificate(alias);//alias為條目的別名
四:JAVA程序中顯示證書指定信息
System.out.println("輸出證書信息:\n"+c.toString());
System.out.println("版本號:"+t.getVersion());
System.out.println("序列號:"+t.getSerialNumber().toString(16));
System.out.println("主體名:"+t.getSubjectDN());
System.out.println("簽發者:"+t.getIssuerDN());
System.out.println("有效期:"+t.getNotBefore());
System.out.println("簽名演算法:"+t.getSigAlgName());
byte [] sig=t.getSignature();//簽名值
PublicKey pk=t.getPublicKey();
byte [] pkenc=pk.getEncoded();
System.out.println("公鑰");
for(int i=0;i<pkenc.length;i++)System.out.print(pkenc[i]+",");
五:JAVA程序列出密鑰庫所有條目
String pass="123456";
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,pass.toCharArray());
Enumeration e=ks.aliases();
while(e.hasMoreElements())
java.security.cert.Certificate c=ks.getCertificate((String)e.nextElement());
六:JAVA程序修改密鑰庫口令
String oldpass="123456";
String newpass="654321";
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,oldpass.toCharArray());
in.close();
FileOutputStream output=new FileOutputStream(".keystore");
ks.store(output,newpass.toCharArray());
output.close();
七:JAVA程序修改密鑰庫條目的口令及添加條目
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,storepass.toCharArray());
Certificate [] cchain=ks.getCertificate(alias);獲取別名對應條目的證書鏈
PrivateKey pk=(PrivateKey)ks.getKey(alias,oldkeypass.toCharArray());獲取別名對應條目的私鑰
ks.setKeyEntry(alias,pk,newkeypass.toCharArray(),cchain);向密鑰庫中添加條目
第一個參數指定所添加條目的別名,假如使用已存在別名將覆蓋已存在條目,使用新別名將增加一個新條目,第二個參數為條目的私鑰,第三個為設置的新口令,第四個為該私鑰的公鑰的證書鏈
FileOutputStream output=new FileOutputStream("another");
ks.store(output,storepass.toCharArray())將keystore對象內容寫入新文件
八:JAVA程序檢驗別名和刪除條目
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,storepass.toCharArray());
ks.containsAlias("sage");檢驗條目是否在密鑰庫中,存在返回true
ks.deleteEntry("sage");刪除別名對應的條目
FileOutputStream output=new FileOutputStream(".keystore");
ks.store(output,storepass.toCharArray())將keystore對象內容寫入文件,條目刪除成功
九:JAVA程序簽發數字證書
(1)從密鑰庫中讀取CA的證書
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,storepass.toCharArray());
java.security.cert.Certificate c1=ks.getCertificate("caroot");
(2)從密鑰庫中讀取CA的私鑰
PrivateKey caprk=(PrivateKey)ks.getKey(alias,cakeypass.toCharArray());
(3)從CA的證書中提取簽發者的信息
byte[] encod1=c1.getEncoded(); 提取CA證書的編碼
X509CertImpl cimp1=new X509CertImpl(encod1); 用該編碼創建X509CertImpl類型對象
X509CertInfo cinfo1=(X509CertInfo)cimp1.get(X509CertImpl.NAME+"."+X509CertImpl.INFO); 獲取X509CertInfo對象
X500Name issuer=(X500Name)cinfo1.get(X509CertInfo.SUBJECT+"."+CertificateIssuerName.DN_NAME); 獲取X509Name類型的簽發者信息
(4)獲取待簽發的證書
CertificateFactory cf=CertificateFactory.getInstance("X.509");
FileInputStream in2=new FileInputStream("user.csr");
java.security.cert.Certificate c2=cf.generateCertificate(in);
(5)從待簽發的證書中提取證書信息
byte [] encod2=c2.getEncoded();
X509CertImpl cimp2=new X509CertImpl(encod2); 用該編碼創建X509CertImpl類型對象
X509CertInfo cinfo2=(X509CertInfo)cimp2.get(X509CertImpl.NAME+"."+X509CertImpl.INFO); 獲取X509CertInfo對象
(6)設置新證書有效期
Date begindate=new Date(); 獲取當前時間
Date enddate=new Date(begindate.getTime()+3000*24*60*60*1000L); 有效期為3000天
CertificateValidity cv=new CertificateValidity(begindate,enddate); 創建對象
cinfo2.set(X509CertInfo.VALIDITY,cv); 設置有效期
(7)設置新證書序列號
int sn=(int)(begindate.getTime()/1000); 以當前時間為序列號
CertificateSerialNumber csn=new CertificateSerialNumber(sn);
cinfo2.set(X509CertInfo.SERIAL_NUMBER,csn);
(8)設置新證書簽發者
cinfo2.set(X509CertInfo.ISSUER+"."+CertificateIssuerName.DN_NAME,issuer);應用第三步的結果
(9)設置新證書簽名演算法信息
AlgorithmId algorithm=new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
cinfo2.set(CertificateAlgorithmId.NAME+"."+CertificateAlgorithmId.ALGORITHM,algorithm);
(10)創建證書並使用CA的私鑰對其簽名
X509CertImpl newcert=new X509CertImpl(cinfo2);
newcert.sign(caprk,"MD5WithRSA"); 使用CA私鑰對其簽名
(11)將新證書寫入密鑰庫
ks.setCertificateEntry("lf_signed",newcert);
FileOutputStream out=new FileOutputStream("newstore");
ks.store(out,"newpass".toCharArray()); 這里是寫入了新的密鑰庫,也可以使用第七條來增加條目
十:數字證書的檢驗
(1)驗證證書的有效期
(a)獲取X509Certificate類型對象
CertificateFactory cf=CertificateFactory.getInstance("X.509");
FileInputStream in1=new FileInputStream("aa.crt");
java.security.cert.Certificate c1=cf.generateCertificate(in1);
X509Certificate t=(X509Certificate)c1;
in2.close();
(b)獲取日期
Date TimeNow=new Date();
(c)檢驗有效性
try{
t.checkValidity(TimeNow);
System.out.println("OK");
}catch(CertificateExpiredException e){ //過期
System.out.println("Expired");
System.out.println(e.getMessage());
}catch(( e){ //尚未生效
System.out.println("Too early");
System.out.println(e.getMessage());}
(2)驗證證書簽名的有效性
(a)獲取CA證書
CertificateFactory cf=CertificateFactory.getInstance("X.509");
FileInputStream in2=new FileInputStream("caroot.crt");
java.security.cert.Certificate cac=cf.generateCertificate(in2);
in2.close();
(c)獲取CA的公鑰
PublicKey pbk=cac.getPublicKey();
(b)獲取待檢驗的證書(上步已經獲取了,就是C1)
(c)檢驗證書
boolean pass=false;
try{
c1.verify(pbk);
pass=true;
}catch(Exception e){
pass=false;
System.out.println(e);
}
2. JAVA 如何生成證書
下面產生一個自簽證書伍飢。安裝完J2SDK(這里用的是J2SDK1.4)後,在J2SDK安裝目錄的bin目錄下,有一個keytool的可執行程序。利用keytool產生自簽證書的步驟如下:
第一步,用-genkey命令選項,產生公私密鑰對。在控制台界面輸入:keytool -genkey -alias testkeypair -keyalg RSA -keysize 1024 -sigalg MD5withRSA。這里的-alias表示使用這對公私密鑰產生新的keystore入口的別名(keystore是用來存放管理密鑰對和證書鏈的,預設位置是在使用者主目錄下,以.keystore為名的隱藏文件,當然也可指定敏橘罩某個路徑存放.keystore文件);-keyalg是產生公私鑰對所用的演算法,這里是RSA;-keysize定義密鑰的長度;-sigalg是簽名算橋鬧法,選擇MD5withRSA,即用RSA簽名,然後用MD5哈希演算法摘要。接下來,系統會提示進行一些輸入:
輸入keystore密碼: abc123
您的名字與姓氏是什麼?
[Unknown]: Li
您的組織單位名稱是什麼?
&nbs
問題的其他解決辦法參考 :
http://..com/question/41527308.html?a=5.7121119214148&t=JAVA+
3. JAVA公鑰加密,私鑰解密,該怎麼解決
這個是非對稱加密,你可以考慮用RSA加密方法,然後調用密鑰生成函數自動生成公鑰和私鑰,公鑰可以直接發給對方,然後對方用你給的公鑰來進行數據加密,加密的結果送回來只有你的私鑰才能解開,別人都不可以解開。
4. Java通過RSA演算法獲取公私鑰對 將公鑰提供出去 如何獲取字元串的公鑰
直接將公匙BYTE數組轉換為16進制的串啊
private static char hexTable[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
public static String toHexString(byte bytes[])
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++)
{
char chars[] = new char[2];
int d = (bytes[i] & 240) >> 4;
int m = bytes[i] & 15;
chars[0] = hexTable[d];
chars[1] = hexTable[m];
sb.append(chars);
}
return sb.toString();
}
5. java 如果隨機生成秘鑰對並獲取
好像是,..這個你可以將公鑰私鑰放到一個MAP中 在這個MAP中初始化隨即產生器然後生成密鑰對 我也剛接觸 還沒看懂... //生成密鑰
public static Map<String,Object> initKey(String seed) throws Exception{
KeyPairGenerator keygen = KeyPairGenerator.getInstance(ALGORITHM);
//初始化隨機產生器
SecureRandom sr = new SecureRandom();
sr.setSeed(seed.getBytes());
keygen.initialize(KEY_SIZE,sr);
KeyPair keys = keygen.genKeyPair();
DSAPublicKey publicKey = (DSAPublicKey) keys.getPublic();
DSAPrivateKey privateKey = (DSAPrivateKey) keys.getPrivate();
Map<String,Object> map = new HashMap<String,Object>(2);
map.put(PUBLIC_KEY, publicKey);
map.put(PRIVATE_KEY, privateKey);
return map;
}
6. java web系統如何製作License
publicInterfaceLecenseFactory{/***生成公鑰、私鑰對。公鑰公開,注意保管好私鑰(如果泄露,則有可能被hacker隨意創建license*/publicstaticvoidgenerateKey()throwsException;
/**用私鑰對license進行數據簽名*/
(Licenselicense)throwsException;/***驗證license是否合法。
*首先驗證Mac地址是否有改變,有的話則非法。(防止用戶自由拷貝軟體)。
*然後根據公鑰驗證簽名是否合法。*/booleanvalidate(Licenselicense)throwsException;}
License創建及驗證步驟代碼
第一步:生成公鑰、私鑰對。公鑰公開,注意保管好私鑰(如果泄露,則有可能被隨意創建license)。
LicenseFactory.generateKey();
第二步:根據產品、版本、Mac地址、有效期等信息,簽名產生注冊號,並將該注冊號復制到license中。
第三步:利用公鑰對license進行合法性驗證。可以在軟體代碼的重要模塊中加入下面的驗證,比如登錄模塊關鍵字:java, web, security java web系
7. java rsa私鑰加密
java rsa私鑰加密是什麼?讓我們一起來了解一下吧!
java rsa私鑰加密是一種加密演算法。私鑰加密演算法是用私鑰來進行加密與解密信息。私鑰加密也被稱作對稱加密,原因是加密與解密使用的秘鑰是同一個。
RSA加密需要注意的事項如下:
1. 首先產生公鑰與私鑰
2. 設計加密與解密的演算法
3. 私鑰加密的數據信息只能由公鑰可以解密
4. 公鑰加密的數據信息只能由私鑰可以解密
實戰演練,具體步驟如下: public class RsaCryptTools { private static final String CHARSET = "utf-8"; private static final Base64.Decoder decoder64 = Base64.getDecoder(); private static final Base64.Encoder encoder64 = Base64.getEncoder(); /** * 生成公私鑰 * @param keySize * @return * @throws NoSuchAlgorithmException */ public static SecretKey generateSecretKey(int keySize) throws NoSuchAlgorithmException { //生成密鑰對 KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); keyGen.initialize(keySize, new SecureRandom()); KeyPair pair = keyGen.generateKeyPair(); PrivateKey privateKey = pair.getPrivate(); PublicKey publicKey = pair.getPublic(); //這里可以將密鑰對保存到本地 return new SecretKey(encoder64.encodeToString(publicKey.getEncoded()), encoder64.encodeToString(privateKey.getEncoded())); } /** * 私鑰加密 * @param data * @param privateInfoStr * @return * @throws IOException * @throws InvalidCipherTextException */ public static String encryptData(String data, String privateInfoStr) throws IOException, InvalidKeySpecException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, getPrivateKey(privateInfoStr)); return encoder64.encodeToString(cipher.doFinal(data.getBytes(CHARSET))); } /** * 公鑰解密 * @param data * @param publicInfoStr * @return */ public static String decryptData(String data, String publicInfoStr) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException { byte[] encryptDataBytes=decoder64.decode(data.getBytes(CHARSET)); //解密 Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, getPublicKey(publicInfoStr)); return new String(cipher.doFinal(encryptDataBytes), CHARSET); } private static PublicKey getPublicKey(String base64PublicKey) throws NoSuchAlgorithmException, InvalidKeySpecException { X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(base64PublicKey.getBytes())); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePublic(keySpec); } private static PrivateKey getPrivateKey(String base64PrivateKey) throws NoSuchAlgorithmException, InvalidKeySpecException { PrivateKey privateKey = null; PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(base64PrivateKey.getBytes())); KeyFactory keyFactory = null; keyFactory = KeyFactory.getInstance("RSA"); privateKey = keyFactory.generatePrivate(keySpec); return privateKey; } /** * 密鑰實體 * @author hank * @since 2020/2/28 0028 下午 16:27 */ public static class SecretKey { /** * 公鑰 */ private String publicKey; /** * 私鑰 */ private String privateKey; public SecretKey(String publicKey, String privateKey) { this.publicKey = publicKey; this.privateKey = privateKey; } public String getPublicKey() { return publicKey; } public void setPublicKey(String publicKey) { this.publicKey = publicKey; } public String getPrivateKey() { return privateKey; } public void setPrivateKey(String privateKey) { this.privateKey = privateKey; } @Override public String toString() { return "SecretKey{" + "publicKey='" + publicKey + '\'' + ", privateKey='" + privateKey + '\'' + '}'; } } private static void writeToFile(String path, byte[] key) throws IOException { File f = new File(path); f.getParentFile().mkdirs(); try(FileOutputStream fos = new FileOutputStream(f)) { fos.write(key); fos.flush(); } } public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, IOException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException, InvalidKeySpecException { SecretKey secretKey = generateSecretKey(2048); System.out.println(secretKey); String enStr = encryptData("你好測試測試", secretKey.getPrivateKey()); System.out.println(enStr); String deStr = decryptData(enStr, secretKey.getPublicKey()); System.out.println(deStr); enStr = encryptData("你好測試測試hello", secretKey.getPrivateKey()); System.out.println(enStr); deStr = decryptData(enStr, secretKey.getPublicKey()); System.out.println(deStr); } }
8. JAVA公鑰加密,私鑰解密,該怎麼解決
一個比較簡單的實現:一個三個類KeyGenerater生成公鑰私鑰對,Signaturer類使用私鑰簽名,SignProvider用公鑰驗證。公鑰和私鑰使用Base64加密Base64這個類也在博客裡面
public class KeyGenerater {
private byte[] priKey;
private byte[] pubKey;
public void generater() {
try {
Java.security.KeyPairGenerator keygen = java.security.KeyPairGenerator
.getInstance("RSA");
SecureRandom secrand = new SecureRandom();
secrand.setSeed("syj".getBytes()); // 初始化隨機產生器
keygen.initialize(1024, secrand);
KeyPair keys = keygen.genKeyPair();
PublicKey pubkey = keys.getPublic();
PrivateKey prikey = keys.getPrivate();
pubKey = Base64.encodeToByte(pubkey.getEncoded());
priKey = Base64.encodeToByte(prikey.getEncoded());
System.out.println("pubKey = " + new String(pubKey));
System.out.println("priKey = " + new String(priKey));
} catch (java.lang.Exception e) {
System.out.println("生成密鑰對失敗");
e.printStackTrace();
}
}
public byte[] getPriKey() {
return priKey;
}
public byte[] getPubKey() {
return pubKey;
}
}
public class Signaturer {
/**
*
* Description:數字簽名
*
* @param priKeyText
* @param plainText
* @return
* @author 孫鈺佳
* @since:2007-12-27 上午10:51:48
*/
public static byte[] sign(byte[] priKeyText, String plainText) {
try {
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64
.decode(priKeyText));
KeyFactory keyf = KeyFactory.getInstance("RSA");
PrivateKey prikey = keyf.generatePrivate(priPKCS8);
// 用私鑰對信息生成數字簽名
java.security.Signature signet = java.security.Signature
.getInstance("MD5withRSA");
signet.initSign(prikey);
signet.update(plainText.getBytes());
byte[] signed = Base64.encodeToByte(signet.sign());
return signed;
} catch (java.lang.Exception e) {
System.out.println("簽名失敗");
e.printStackTrace();
}
return null;
}
}
public class SignProvider {
private SignProvider() {
}
/**
*
* Description:校驗數字簽名,此方法不會拋出任務異常,成功返回true,失敗返回false,要求全部參數不能為空
*
* @param pubKeyText
* 公鑰,base64編碼
* @param plainText
* 明文
* @param signTest
* 數字簽名的密文,base64編碼
* @return 校驗成功返回true 失敗返回false
* @author 孫鈺佳
* @since:2007-12-27 上午09:33:55
*/
public static boolean verify(byte[] pubKeyText, String plainText,
byte[] signText) {
try {
// 解密由base64編碼的公鑰,並構造X509EncodedKeySpec對象
java.security.spec.X509EncodedKeySpec bobPubKeySpec = new java.security.spec.X509EncodedKeySpec(
Base64.decode(pubKeyText));
// RSA對稱加密演算法
java.security.KeyFactory keyFactory = java.security.KeyFactory
.getInstance("RSA");
// 取公鑰匙對象
java.security.PublicKey pubKey = keyFactory
.generatePublic(bobPubKeySpec);
// 解密由base64編碼的數字簽名
byte[] signed = Base64.decode(signText);
java.security.Signature signatureChecker = java.security.Signature
.getInstance("MD5withRSA");
signatureChecker.initVerify(pubKey);
signatureChecker.update(plainText.getBytes());
// 驗證簽名是否正常
if (signatureChecker.verify(signed))
return true;
else
return false;
} catch (Throwable e) {
System.out.println("校驗簽名失敗");
e.printStackTrace();
return false;
}
}
}
望採納,謝謝。
9. RSA PKCS#1在java中怎麼實現
樓主看看下面的代碼是不是你所需要的,這是我原來用的時候收集的
import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.io.*;
import java.math.BigInteger;
/**
* RSA 工具類。提供加密,解密,生成密鑰對等方法。
* 需要到http://www.bouncycastle.org下載bcprov-jdk14-123.jar。
* RSA加密原理概述
* RSA的安全性依賴於大數的分解,公鑰和私鑰都是兩個大素數(大於100的十進制位)的函數。
* 據猜測,從一個密鑰和密文推斷出明文的難度等同於分解兩個大素數的積
* ===================================================================
* (該演算法的安全性未得到理論的證明)
* ===================================================================
* 密鑰的產生:
* 1.選擇兩個大素數 p,q ,計算 n=p*q;
* 2.隨機選擇加密密鑰 e ,要求 e 和 (p-1)*(q-1)互質
* 3.利用 Euclid 演算法計算解密密鑰 d , 使其滿足 e*d = 1(mod(p-1)*(q-1)) (其中 n,d 也要互質)
* 4:至此得出公鑰為 (n,e) 私鑰為 (n,d)
* ===================================================================
* 加解密方法:
* 1.首先將要加密的信息 m(二進製表示) 分成等長的數據塊 m1,m2,...,mi 塊長 s(盡可能大) ,其中 2^s<n
* 2:對應的密文是: ci = mi^e(mod n)
* 3:解密時作如下計算: mi = ci^d(mod n)
* ===================================================================
* RSA速度
* 由於進行的都是大數計算,使得RSA最快的情況也比DES慢上100倍,無論是軟體還是硬體實現。
* 速度一直是RSA的缺陷。一般來說只用於少量數據加密。
* 文件名:RSAUtil.java<br>
* @author 趙峰<br>
* 版本:1.0.1<br>
* 描述:本演算法摘自網路,是對RSA演算法的實現<br>
* 創建時間:2009-7-10 下午09:58:16<br>
* 文件描述:首先生成兩個大素數,然後根據Euclid演算法生成解密密鑰<br>
*/
public class RSAUtil {
//密鑰對
private KeyPair keyPair = null;
/**
* 初始化密鑰對
*/
public RSAUtil(){
try {
this.keyPair = this.generateKeyPair();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 生成密鑰對
* @return KeyPair
* @throws Exception
*/
private KeyPair generateKeyPair() throws Exception {
try {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA",new org.bouncycastle.jce.provider.BouncyCastleProvider());
//這個值關繫到塊加密的大小,可以更改,但是不要太大,否則效率會低
final int KEY_SIZE = 1024;
keyPairGen.initialize(KEY_SIZE, new SecureRandom());
KeyPair keyPair = keyPairGen.genKeyPair();
return keyPair;
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
/**
* 生成公鑰
* @param molus
* @param publicExponent
* @return RSAPublicKey
* @throws Exception
*/
private RSAPublicKey generateRSAPublicKey(byte[] molus, byte[] publicExponent) throws Exception {
KeyFactory keyFac = null;
try {
keyFac = KeyFactory.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
} catch (NoSuchAlgorithmException ex) {
throw new Exception(ex.getMessage());
}
RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(molus), new BigInteger(publicExponent));
try {
return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);
} catch (InvalidKeySpecException ex) {
throw new Exception(ex.getMessage());
}
}
/**
* 生成私鑰
* @param molus
* @param privateExponent
* @return RSAPrivateKey
* @throws Exception
*/
private RSAPrivateKey generateRSAPrivateKey(byte[] molus, byte[] privateExponent) throws Exception {
KeyFactory keyFac = null;
try {
keyFac = KeyFactory.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
} catch (NoSuchAlgorithmException ex) {
throw new Exception(ex.getMessage());
}
RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(molus), new BigInteger(privateExponent));
try {
return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);
} catch (InvalidKeySpecException ex) {
throw new Exception(ex.getMessage());
}
}
/**
* 加密
* @param key 加密的密鑰
* @param data 待加密的明文數據
* @return 加密後的數據
* @throws Exception
*/
public byte[] encrypt(Key key, byte[] data) throws Exception {
try {
Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE, key);
// 獲得加密塊大小,如:加密前數據為128個byte,而key_size=1024 加密塊大小為127 byte,加密後為128個byte;
// 因此共有2個加密塊,第一個127 byte第二個為1個byte
int blockSize = cipher.getBlockSize();
// System.out.println("blockSize:"+blockSize);
int outputSize = cipher.getOutputSize(data.length);// 獲得加密塊加密後塊大小
// System.out.println("加密塊大小:"+outputSize);
int leavedSize = data.length % blockSize;
// System.out.println("leavedSize:"+leavedSize);
int blocksSize = leavedSize != 0 ? data.length / blockSize + 1 : data.length / blockSize;
byte[] raw = new byte[outputSize * blocksSize];
int i = 0;
while (data.length - i * blockSize > 0) {
if (data.length - i * blockSize > blockSize)
cipher.doFinal(data, i * blockSize, blockSize, raw, i * outputSize);
else
cipher.doFinal(data, i * blockSize, data.length - i * blockSize, raw, i * outputSize);
// 這裡面doUpdate方法不可用,查看源代碼後發現每次doUpdate後並沒有什麼實際動作除了把byte[]放到ByteArrayOutputStream中
// 而最後doFinal的時候才將所有的byte[]進行加密,可是到了此時加密塊大小很可能已經超出了OutputSize所以只好用dofinal方法。
i++;
}
return raw;
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
/**
* 解密
* @param key 解密的密鑰
* @param raw 已經加密的數據
* @return 解密後的明文
* @throws Exception
*/
@SuppressWarnings("static-access")
public byte[] decrypt(Key key, byte[] raw) throws Exception {
try {
Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
cipher.init(cipher.DECRYPT_MODE, key);
int blockSize = cipher.getBlockSize();
ByteArrayOutputStream bout = new ByteArrayOutputStream(64);
int j = 0;
while (raw.length - j * blockSize > 0) {
bout.write(cipher.doFinal(raw, j * blockSize, blockSize));
j++;
}
return bout.toByteArray();
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
/**
* 返回公鑰
* @return
* @throws Exception
*/
public RSAPublicKey getRSAPublicKey() throws Exception{
//獲取公鑰
RSAPublicKey pubKey = (RSAPublicKey) keyPair.getPublic();
//獲取公鑰系數(位元組數組形式)
byte[] pubModBytes = pubKey.getMolus().toByteArray();
//返回公鑰公用指數(位元組數組形式)
byte[] pubPubExpBytes = pubKey.getPublicExponent().toByteArray();
//生成公鑰
RSAPublicKey recoveryPubKey = this.generateRSAPublicKey(pubModBytes,pubPubExpBytes);
return recoveryPubKey;
}
/**
* 獲取私鑰
* @return
* @throws Exception
*/
public RSAPrivateKey getRSAPrivateKey() throws Exception{
// 獲取私鑰
RSAPrivateKey priKey = (RSAPrivateKey) keyPair.getPrivate();
// 返回私鑰系數(位元組數組形式)
byte[] priModBytes = priKey.getMolus().toByteArray();
// 返回私鑰專用指數(位元組數組形式)
byte[] priPriExpBytes = priKey.getPrivateExponent().toByteArray();
// 生成私鑰
RSAPrivateKey recoveryPriKey = this.generateRSAPrivateKey(priModBytes,priPriExpBytes);
return recoveryPriKey;
}
/**
* 測試
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
RSAUtil rsa = new RSAUtil();
String str = "天龍八部、神鵰俠侶、射鵰英雄傳白馬嘯西風";
RSAPublicKey pubKey = rsa.getRSAPublicKey();
RSAPrivateKey priKey = rsa.getRSAPrivateKey();
// System.out.println("加密後==" + new String(rsa.encrypt(pubKey,str.getBytes())));
String mw = new String(rsa.encrypt(pubKey, str.getBytes()));
System.out.println("加密後:"+mw);
// System.out.println("解密後:");
System.out.println("解密後==" + new String(rsa.decrypt(priKey,rsa.encrypt(pubKey,str.getBytes()))));
}
}
10. 我用java的api 生成一對公私鑰,把公鑰給服務端,但java生成的公鑰 是162個位元組, server端 只接收140個
客戶端和服務端都指定編碼格式了嗎?
注意編碼格式,UFt8和gbk等 每種編橡前碼格式獲旦如塌得的位元組數模圓是不一樣的,