结论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.");
}
}