結論1:密鑰生成佔據初始化99%的時間
public void createKeys(int keySize) throws Exception {
long t1 = System.currentTimeMillis();
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(keySize);
long t2 = System.currentTimeMillis();
KeyPair keyPair = kpg.generateKeyPair();
long t3 = System.currentTimeMillis();
this.publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
this.privateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
this.rsaPublicKey = this.getPublicKey(this.publicKey);
this.rsaPrivateKey = this.getPrivateKey(this.privateKey);
long t4 = System.currentTimeMillis();
System.out.printf("Total Time: %d ms, key generation time: %d ms.\n", t4 - t1, t3 - t2);
}
經測試發現,創建密鑰的過程中,密鑰對的生成算法佔據了99%的時間,如下所示,總時間1788ms,而創建密鑰對就用了1768ms。這個過程雖然耗時很長,但是好在只需要一次創建,可以重複使用。
Total Time: 1788 ms, key generation time: 1768 ms.
結論2:加密耗時佔據99%的時間
第二個耗時的地方是加密,以下代碼
public static void main(String[] args) throws Exception {
String str = "This is what I wanted to tell you.";
long[] times = new long[4];
times[0] = System.currentTimeMillis();
RSAUtil rsa = new RSAUtil();
times[1] = System.currentTimeMillis();
String encodedData = rsa.publicEncrypt(str);
times[2] = System.currentTimeMillis();
String decodedData = rsa.privateDecrypt(encodedData);
times[3] = System.currentTimeMillis();
for (int i = 0; i < times.length - 1; i++)
System.out.println(i + ": " + (times[i + 1] - times[i]) + " ms.");
}
測試結果爲:
0: 16 ms.
1: 1572 ms.
2: 8 ms.
這個過程表明加密是耗時的,解密是很快速的。所以RSA算法主要的使用場景是爲了生成密鑰,而不是爲了數據加解密,因爲其所消耗的時間太多,不適合頻繁使用。
附:源代碼
package test;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
import java.util.ArrayList;
import java.util.Base64;
public class RSAUtil {
public static final String charset = "UTF-8";
public static final String algorithm = "RSA";
public String publicKey = null;
public String privateKey = null;
public RSAPublicKey rsaPublicKey = null;
public RSAPrivateKey rsaPrivateKey = null;
public RSAUtil() throws Exception {
createKeys(1024);
}
public void createKeys(int keySize) throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(keySize);
KeyPair keyPair = kpg.generateKeyPair();
this.publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
this.privateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
this.rsaPublicKey = this.getPublicKey(this.publicKey);
this.rsaPrivateKey = this.getPrivateKey(this.privateKey);
}
private RSAPublicKey getPublicKey(String publicKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey));
return (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
}
private RSAPrivateKey getPrivateKey(String privateKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey));
return (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
}
public String publicEncrypt(String data) throws Exception {
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, rsaPublicKey);
return Base64.getEncoder().encodeToString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(charset),
rsaPublicKey.getModulus().bitLength()));
}
public String privateDecrypt(String data) throws Exception {
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, rsaPrivateKey);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.getDecoder().decode(data),
rsaPrivateKey.getModulus().bitLength()), charset);
}
public String privateEncrypt(String data, RSAPrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return Base64.getEncoder().encodeToString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(charset),
privateKey.getModulus().bitLength()));
}
public String publicDecrypt(String data, RSAPublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.getDecoder().decode(data),
publicKey.getModulus().bitLength()), charset);
}
private byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize) throws Exception {
int maxBlock = opmode == Cipher.DECRYPT_MODE ? keySize / 8 : keySize / 8 - 11;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0, i = 0;
byte[] buff;
while (datas.length > offSet) {
buff = datas.length - offSet > maxBlock ? cipher.doFinal(datas, offSet, maxBlock)
: cipher.doFinal(datas, offSet, datas.length - offSet);
out.write(buff, 0, buff.length);
offSet = ++i * maxBlock;
}
return out.toByteArray();
}
public static void main(String[] args) throws Exception {
String str = "This is what I wanted to tell you.";
long[] times = new long[4];
times[0] = System.currentTimeMillis();
RSAUtil rsa = new RSAUtil();
times[1] = System.currentTimeMillis();
String encodedData = rsa.publicEncrypt(str);
times[2] = System.currentTimeMillis();
String decodedData = rsa.privateDecrypt(encodedData);
times[3] = System.currentTimeMillis();
System.out.println("Original: " + str);
System.out.println("PubKey: " + rsa.publicKey);
System.out.println("PriKey: " + rsa.privateKey);
// System.out.println("RsaPubKey: " + rsa.rsaPublicKey);
// System.out.println("RsaPriKey: " + rsa.rsaPrivateKey);
System.out.println("Encoded: " + encodedData);
System.out.println("Decoded: " + decodedData);
for (int i = 0; i < times.length - 1; i++)
System.out.println("All Time: " + (times[i + 1] - times[i]) + " ms.");
}
}