Java安全學習筆記(十一)-RSA演算法加密和解密
RSA演算法是使用整數進行加密和解密運算的,
加密:在RSA公鑰中包含了兩個資訊:公鑰對應的整數e和用於取模的整數n。對於明文數字m,計算密文的公式是: m^e mod n.
解密:跟加密類似,私鑰對應的指數e和用於取模的整數m.其中模m和加密時的加密的模n完全相同。對於密文數字d,計算公式d^e mod n。加密和解密最大的不同在於冪e不同。
本例項以加密和解密一個字串”I am a student” 為例,演示瞭如何使用生成的RSA公鑰檔案進行加密。
使用RSA演算法加密的技術要點如下:
1.用FileInputStream獲取公鑰
2.用RSAPublicKey類中的方法獲取公鑰的引數(e,n)
3.用BigInteger m=new BigInteger(ptext);來獲取明文整數(m)
4.執行計算
使用RSA演算法解密的技術要點如下:
1.利用FileInputStream讀取密文Enc_RSA.dat
2.利用RSAPrivateKey類的readObject()方法獲取私鑰
3.利用RSAPrivateKey類獲取私鑰的BigInteger型別的引數(e,m)
4.利用BigInteger的modPow()方法執行解密的計算
5.解析出明文整型數對應的字串
package core;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStreamWriter;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
/**
* RSA演算法加密和解密
* */
public class Password_Test {
public static void main (String[] args) {
try {
new Password_Test();
Encryption_RSA();
Decryption_RSA();
} catch (Exception e) {
e.printStackTrace();
}
}
public Password_Test() throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");// 生成實現RSA演算法的KeyPairGenerator物件
kpg.initialize(1024);// 初始化確定金鑰的大小
KeyPair kp = kpg.generateKeyPair();// 生成金鑰對
PublicKey pbkey = kp.getPublic();// 建立公鑰
PrivateKey prkey = kp.getPrivate();// 建立私鑰
/* 儲存公鑰和私鑰 */
// 儲存公鑰
FileOutputStream file1 = new FileOutputStream("Skey_RSA_pub.dat");
ObjectOutputStream ob1 = new ObjectOutputStream(file1);// 建立ObjectOutputStream
ob1.writeObject(pbkey);
// 儲存私鑰
FileOutputStream file2 = new FileOutputStream("Skey_RSA_priv.dat");
ObjectOutputStream ob2 = new ObjectOutputStream(file2);// 建立ObjectOutputStream
ob2.writeObject(prkey);
//關閉流
ob1.close();
ob2.close();
}
public static void Encryption_RSA() throws Exception{
System.out.println("根據公鑰生成密文:");
String string="I am a student";
//獲取公鑰
FileInputStream f_in=new FileInputStream("Skey_RSA_pub.dat");
ObjectInputStream o_in=new ObjectInputStream(f_in);
RSAPublicKey pbk=(RSAPublicKey) o_in.readObject();
//獲取引數e,n
BigInteger e=pbk.getPublicExponent();//返回此公鑰的指數
BigInteger n=pbk.getModulus();//返回此公鑰的模
System.out.println("公鑰的指數 e="+e);
System.out.println("公鑰的模 n="+n);
//明文 bit
byte bt[]=string.getBytes("UTF8");
BigInteger bit=new BigInteger(bt);
//計算密文c,列印
BigInteger c=bit.modPow(e, n);
System.out.println("生成密文為: "+ c+"\n");
//儲存密文
String save=c.toString();
BufferedWriter out=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("Enc_RSA.dat")));//儲存密文
out.write(save, 0, save.length());
o_in.close();
out.close();
}
public static void Decryption_RSA() throws Exception{
System.out.println("根據私鑰破解密文");
//讀取密文
BufferedReader in=new BufferedReader(new InputStreamReader(new FileInputStream("Enc_RSA.dat")));
String ctext=in.readLine();
BigInteger d=new BigInteger(ctext);
//讀取私鑰
FileInputStream f=new FileInputStream("Skey_RSA_priv.dat");
ObjectInputStream b=new ObjectInputStream(f);
RSAPrivateKey prk=(RSAPrivateKey) b.readObject();
//獲取私鑰指數和模
BigInteger e=prk.getPrivateExponent();//返回私鑰的指數
BigInteger m=prk.getModulus();//返回私鑰的模
BigInteger jie=d.modPow(e, m);
System.out.println("私鑰的指數 e= "+e);
System.out.println("私鑰的模 m="+m);
System.out.println("解密結果 : "+jie);
byte mt[]=jie.toByteArray();
System.out.print("解密後的文字內容為: ");
for (int i = 0; i < mt.length; i++) {
System.out.print((char)mt[i]);
}
in.close();
b.close();
}
}
源程式解讀
(1)Password_Test()構造方法中主要介紹了RSA公鑰和私鑰檔案的生成。建立金鑰對生成器KeyPairGenerator,指定非對稱加密所使用的演算法,常用的有RSA、DSA等。
初始化金鑰生成器。關於金鑰長度,對於RSA演算法,這裡指定的其實是RSA演算法中所用的模的位數,可以在512-2048之間。
通過KeyPair類的getPublic()和getPrivate()方法獲得公鑰和私鑰物件.
(2)Encryption_RSA()方法中主要介紹瞭如何使用生成好的RSA公鑰檔案對字串進行加密。
獲取公鑰。從生成的公鑰檔案Skey_RSA_pub.dat中讀取公鑰,由於生成該檔案時使用的是RSA演算法,因此從檔案讀取公鑰物件後強制轉換為RSAPublicKey型別,以便後續讀取RSA演算法所需要的引數。
獲取明文。明文是一個字串,為了用整數表達這個字串,先使用字串的getByte()方法將其轉換為byte型別陣列,它其實是字串中各個字元的二進位制表達方式,這一串二進位制數轉換為一個整數將非常大,因此仍舊使用BigInteger類將這個二進位制串轉換為整型。
執行加密計算。計算公式: m^e mod n。BigInteger類中已經提供了方法modPow()來執行這個計算。方法返回的結果為密文。
(3)Decryption_RSA()法中主要介紹瞭如何使用生成好的RSA公鑰檔案對字串進行加密。
從生成的密文檔案Enc_RSA.dat中讀取密文,由於加密後只是一行字串,因此只要一條readLine()語句即可
從生成的私鑰檔案Skey_RSA_priv.dat中讀取私鑰,由於生成該私鑰使用的演算法是RSA演算法,因此從檔案讀取公鑰物件後強制轉換為RSAPrivateKey型別,以便後續讀取RSA所需的引數。在獲取私鑰的引數(e,m)的時候可以使用RSAPrivateKey類的getPrivateExponent()和getModulus()方法分別獲得私鑰中e和m的值。RSA演算法解密的結果jie是一個很大的整數,為了計算出其對應的字串的值,先使用BigInteger類的toByteArray()方法得到代表該整型數的位元組陣列,然後將陣列中每個元素轉換為字元,組成字串。
使用BigInteger的modPow()方法計算前面的公式: d^e mod n,方法返回的結果即是明文。
相關推薦
Java安全學習筆記(十一)-RSA演算法加密和解密
RSA演算法是使用整數進行加密和解密運算的, 加密:在RSA公鑰中包含了兩個資訊:公鑰對應的整數e和用於取模的整數n。對於明文數字m,計算密文的公式是: m^e mod n. 解密:跟加密類似,私鑰對應的指數e和用於取模的整數m.其中模m和加密時的加密的模
java入門學習(十一)邏輯運算子和位運算子
家裡有急事 暫停了幾天,抱歉,現在呢開始說說java的運算語句和運算子 如果想利用java的運算語句 那麼就離不開java的運算子,前面第九章講了java的算術運算子,那麼現在咱們說說java的邏輯運算子。特別強調一下 我在這裡說的是邏輯運算子而不是位運算子,至於什麼是位運算子 我後面章節在說。 jav
java之jvm學習筆記十一(訪問控制器)
這一節,我們要學習的是訪問控制器,在閱讀本節之前,如果沒有前面幾節的基礎,對你來說可能會比較困難! 知識回顧: 我們先來回顧一下前幾節的內容,在筆記三的時候我們學了類裝載器,它主
Java基礎學習筆記十六 集合框架(二)
first 哈希 cat etag 基於 col 容器 處的 新元素 List List接口的特點: 它是一個元素存取有序的集合。例如,存元素的順序是11、22、33。那麽集合中,元素的存儲就是按照11、22、33的順序完成的。 它是一個帶有索引的集合,通過索引就
java核心學習(二十一) 多線程---創建啟動線程的三種方式
使用 trace 啟動 操作系統 java多線程 start name image 獲取 本節開始java多線程編程的學習,對於操作系統、進程、線程的基本概念不再贅述,只是了解java對於多線程編程的支持有哪些。 一、繼承Thread類來創建線程 java語言中
odoo10學習筆記十一:視圖綜述
當前 存在 ren name屬性 簡寫 ann idg 重寫 ogre 原文地址:http://www.cnblogs.com/ygj0930/p/7150983.html 一:視圖標簽等公共結構 name (必選) 用於通過名字查找標簽 model: 與view相關聯的
Go語言學習筆記十一: 切片(slice)
操作 容量 方括號 一個 組類型 學習 中學 slice 修改 Go語言學習筆記十一: 切片(slice) 切片這個概念我是從python語言中學到的,當時感覺這個東西真的比較好用。不像java語言寫起來就比較繁瑣。不過我覺得未來java語法也會支持的。 定義切片 切片可以
分散式學習筆記十一:分散式事務模型DTP
一。 DTP簡介 X/Open DTP(X/Open Distributed Transaction Processing Reference Model) 是X/Open 這個組織定義的一套分散式事務的標準,也就是了定義了規範和API介面,由廠商進行具體的實
Web安全學習筆記(十):PHP基礎(下) 之 連線資料庫
前言: 把這個總結完,對於學習的基礎也算完事了,剩下的我就要將實戰中遇到的多多分享了,也希望多結識一些志同道合,聊得來的朋友。  
JQueryEasyUI學習筆記 十一 datagrid 右鍵選單 凍結列
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
IOS開發學習筆記十一 使用xlib檔案實現GridView的效果
效果圖: 在專案中資源素材檔案 新增plist檔案 新增名叫AFGridItem的model物件,用來代替我們從plist檔案中解析得到的字典資料,並新增通過字典獲取物件例項和初始化物件的方法。 #import <Foundation/Foun
Java語言學習(十一):列舉型別和泛型
Java中一個重要的型別:列舉,它可以用來表示一組取值範圍固定的變數,使用 enum 關鍵字定義列舉型別,其中元素不能重複,通常大寫表示。利用Java的反射機制,可以在執行時分析類,如檢視列舉型別的修飾符、父類和自定義方法等,下面簡單說下。
Java Web學習筆記(一)
- Java Web介紹: Java Web,是用Java技術來解決相關web網際網路領域的技術總和。web包括:web伺服器和web客戶端兩部分。JavaWeb應用由一組Servlet、HTML頁、類、以及其它可以被繫結的資源構成。 JavaWeb應用中可以包含: - Servl
Java NIO 學習筆記(一)----概述,Channel/Buffer
Java NIO (來自 Java 1.4)可以替代標準 IO 和 Java Networking API ,NIO 提供了與標準 IO 不同的使用方式。學習 NIO 之前建議先掌握標準 IO 和 Java 網路程式設計,推薦教程: 系統學習 Java IO----目錄,概覽 初步接觸 Java
Java Web 學習筆記(一)
HTML基礎 一、什麼是 HTML? HTML 是用來描述網頁的一種語言。 HTML 指的是超文字標記語言 (Hyper Text Markup Language) HTML 不是一種程式語言,而是一種標記語言 (markup language) 標記語言是一套標記標籤 (markup
java學習筆記(一)成員變數和區域性變數以及靜態變數的區別
成員變數和區域性變數的區別 成員變數: ①成員變數定義在類中,在整個類中都可以被訪問。 ②成員
C++Primer學習筆記十一——關聯容器、.md
關聯容器不支援順序容器的位置相關操作,如 push_back或push_front。原因是關聯容器中元素是按關鍵字儲存的,這些操作對關聯容器沒有意義。 關聯容器也不支援建構函式或插入操作這些接受一個元素值和一個數量值的操作 關聯容器的迭代器都是雙向的,還有一些
圖解演算法學習筆記(一): 演算法簡介
本章內容: 編寫第一種查詢演算法——二分查詢。 學習如何談論演算法的執行時間——大O表示法。 1) 演算法是一組完成任務的指令,任何程式碼片段都可視為演算法。 2)二分查詢:一種查詢演算法,其輸入是一個有序的元素列表。 Python實現二分查詢程式碼:
Go語言學習筆記(十一)之指標
16 指標 變數和記憶體地址 1.每個變數都有記憶體地址,可以說通過變數來操作對應大小的記憶體,&符號可以獲取變數的地址 1: var a int32 2: a = 100 3: fmt.Printf("%d\n", a) 4: fmt.Printf("%p\n", &a)
Pro Android學習筆記 十一 瞭解Intent 中
Intent的構成Intent可以帶有action,data(由URI表達),extra data(key/value map,鍵值對),指定的類名(成為component name)。一個intent至少攜帶上述的一個內容。Action。Action名,在上一筆記中已經給出兩種例子,一種是系統自帶的,如In