㈠ RSA的公鑰和私鑰到底哪個才是用來加密和哪個用來解密
我們來回顧一下RSA的加密演算法。我們從公鑰加密演算法和簽名演算法的定義出發,用比較規范的語言來描述這一演算法。
RSA公鑰加密體制包含如下3個演算法:KeyGen(密鑰生成演算法),Encrypt(加密演算法)以及Decrypt(解密演算法)。
(PK, SK)\leftarrow KeyGen(\lambda)。密鑰生成演算法以安全常數\lambda作為輸入,輸出一個公鑰PK,和一個私鑰SK。安全常數用於確定這個加密演算法的安全性有多高,一般以加密演算法使用的質數p的大小有關。\lambda越大,質數p一般越大,保證體制有更高的安全性。在RSA中,密鑰生成演算法如下:演算法首先隨機產生兩個不同大質數p和q,計算N=pq。隨後,演算法計算歐拉函數\varphi(N)=(p-1)(q-1)。接下來,演算法隨機選擇一個小於\varphi(N)的整數e,並計算e關於\varphi(N)的模反元素d。最後,公鑰為PK=(N, e),私鑰為SK=(N, d)。
CT \leftarrow Encrypt(PK,M)。加密演算法以公鑰PK和待加密的消息M作為輸入,輸出密文CT。在RSA中,加密演算法如下:演算法直接輸出密文為CT=M^e \mod \varphi(N)
M \leftarrow Decrypt(SK,CT)。解密演算法以私鑰SK和密文CT作為輸入,輸出消息M。在RSA中,解密演算法如下:演算法直接輸出明文為M=CT^d \mod \varphi(N)。由於e和d在\varphi(N)下互逆,因此我們有:CT^d=M^{ed}=M\mod \varphi(N)
所以,從演算法描述中我們也可以看出:公鑰用於對數據進行加密,私鑰用於對數據進行解密。當然了,這個也可以很直觀的理解:公鑰就是公開的密鑰,其公開了大家才能用它來加密數據。私鑰是私有的密鑰,誰有這個密鑰才能夠解密密文。否則大家都能看到私鑰,就都能解密,那不就亂套了。
=================分割線=================
我們再來回顧一下RSA簽名體制。簽名體制同樣包含3個演算法:KeyGen(密鑰生成演算法),Sign(簽名演算法),Verify(驗證演算法)。
(PK,SK) \leftarrow KeyGen(\lambda)。密鑰生成演算法同樣以安全常數\lambda作為輸入,輸出一個公鑰PK和一個私鑰SK。在RSA簽名中,密鑰生成演算法與加密演算法完全相同。
\sigma \leftarrow Sign(SK,M)。簽名演算法以私鑰SK和待簽名的消息M作為輸入,輸出簽名\sigma。在RSA簽名中,簽名演算法直接輸出簽名為\sigma = M^d \mod \varphi(N)。注意,簽名演算法和RSA加密體制中的解密演算法非常像。
b \leftarrow Verify(PK,\sigma,M)。驗證演算法以公鑰PK,簽名\sigma以及消息M作為輸入,輸出一個比特值b。b=1意味著驗證通過。b=0意味著驗證不通過。在RSA簽名中,驗證演算法首先計算M'=\sigma^e \mod \varphi(N),隨後對比M'與M,如果相等,則輸出b=1,否則輸出b=0。注意:驗證演算法和RSA加密體制中的加密演算法非常像。
所以,在簽名演算法中,私鑰用於對數據進行簽名,公鑰用於對簽名進行驗證。這也可以直觀地進行理解:對一個文件簽名,當然要用私鑰,因為我們希望只有自己才能完成簽字。驗證過程當然希望所有人都能夠執行,大家看到簽名都能通過驗證證明確實是我自己簽的。
=================分割線=================
那麼,為什麼題主問這么一個問題呢?我們可以看到,RSA的加密/驗證,解密/簽字過程太像了。同時,RSA體制本身就是對稱的:如果我們反過來把e看成私鑰,d看成公鑰,這個體制也能很好的執行。我想正是由於這個原因,題主在學習RSA體制的時候才會出現這種混亂。那麼解決方法是什麼呢?建議題主可以學習一下其他的公鑰加密體制以及簽名體制。其他的體制是沒有這種對稱性質的。舉例來說,公鑰加密體制的話可以看一看ElGamal加密,以及更安全的Cramer-Shoup加密。簽名體制的話可以進一步看看ElGamal簽名,甚至是BLS簽名,這些體制可能能夠幫助題主更好的弄清加密和簽名之間的區別和潛在的聯系。
至於題主問的加密和簽名是怎麼結合的。這種體制叫做簽密方案(SignCrypt),RSA中,這種簽密方案看起來特別特別像,很容易引起混亂。在此我不太想詳細介紹RSA中的加密與簽字結合的方案。我想提醒題主的是,加密與簽字結合時,兩套公私鑰是不同的。
㈡ 用javaScript實現RSA加密和解密
下面是一個我收藏的函數,用於計算rsa的pow和mod有很高的效率。我不知道是什麼演算法,但這個函數真的很好用。
function RSAPowMod(txt, key, n) {
var a, b;
if (key % 2 == 0) {
a = 1
for (var i = 1; i <= key / 2; i++) {
b = (txt * txt) % n
a = (b * a) % n
}
} else {
a = txt
for (var i = 1; i <= key / 2; i++) {
b = (txt * txt) % n
a = (b * a) % n
}
}
return a;
}
txt,key,n都可以是字元串,代表著大數,當然,具體大到什麼范圍我不知道。
大於65535的數我測試過,表示支持不止兩位元組了,那推測是四位元組或者以上。
當我用九位數和十位數的時候,計算效率就不行。中間的,比如七位八位數的,我沒有現成的密鑰對,測試不了。
把對應的變數名改一改就符合要求了。(其實不用改,直接使用函數也是可以的。)
㈢ RSA加密解密過程
為了這道題把好幾年前學的東西重新看了一遍,累覺不愛。。。
不清楚你了不了解RSA過程,先跟說一下吧
隨機產生兩個大素數p和q作為密鑰對。此題:p=13,q=17,n =p*q=221
隨機產生一個加密密鑰e,使e 和(p-1)*(q-1)互素。此題:e=83
公鑰就是(n,e)。此題:(221,83)
通過e*d mod (p-1)*(q-1)=1生成解密密鑰d, ,n與d也要互素。此題:(d*83)≡1mod192
私鑰就是(n,d)。此題:(221,155)
之後發送者用公鑰加密明文M,得到密文C=M^e mod n
接受者利用私鑰解密M=C^d mod n
求解d呢,就是求逆元,de = 1 mod n這種形式就稱de於模數n說互逆元,可以看成de-ny=1,此題83e-192y=1.
用擴展的歐幾里得演算法。其實就是輾轉相除
此題:
192=2*83+26
83=3*26+5
26=5*5+1
求到余數為1了,就往回寫
1=26-5*5
=26-5*(83-3*26)
=(192-2*83)-5*(83-3*(192-2*83))
=16*192-37*83
則d=-37,取正後就是155.
記住,往回寫的時候數不該換的一定不要換,比如第二步中的26,一定不能換成(83-5)/3,那樣就求不出來了,最終一定要是192和83相關聯的表達式。還有,最好保持好的書寫格式,比如第一步2*83+26時第二步最好寫成3*26+5而不是26*3+5,要不步驟比較多的話容易亂
㈣ RSA的公鑰和私鑰到底哪個才是用來加密和哪個用來解密
它們都可以加密,也都可以解密,只不過側重點不同。
數字簽名只不過是兩個目的:證明你發送了信息;確實,該消息的內容是完整的——也就是說,沒有任何形式的篡改(包括替換、缺少、添加)。事實上,上述關於「通知」的聲明已經證明了第一點:您發送了消息。因此,要做第二點,也很簡單,就是保持原來的方法,你注意到一個哈希(md5和sha1),然後使用你的私鑰加密作為簽名,然後一起發布。當別人收到你的通知時,他可以用你的公鑰解密簽名,如果成功解密,哈希值相符,就可以證明是你發的公文。
㈤ java中RSA用私鑰加密公鑰解密問題
公鑰和私鑰可以互換的用,用公鑰加密私鑰解密,用私鑰加密公鑰解密都ok,方法一樣
㈥ 如何實現用javascript實現rsa加解密
服務端生成公鑰與私鑰,保存。
客戶端在請求到登錄頁面後,隨機生成一字元串。
後此隨機字元串作為密鑰加密密碼,再用從服務端獲取到的公鑰加密生成的隨機字元串
將此兩段密文傳入服務端,服務端用私鑰解出隨機字元串,再用此私鑰解出加密的密文。這其中有一個關鍵是解決服務端的公鑰,傳入客戶端,客戶端用此公鑰加密字元串後,後又能在服務端用私鑰解出。
步驟:
服務端的RSAJava實現:
/**
*
*/
packagecom.sunsoft.struts.util;
importjava.io.ByteArrayOutputStream;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.ObjectInputStream;
importjava.io.ObjectOutputStream;
importjava.math.BigInteger;
importjava.security.KeyFactory;
importjava.security.KeyPair;
importjava.security.KeyPairGenerator;
importjava.security.NoSuchAlgorithmException;
importjava.security.PrivateKey;
importjava.security.PublicKey;
importjava.security.SecureRandom;
importjava.security.interfaces.RSAPrivateKey;
importjava.security.interfaces.RSAPublicKey;
importjava.security.spec.InvalidKeySpecException;
importjava.security.spec.RSAPrivateKeySpec;
importjava.security.spec.RSAPublicKeySpec;
importjavax.crypto.Cipher;/**
*RSA工具類。提供加密,解密,生成密鑰對等方法。
*需要到
下載bcprov-jdk14-123.jar。
*
*/
publicclassRSAUtil{
/**
**生成密鑰對*
*
*@returnKeyPair*
*@throwsEncryptException
*/
()throwsException{
try{
KeyPairGeneratorkeyPairGen=KeyPairGenerator.getInstance("RSA",
neworg.bouncycastle.jce.provider.BouncyCastleProvider());
finalintKEY_SIZE=1024;//沒什麼好說的了,這個值關繫到塊加密的大小,可以更改,但是不要太大,否則效率會低
keyPairGen.initialize(KEY_SIZE,newSecureRandom());
KeyPairkeyPair=keyPairGen.generateKeyPair();
saveKeyPair(keyPair);
returnkeyPair;
}catch(Exceptione){
thrownewException(e.getMessage());
}
}
publicstaticKeyPairgetKeyPair()throwsException{
FileInputStreamfis=newFileInputStream("C:/RSAKey.txt");
ObjectInputStreamoos=newObjectInputStream(fis);
KeyPairkp=(KeyPair)oos.readObject();
oos.close();
fis.close();
returnkp;
}
publicstaticvoidsaveKeyPair(KeyPairkp)throwsException{
FileOutputStreamfos=newFileOutputStream("C:/RSAKey.txt");
ObjectOutputStreamoos=newObjectOutputStream(fos);
//生成密鑰
oos.writeObject(kp);
oos.close();
fos.close();
}
/**
**生成公鑰*
*
*@parammolus*
*@parampublicExponent*
*@returnRSAPublicKey*
*@throwsException
*/
(byte[]molus,
byte[]publicExponent)throwsException{
KeyFactorykeyFac=null;
try{
keyFac=KeyFactory.getInstance("RSA",
neworg.bouncycastle.jce.provider.BouncyCastleProvider());
}catch(NoSuchAlgorithmExceptionex){
thrownewException(ex.getMessage());
}
RSAPublicKeySpecpubKeySpec=newRSAPublicKeySpec(newBigInteger(
molus),newBigInteger(publicExponent));
try{
return(RSAPublicKey)keyFac.generatePublic(pubKeySpec);
}catch(InvalidKeySpecExceptionex){
thrownewException(ex.getMessage());
}
}
/**
**生成私鑰*
*
*@parammolus*
*@paramprivateExponent*
*@returnRSAPrivateKey*
*@throwsException
*/
(byte[]molus,
byte[]privateExponent)throwsException{
KeyFactorykeyFac=null;
try{
keyFac=KeyFactory.getInstance("RSA",
neworg.bouncycastle.jce.provider.BouncyCastleProvider());
}catch(NoSuchAlgorithmExceptionex){
thrownewException(ex.getMessage());
}
RSAPrivateKeySpecpriKeySpec=newRSAPrivateKeySpec(newBigInteger(
molus),newBigInteger(privateExponent));
try{
return(RSAPrivateKey)keyFac.generatePrivate(priKeySpec);
}catch(InvalidKeySpecExceptionex){
thrownewException(ex.getMessage());
}
}
/**
**加密*
*
*@paramkey
*加密的密鑰*
*@paramdata
*待加密的明文數據*
*@return加密後的數據*
*@throwsException
*/
publicstaticbyte[]encrypt(PublicKeypk,byte[]data)throwsException{
try{
Ciphercipher=Cipher.getInstance("RSA",
neworg.bouncycastle.jce.provider.BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE,pk);
intblockSize=cipher.getBlockSize();//獲得加密塊大小,如:加密前數據為128個byte,而key_size=1024
//加密塊大小為127
//byte,加密後為128個byte;因此共有2個加密塊,第一個127
//byte第二個為1個byte
intoutputSize=cipher.getOutputSize(data.length);//獲得加密塊加密後塊大小
intleavedSize=data.length%blockSize;
intblocksSize=leavedSize!=0?data.length/blockSize+1
:data.length/blockSize;
byte[]raw=newbyte[outputSize*blocksSize];
inti=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++;
}
returnraw;
}catch(Exceptione){
thrownewException(e.getMessage());
}
}
/**
**解密*
*
*@paramkey
*解密的密鑰*
*@paramraw
*已經加密的數據*
*@return解密後的明文*
*@throwsException
*/
publicstaticbyte[]decrypt(PrivateKeypk,byte[]raw)throwsException{
try{
Ciphercipher=Cipher.getInstance("RSA",
neworg.bouncycastle.jce.provider.BouncyCastleProvider());
cipher.init(cipher.DECRYPT_MODE,pk);
intblockSize=cipher.getBlockSize();
ByteArrayOutputStreambout=newByteArrayOutputStream(64);
intj=0;
while(raw.length-j*blockSize>0){
bout.write(cipher.doFinal(raw,j*blockSize,blockSize));
j++;
}
returnbout.toByteArray();
}catch(Exceptione){
thrownewException(e.getMessage());
}
}
/**
***
*
*@paramargs*
*@throwsException
*/
publicstaticvoidmain(String[]args)throwsException{
RSAPublicKeyrsap=(RSAPublicKey)RSAUtil.generateKeyPair().getPublic();
Stringtest="helloworld";
byte[]en_test=encrypt(getKeyPair().getPublic(),test.getBytes());
byte[]de_test=decrypt(getKeyPair().getPrivate(),en_test);
System.out.println(newString(de_test));
}
}
測試頁面IndexAction.java:
/*
*GeneratedbyMyEclipseStruts
*Templatepath:templates/java/JavaClass.vtl
*/
packagecom.sunsoft.struts.action;
importjava.security.interfaces.RSAPrivateKey;
importjava.security.interfaces.RSAPublicKey;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importorg.apache.struts.action.Action;
importorg.apache.struts.action.ActionForm;
importorg.apache.struts.action.ActionForward;
importorg.apache.struts.action.ActionMapping;
importcom.sunsoft.struts.util.RSAUtil;
/**
*MyEclipseStruts
*Creationdate:06-28-2008
*
*XDocletdefinition:
*@struts.actionvalidate="true"
*/
{
/*
*GeneratedMethods
*/
/**
*Methodexecute
*@parammapping
*@paramform
*@paramrequest
*@paramresponse
*@returnActionForward
*/
publicActionForwardexecute(ActionMappingmapping,ActionFormform,
HttpServletRequestrequest,HttpServletResponseresponse)throwsException{
RSAPublicKeyrsap=(RSAPublicKey)RSAUtil.getKeyPair().getPublic();
Stringmole=rsap.getMolus().toString(16);
Stringempoent=rsap.getPublicExponent().toString(16);
System.out.println("mole");
System.out.println(mole);
System.out.println("empoent");
System.out.println(empoent);
request.setAttribute("m",mole);
request.setAttribute("e",empoent);
returnmapping.findForward("login");
}
}
通過此action進入登錄頁面,並傳入公鑰的Molus 與PublicExponent的hex編碼形式。
㈦ jsencrypt庫進行rsa公鑰加密怎麼在後台解密
1、用公鑰加密,用私鑰解密。 2、給別人發信息,就從伺服器上拉下來別人的公鑰,加密後發給他。 3、對方拿到信息後用自己的私鑰解密。 4、這樣,公鑰加密後除了私鑰持有人,別人都看不到信息。
㈧ 關於私鑰加密 公鑰解密
如果只是單方面採用非對稱性加密演算法,其實有兩種方式,用於不同用處.
第一種是簽名,使用私鑰加密,公鑰解密,用於讓所有公鑰所有者驗證私鑰所有者的身份並且用來防止私鑰所有者發布的內容被篡改.但是不用來保證內容不被他人獲得.
第二種是加密,用公鑰加密,私鑰解密,用於向公鑰所有者發布信息,這個信息可能被他人篡改,但是無法被他人獲得.
如果甲想給乙發一個安全的保密的數據,那麼應該甲乙各自有一個私鑰,甲先用乙的公鑰加密這段數據,再用自己的私鑰加密這段加密後的數據.最後再發給乙,這樣確保了內容即不會被讀取,也不會被篡改.