RSA加密算法耗时耗在哪里?

结论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.");
	}
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RSA(Rivest-Shamir-Adleman)是一种非对称加密算法,用于加密和解密数据。C#中提供了对RSA算法的支持。下面是一个简单的示例代码,展示如何使用RSA算法进行加密和解密: ```csharp using System; using System.Security.Cryptography; using System.Text; public class RSADemo { public static void Main() { // 创建RSA实例 using (RSA rsa = RSA.Create()) { try { // 生成RSA的公钥和私钥对 RSAParameters publicKey; RSAParameters privateKey; rsa.KeySize = 2048; // 设置密钥长度 // 生成密钥对 publicKey = rsa.ExportParameters(false); privateKey = rsa.ExportParameters(true); // 要加密的数据 string dataToEncrypt = "Hello, RSA!"; // 加密数据 byte[] encryptedData = EncryptData(Encoding.UTF8.GetBytes(dataToEncrypt), publicKey); // 解密数据 byte[] decryptedData = DecryptData(encryptedData, privateKey); // 显示结果 Console.WriteLine("原始数据: {0}", dataToEncrypt); Console.WriteLine("加密后的数据: {0}", Convert.ToBase64String(encryptedData)); Console.WriteLine("解密后的数据: {0}", Encoding.UTF8.GetString(decryptedData)); } catch (CryptographicException e) { Console.WriteLine(e.Message); } } } // 使用RSA算法加密数据 public static byte[] EncryptData(byte[] dataToEncrypt, RSAParameters publicKey) { using (RSA rsa = RSA.Create()) { try { rsa.ImportParameters(publicKey); return rsa.Encrypt(dataToEncrypt, RSAEncryptionPadding.OaepSHA256); } catch (CryptographicException e) { Console.WriteLine(e.Message); return null; } } } // 使用RSA算法解密数据 public static byte[] DecryptData(byte[] dataToDecrypt, RSAParameters privateKey) { using (RSA rsa = RSA.Create()) { try { rsa.ImportParameters(privateKey); return rsa.Decrypt(dataToDecrypt, RSAEncryptionPadding.OaepSHA256); } catch (CryptographicException e) { Console.WriteLine(e.Message); return null; } } } } ``` 这个示例代码中,我们使用`RSA.Create()`创建了一个RSA实例,并设置了密钥长度为2048位。然后,调用`ExportParameters()`方法生成公钥和私钥对。接下来,我们使用公钥加密数据,然后再用私钥解密数据。最后,我们将结果打印到控制台上。 需要注意的是,RSA算法对于较大的数据加密耗时较长,因此通常会使用RSA算法加密对称加密算法(如AES)的密钥,从而提高加密效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值