1。服務器生成公鑰和私鑰並保存它們。
2。客戶端請求登錄頁面後,它會隨機生成壹個字符串。
3。然後將這個隨機串作為密鑰加密密碼,然後用從服務器獲取的公鑰對生成的隨機串進行加密。
4。這兩個密文傳輸到服務器,服務器用私鑰解隨機串,再用這個私鑰解加密的密文。
其中壹個關鍵是求解服務器的公鑰,這個公鑰傳輸給客戶端。客戶端用這個公鑰加密字符串後,就可以在服務器端用私鑰解決了。
本文就是為了實現這壹步。
加密算法是RSA:
1。服務器上的RSA?Java實現。
/**?
*?
*/?
包裹?com . sun soft . struts . util;?
進口?Java . io . bytearrayoutputstream;?
進口?Java . io . file inputstream;?
進口?Java . io . file output stream;?
進口?Java . io . objectinputstream;?
進口?Java . io . object output stream;?
進口?Java . math . big integer;?
進口?Java . security . key factory;?
進口?Java . security . key pair;?
進口?Java . security . key pair generator;?
進口?Java . security . nosuchalgorithm exception;?
進口?Java . security . private key;?
進口?Java . security . public key;?
進口?Java . security . securerandom;?
進口?Java . security . interfaces . rsaprivatekey;?
進口?Java . security . interfaces . RSA public key;?
進口?Java . security . spec . invalidkeyspecexception;?
進口?Java . security . spec . rsaprivatekeyspec;?
進口?Java . security . spec . rsapapublickeyspec;?
進口?javax . crypto . cipher;?
/**?
*?RSA?工具類。提供對等的加密、解密和密鑰生成方法。?
*?妳需要在http://www.bouncycastle.org下載BC prov-JDK 14-123 . jar。?
*?
*/?
公共?班級?RSAUtil?{?
/**?
*?*?生成密鑰對?*?
*?
*?@回歸?KeyPair?*?
*?@throws?加密異常?
*/?
公共?靜電?KeyPair?generateKeyPair()?摔投?例外?{?
試試?{?
KeyPairGenerator?keyPairGen?=?keypairgenerator . getinstance(" RSA ",
新的?org . bouncy castle . JCE . provider . bouncy castle provider());?
決賽?int?KEY_SIZE?=?1024;//?沒什麽好說的。這個值與塊加密的大小有關,可以改變,但不能太大,否則效率低?
keyPairGen.initialize(KEY_SIZE,?新的?SecureRandom());?
KeyPair?keyPair?=?keypairgen . generatekeypair();?
saveKeyPair(密鑰對);?
回歸?密鑰對;?
}?接住?(例外?e)?{?
扔?新的?異常(e . getmessage());?
}?
}?
公共?靜電?KeyPair?getKeyPair()拋出?異常{?
FileInputStream?fis?=?新的?file inputstream(" C:/RSA key . txt ");?
ObjectInputStream?oos?=?新的?ObjectInputStream(fis);?
KeyPair?kp=?(KeyPair)?OOS . read object();?
OOS . close();?
fis . close();?
回歸?KP;?
}?
公共?靜電?作廢?saveKeyPair(KeyPair?kp)投?異常{?
FileOutputStream?fos?=?新的?file output stream(" C:/RSA key . txt ");?
ObjectOutputStream?oos?=?新的?ObjectOutputStream(fos);?
//生成密鑰?
OOS . writeobject(KP);?
OOS . close();?
fos . close();?
}?
/**?
*?*?生成公鑰?*?
*?
*?@param?模數?*?
*?@param?publicExponent?*?
*?@回歸?RSAPublicKey?*?
*?@throws?例外?
*/?
公共?靜電?RSAPublicKey?generateRSAPublicKey(byte[]?模數,?
byte[]?publicExponent)?摔投?例外?{?
KeyFactory?keyFac?=?null?
試試?{?
keyFac?=?KeyFactory.getInstance("RSA ",
新的?org . bouncy castle . JCE . provider . bouncy castle provider());?
}?接住?(NoSuchAlgorithmException?ex)?{?
扔?新的?異常(ex . getmessage());?
}?
RSAPublicKeySpec?pubKeySpec?=?新的?RSAPublicKeySpec(新?BigInteger(?
模數),?新的?big integer(public index));?
試試?{?
回歸?(RSAPublicKey)?keyfac . generate public(pubkey spec);?
}?接住?(InvalidKeySpecException?ex)?{?
扔?新的?異常(ex . getmessage());?
}?
}?
/**?
*?*?生成私鑰?*?
*?
*?@param?模數?*?
*?@param?privateExponent?*?
*?@回歸?RSAPrivateKey?*?
*?@throws?例外?
*/?
公共?靜電?RSAPrivateKey?generateRSAPrivateKey(byte[]?模數,?
byte[]?privateExponent)?摔投?例外?{?
KeyFactory?keyFac?=?null?
試試?{?
keyFac?=?KeyFactory.getInstance("RSA ",
新的?org . bouncy castle . JCE . provider . bouncy castle provider());?
}?接住?(NoSuchAlgorithmException?ex)?{?
扔?新的?異常(ex . getmessage());?
}?
RSAPrivateKeySpec?priKeySpec?=?新的?RSAPrivateKeySpec(新?BigInteger(?
模數),?新的?big integer(private index));?
試試?{?
回歸?(RSAPrivateKey)?key fac . generate private(prikey spec);?
}?接住?(InvalidKeySpecException?ex)?{?
扔?新的?異常(ex . getmessage());?
}?
}?
/**?
*?*?加密?*?
*?
*?@param?鑰匙?
*加密密鑰?*?
*?@param?數據?
*要加密的明文數據?*?
*?@回歸?加密數據?*?
*?@throws?例外?
*/?
公共?靜電?byte[]?加密(PublicKey?pk,?byte[]?數據)?摔投?例外?{?
試試?{?
密碼?密碼?=?Cipher.getInstance("RSA ",
新的?org . bouncy castle . JCE . provider . bouncy castle provider());?
cipher.init(密碼。加密模式?PK);?
int?blockSize?=?cipher . get blocksize();//?獲取加密後的塊大小,比如加密前的數據是128 byte,key_size=1024?
//?加密塊大小是127?
//?Byte,加密後為128字節;所以* * *有兩個加密塊,第壹個是127?
//?第二個字節是1字節?
int?outputSize?=?cipher . getoutputsize(data . length);//?加密後得到加密塊大小?
int?leavedSize?=?數據長度?%?blockSize?
int?blocksSize?=?leavedSize?!=?0數據長度?/?blockSize?+?1?
:?數據長度?/?blockSize?
byte[]?生的?=?新的?byte[outputSize?*?blocksSize];?
int?我?=?0;?
什麽時候?(數據.長度?-?我?*?blockSize?& gt?0)?{?
如果?(數據.長度?-?我?*?blockSize?& gt?blockSize)?
cipher.doFinal(data,?我?*?塊大小,?塊大小,?生的?我?
*?output size);?
不然呢?
cipher.doFinal(data,?我?*?塊大小,?數據長度?-?我?
*?塊大小,?生的?我?*?output size);?
//?doUpdate方法在這裏不可用。查了壹下源代碼,發現每次doUpdate之後除了把byte[]放進去之外,並沒有什麽實際動作?
//?ByteArrayOutputStream,以及所有byte[] []都在doFinal結束時加密,但此時加密塊大小很可能已經超過?
//?OutputSize,所以我們必須使用dofinal方法。?
i++;?
}?
回歸?生的;?
}?接住?(例外?e)?{?
扔?新的?異常(e . getmessage());?
}?
}?
/**?
*?*?解密?*?
*?
*?@param?鑰匙?
*解密密鑰?*?
*?@param?生的?
*加密數據?*?
*?@回歸?解密明文?*?
*?@throws?例外?
*/?
公共?靜電?byte[]?解密(PrivateKey?pk,?byte[]?raw)?摔投?例外?{?
試試?{?
密碼?密碼?=?Cipher.getInstance("RSA ",
新的?org . bouncy castle . JCE . provider . bouncy castle provider());?
cipher.init(密碼。解密模式,?PK);?
int?blockSize?=?cipher . get blocksize();?
ByteArrayOutputStream?布特?=?新的?ByteArrayOutputStream(64);?
int?j?=?0;?
什麽時候?(raw .長度?-?j?*?blockSize?& gt?0)?{?
bout.write(cipher.doFinal(raw,j?*?塊大小,?block size));?
j++;?
}?
回歸?bout . tobytearray();?
}?接住?(例外?e)?{?
扔?新的?異常(e . getmessage());?
}?
}?
/**?
*?*?*?
*?
*?@param?args?*?
*?@throws?例外?
*/?
公共?靜電?作廢?main(String[]?args)?摔投?例外?{?
RSAPublicKey?rsap?=?(RSAPublicKey)?RSAUtil.generateKeyPair()。getPublic();?
字符串?測試?=?“餵?世界”;?
byte[]?en_test?=?encrypt(getKeyPair()。getPublic()、test . getbytes());?
byte[]?de_test?=?解密(getKeyPair()。getPrivate(),en _ test);?
System.out.println(新?string(de _ test));?
}?
} 2.測試頁面:
IndexAction.java