rsa加密解密java
㈠ 有一段用java實現rsa加解密的程序看不懂,希望高手幫我做下注釋,詳細些,謝謝
//引入文件
import java.security.*;
import javax.crypto.*;
/**
* RSACryptography
* RSACryptography use the privated key to encrypt the plain text and decrypt
* the cipher text with the public key
*/
public class RSACryptography {
Cipher cipher;
/**
構造函數,就是你每次new這個對象RSACryptography 時候就會執行裡面的方法
返回一個Cipher對象(其實他就是用來加密解密的)
*/
public RSACryptography() {
try {
cipher = Cipher.getInstance("RSA");//返回一個cipher對象,該類
//應該是單例的
} catch (NoSuchAlgorithmException e) {//拋出異常,沒什麼說的
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
}
/**
好了,重點來了,你需要加密解密的就調用這個方法encrypt_decrypt(),傳入一個byte[]的類型值byteInput,,就是你要加密的東西,在傳入一個key,這個key 就像鑰匙一樣,你根據這個key進行加密,也可以根據這個key進行解密的,boolean 類型的 crypto,如果true就是加密,false就是解密
*/
public byte[] encrypt_decrypt(byte[] byteInput, Key key, boolean crypto) {
try {
if(crypto){
cipher.init(Cipher.ENCRYPT_MODE,key);//加密前初始化
}else{
cipher.init(Cipher.DECRYPT_MODE,key);//解密前初始化
}
byte[] cipherByte = cipher.doFinal(byteInput);//進行加密或解密
return cipherByte;//返回你的加密或者解密值類型為byte[]
} catch (InvalidKeyException e) {//拋出異常
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
}
㈡ java 生成的rsa私鑰怎麼給ios解密
java使用jdk的KeyPairGenerator 生成公鑰和私鑰;
java服務端把公鑰轉化為一個字元串發送給ios端;
然後ios端根據此字元串還原公鑰,使用公鑰進行加密;
服務端使用秘鑰進行解密;
邏輯是這樣的沒問題,可是語言不通,java發送出來的字元串IOS不一定能還原成公鑰,就算有還原的方法,還原了也不一定對(與java端私鑰不對稱);同理私鑰也一樣
㈢ Java 第三方公鑰 RSA加密求助
下面是RSA加譽春密代碼。
/**
* RSA演算法,實現數據的加密解密。
* @author ShaoJiang
*
*/
public class RSAUtil {
private static Cipher cipher;
static{
try {
cipher = Cipher.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
}
/**
* 生成密鑰對
* @param filePath 生成密鑰做含的路徑
* @return
*/
public static Map<String,String> generateKeyPair(String filePath){
try {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
// 密鑰位數
keyPairGen.initialize(1024);
// 密鑰對
KeyPair keyPair = keyPairGen.generateKeyPair();
// 公鑰
PublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// 私鑰
PrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
//得到公鑰字元串
String publicKeyString = getKeyString(publicKey);
//得到私鑰字元串
String privateKeyString = getKeyString(privateKey);
FileWriter pubfw = new FileWriter(filePath+"/publicKey.keystore"純虛笑);
FileWriter prifw = new FileWriter(filePath+"/privateKey.keystore");
BufferedWriter pubbw = new BufferedWriter(pubfw);
BufferedWriter pribw = new BufferedWriter(prifw);
pubbw.write(publicKeyString);
pribw.write(privateKeyString);
pubbw.flush();
pubbw.close();
pubfw.close();
pribw.flush();
pribw.close();
prifw.close();
//將生成的密鑰對返回
Map<String,String> map = new HashMap<String,String>();
map.put("publicKey",publicKeyString);
map.put("privateKey",privateKeyString);
return map;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 得到公鑰
*
* @param key
* 密鑰字元串(經過base64編碼)
* @throws Exception
*/
public static PublicKey getPublicKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = (new BASE64Decoder()).decodeBuffer(key);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}
/**
* 得到私鑰
*
* @param key
* 密鑰字元串(經過base64編碼)
* @throws Exception
*/
public static PrivateKey getPrivateKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = (new BASE64Decoder()).decodeBuffer(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
/**
* 得到密鑰字元串(經過base64編碼)
*
* @return
*/
public static String getKeyString(Key key) throws Exception {
byte[] keyBytes = key.getEncoded();
String s = (new BASE64Encoder()).encode(keyBytes);
return s;
}
/**
* 使用公鑰對明文進行加密,返回BASE64編碼的字元串
* @param publicKey
* @param plainText
* @return
*/
public static String encrypt(PublicKey publicKey,String plainText){
try {
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] enBytes = cipher.doFinal(plainText.getBytes());
return (new BASE64Encoder()).encode(enBytes);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
/**
* 使用keystore對明文進行加密
* @param publicKeystore 公鑰文件路徑
* @param plainText 明文
* @return
*/
public static String encrypt(String publicKeystore,String plainText){
try {
FileReader fr = new FileReader(publicKeystore);
BufferedReader br = new BufferedReader(fr);
String publicKeyString="";
String str;
while((str=br.readLine())!=null){
publicKeyString+=str;
}
br.close();
fr.close();
cipher.init(Cipher.ENCRYPT_MODE,getPublicKey(publicKeyString));
byte[] enBytes = cipher.doFinal(plainText.getBytes());
return (new BASE64Encoder()).encode(enBytes);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 使用私鑰對明文密文進行解密
* @param privateKey
* @param enStr
* @return
*/
public static String decrypt(PrivateKey privateKey,String enStr){
try {
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] deBytes = cipher.doFinal((new BASE64Decoder()).decodeBuffer(enStr));
return new String(deBytes);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 使用keystore對密文進行解密
* @param privateKeystore 私鑰路徑
* @param enStr 密文
* @return
*/
public static String decrypt(String privateKeystore,String enStr){
try {
FileReader fr = new FileReader(privateKeystore);
BufferedReader br = new BufferedReader(fr);
String privateKeyString="";
String str;
while((str=br.readLine())!=null){
privateKeyString+=str;
}
br.close();
fr.close();
cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKeyString));
byte[] deBytes = cipher.doFinal((new BASE64Decoder()).decodeBuffer(enStr));
return new String(deBytes);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
㈣ 如何實現用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編碼形式。
㈤ 怎麼在ios進行rsa公鑰加密,java做rsa私鑰解密
1、用公鑰加密,用私鑰解密。
2、給別人發信息,就從伺服器上拉下來別人的公鑰,加密後發給他。
3、對方拿到信息後用自己的私鑰解密。
4、這樣,公鑰加密後除了私鑰持有人,別人都看不到信息。
5、若是用私鑰加密,那麼公鑰都能解密,還有何安全性可言?
6、私鑰加密的場合只有一個,那就是數字簽名,用來表明這個信息來源於你。
㈥ 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); } }
㈦ 關於java中rsa的問題
【實例下載】本文介紹RSA2加密與解密,RSA2是RSA的加強版本,在密鑰長度上採用2048, RSA2比RSA更安全,更可靠, 本人的另一篇文章RSA已經發表,有想了解的可以點開下面的RSA文章
㈧ javarsa加密c#解密失敗
系統bug。當軟體javarsa的系統出現系統bug時,就會導致該軟體在解密c井的程序的時候出現解密失敗的情況,只需要將該軟體卸載後重新安裝該軟體即可。
㈨ java中的rsa\des演算法的方法
rsa加密解密演算法
1978年就出現了這種演算法,它是第一個既能用於數據加密
也能用於數字簽名的演算法。它易於理解和操作,也很流行。算
法的名字以發明者的名字命名:Ron Rivest, AdiShamir 和
Leonard Adleman。但RSA的安全性一直未能得到理論上的證明。
RSA的安全性依賴於大數分解。公鑰和私鑰都是兩個大素數
( 大於 100個十進制位)的函數。據猜測,從一個密鑰和密文
推斷出明文的難度等同於分解兩個大素數的積。
密鑰對的產生:選擇兩個大素數,p 和q 。計算:
n = p * q
然後隨機選擇加密密鑰e,要求 e 和 ( p - 1 ) * ( q - 1 )
互質。最後,利用Euclid 演算法計算解密密鑰d, 滿足
e * d = 1 ( mod ( p - 1 ) * ( q - 1 ) )
其中n和d也要互質。數e和
n是公鑰,d是私鑰。兩個素數p和q不再需要,應該丟棄,不要讓任
何人知道。 加密信息 m(二進製表示)時,首先把m分成等長數據
塊 m1 ,m2,..., mi ,塊長s,其中 2^s <= n, s 盡可能的大。對
應的密文是:
ci = mi^e ( mod n ) ( a )
解密時作如下計算:
mi = ci^d ( mod n ) ( b )
RSA 可用於數字簽名,方案是用 ( a ) 式簽名, ( b )
式驗證。具體操作時考慮到安全性和 m信息量較大等因素,一般是先
作 HASH 運算。
RSA 的安全性。
RSA的安全性依賴於大數分解,但是否等同於大數分解一直未能得到理
論上的證明,因為沒有證明破解RSA就一定需要作大數分解。假設存在
一種無須分解大數的演算法,那它肯定可以修改成為大數分解演算法。目前,
RSA的一些變種演算法已被證明等價於大數分解。不管怎樣,分解n是最顯
然的攻擊方法。現在,人們已能分解140多個十進制位的大素數。因此,
模數n必須選大一些,因具體適用情況而定。
RSA的速度:
由於進行的都是大數計算,使得RSA最快的情況也比DES慢上100倍,無論
是軟體還是硬體實現。速度一直是RSA的缺陷。一般來說只用於少量數據
加密。
RSA的選擇密文攻擊:
RSA在選擇密文攻擊面前很脆弱。一般攻擊者是將某一信息作一下偽裝
(Blind),讓擁有私鑰的實體簽署。然後,經過計算就可得到它所想要的信
息。實際上,攻擊利用的都是同一個弱點,即存在這樣一個事實:乘冪保
留了輸入的乘法結構:
( XM )^d = X^d *M^d mod n
前面已經提到,這個固有的問題來自於公鑰密碼系統的最有用的特徵
--每個人都能使用公鑰。但從演算法上無法解決這一問題,主要措施有
兩條:一條是採用好的公鑰協議,保證工作過程中實體不對其他實體
任意產生的信息解密,不對自己一無所知的信息簽名;另一條是決不
對陌生人送來的隨機文檔簽名,簽名時首先使用One-Way HashFunction
對文檔作HASH處理,或同時使用不同的簽名演算法。在中提到了幾種不
同類型的攻擊方法。
RSA的公共模數攻擊。
若系統中共有一個模數,只是不同的人擁有不同的e和d,系統將是危險
的。最普遍的情況是同一信息用不同的公鑰加密,這些公鑰共模而且互
質,那末該信息無需私鑰就可得到恢復。設P為信息明文,兩個加密密鑰
為e1和e2,公共模數是n,則:
C1 = P^e1 mod n
C2 = P^e2 mod n
密碼分析者知道n、e1、e2、C1和C2,就能得到P。
因為e1和e2互質,故用Euclidean演算法能找到r和s,滿足:
r * e1 + s * e2 = 1
假設r為負數,需再用Euclidean演算法計算C1^(-1),則
( C1^(-1) )^(-r) * C2^s = P mod n
另外,還有其它幾種利用公共模數攻擊的方法。總之,如果知道給定模數
的一對e和d,一是有利於攻擊者分解模數,一是有利於攻擊者計算出其它
成對的e』和d』,而無需分解模數。解決辦法只有一個,那就是不要共享
模數n。
RSA的小指數攻擊。 有一種提高
RSA速度的建議是使公鑰e取較小的值,這樣會使加密變得易於實現,速度
有所提高。但這樣作是不安全的,對付辦法就是e和d都取較大的值。
RSA演算法是第一個能同時用於加密和數字簽名的演算法,也易於理解和操作。
RSA是被研究得最廣泛的公鑰演算法,從提出到現在已近二十年,經歷了各
種攻擊的考驗,逐漸為人們接受,普遍認為是目前最優秀的公鑰方案之一。
RSA的安全性依賴於大數的因子分解,但並沒有從理論上證明破譯RSA的難
度與大數分解難度等價。即RSA的重大缺陷是無法從理論上把握它的保密性
能如何,而且密碼學界多數人士傾向於因子分解不是NPC問題。
RSA的缺點主要有:
A)產生密鑰很麻煩,受到素數產生技術的限制,因而難以做到一次
一密。B)分組長度太大,為保證安全性,n 至少也要 600 bits
以上,使運算代價很高,尤其是速度較慢,較對稱密碼演算法慢幾個數量級;
且隨著大數分解技術的發展,這個長度還在增加,不利於數據格式的標准化。
目前,SET(Secure Electronic Transaction)協議中要求CA採用2048比特長
的密鑰,其他實體使用1024比特的密鑰。
參考資料:http://superpch.josun.com.cn/bbs/PrintPost.asp?ThreadID=465
CRC加解密演算法
http://www.bouncycastle.org/