RSA加密的简单使用

2025-08-03 05:55:45

RSA是一种非对称加密,发送方用公钥加密,接收方用私钥解密。只要私钥不泄漏,即使获得了公钥和数据,也无法进行解密。RSA的安全性依赖于大整数因式分解的困难,目前已知被分解的最大整数为768个二进制位,也就是说已知能被破解的最大RSA秘钥为768位,但是一般情况都采用1024位的秘钥,重要数据使用2048位的秘钥(当然安全性的提升要付出更多的解密时间)。

首先生成公钥和私钥:

public static void main(String[] args) {

try {

KeyPairGenerator kp = KeyPairGenerator.getInstance("RSA");

kp.initialize(1024); // 要是需要2048的秘钥的话就修改一下参数

KeyPair keyPair = kp.generateKeyPair();

PublicKey publicKey = keyPair.getPublic();

System.out.println("公钥为:" + new String(Base64.getEncoder().encode(publicKey.getEncoded())));

PrivateKey privateKey = keyPair.getPrivate();

System.out.println("私钥为:" + new String(Base64.getEncoder().encode(privateKey.getEncoded())));

} catch (NoSuchAlgorithmException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

执行就能得到结果:

公钥为:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDl0vjjliUX5ZfefPqQ8Mf57EBRWqcHHggs6AYRHYVWJWxkpSTYFbCLuU7R6MnAIaWFZrfLvVfTNE6or7aDmbeHFnYHOZwvZfPRPDL3Iu915wTM3Ns62kQuXNbHNspN/xxiLnSjzMUvbnL5aVc/NJazzuMg+FVma910w9i2c2EMmwIDAQAB

私钥为:MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOXS+OOWJRfll958+pDwx/nsQFFapwceCCzoBhEdhVYlbGSlJNgVsIu5TtHoycAhpYVmt8u9V9M0TqivtoOZt4cWdgc5nC9l89E8Mvci73XnBMzc2zraRC5c1sc2yk3/HGIudKPMxS9ucvlpVz80lrPO4yD4VWZr3XTD2LZzYQybAgMBAAECgYBHnZRdJv5sEelfNUbHP6CxKoNoVn1R5HPbunmZf7969rJuMl/mzetzvszm8EleC54OkdGYNWpWsCgKvKZ9H7tmT8yQfIwP5uvXZY9bbnL0mSU97LmdvJ/NW0+BDZYTz0Uz0OV6yvyluBe4g7YqhckzXToLO8SJrIB15W6hx2qhgQJBAPiBqvkZOPYL3ey9h+hhMyOE9VfFm/LxHxoCFM6MaN4IkBWCoOFMHoK7U4gVOwio3cURBUlHN5wlITwcyvktYbsCQQDswRYqJDBJ5tF412yy8RpF0glJRVM2FAgG0zz8bBvEYJMRVSVi9+Q1u+cFgIPvHDpkaOEezLq+pR3uBGKJ92KhAkBm3n5g+UDsEUN/sYFl/36E0JAjEkkZCxk90ei9C8CJUPAcB2QDf1gN8++DII68afLLld0jVVi+yVv1n1GiTlfrAkEAhrCCj47u+dwap4jHCjYoIDiRl+GcqVNUDa33MBPA6EOY529tSZSFfBxeHb8zT8DbZ2xTRlZqlzMQh+xustbOgQJBAJSq6ioVUR8YwYMl0VD4svuZiuv6aAu2P1BK3f/ftbPyDPm3SKn3TV0/Rpe3KJO1Di2G+8gXyR8tge6Dm3RAdoU=

当然每次得到的公钥私钥都是不一样的,然后把公钥交给发送方以进行加密:

public static void main(String[] args) {

// 公钥字符串,这里直接赋值了,当然一般不会这么写,把公钥放在一个数据文件或者配置里面去获取

String publicKeyStr = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDl0vjjliUX5ZfefPqQ8Mf57EBRWqcHHggs6AYRHYVWJWxkpSTYFbCLuU7R6MnAIaWFZrfLvVfTNE6or7aDmbeHFnYHOZwvZfPRPDL3Iu915wTM3Ns62kQuXNbHNspN/xxiLnSjzMUvbnL5aVc/NJazzuMg+FVma910w9i2c2EMmwIDAQAB";

try {

// 把公钥字符串转换成对象

byte[] publicKeyBy = Base64.getDecoder().decode(publicKeyStr.getBytes());

KeyFactory keyFactory = KeyFactory.getInstance("RSA");

PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(publicKeyBy));

// 以上获得的PublicKey可以固化下来,只要秘钥不变,就可以一直使用,但是下面的cipherPublic 不要固化!因为他不是线程安全的,如果使用同一个cipherPublic 并发访问时可能会抛出异常javax.crypto.IllegalBlockSizeException: Data must not be longer than 128 bytes

Cipher cipherPublic = Cipher.getInstance("RSA");

// 设置为加密模式并设置公钥

cipherPublic.init(Cipher.ENCRYPT_MODE, publicKey);

// 定义一个发送的数据

String sendMsg = "你好呀!";

// 获得加密的byte[]

byte[] encryptByte = cipherPublic.doFinal(sendMsg.toString().getBytes("UTF-8"));

// 转变成字符串以进行传输

String strKey = Base64.getEncoder().encodeToString(encryptByte);

System.out.println("加密后的数据为:" + strKey);

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

得到的结果为:

加密后的数据为:dBz/nSJ+jK13dhEhNZOeBcMgQjJfauWP9xl0OLYKiuhKOzYbI+zOezyM1PhHqTvl3hjaTf+wzpzUd+2p75v4Zn8sxSmRw8CIzXTtY/4g3v94cdZbvTfWe+snLXt7qTMdK9grrBqSvBhp/JsOPhd336h/lo77mYd0XEUNJhIFyl0=

获得加密数据后接收方就可以进行相应的解密了,不过要注意一些传输方式会破坏加密数据,如url的get方式传输时,加密数据的’+'会被转换成 ’ ',所以接收到数据之后要注意转换回来,不然就解密错误了:

public static void main(String[] args) {

// 私钥字符串,这里直接赋值了,同样的,可以把私钥放在一个数据文件或者配置里面去获取

String privateKeyStr = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOXS+OOWJRfll958+pDwx/nsQFFapwceCCzoBhEdhVYlbGSlJNgVsIu5TtHoycAhpYVmt8u9V9M0TqivtoOZt4cWdgc5nC9l89E8Mvci73XnBMzc2zraRC5c1sc2yk3/HGIudKPMxS9ucvlpVz80lrPO4yD4VWZr3XTD2LZzYQybAgMBAAECgYBHnZRdJv5sEelfNUbHP6CxKoNoVn1R5HPbunmZf7969rJuMl/mzetzvszm8EleC54OkdGYNWpWsCgKvKZ9H7tmT8yQfIwP5uvXZY9bbnL0mSU97LmdvJ/NW0+BDZYTz0Uz0OV6yvyluBe4g7YqhckzXToLO8SJrIB15W6hx2qhgQJBAPiBqvkZOPYL3ey9h+hhMyOE9VfFm/LxHxoCFM6MaN4IkBWCoOFMHoK7U4gVOwio3cURBUlHN5wlITwcyvktYbsCQQDswRYqJDBJ5tF412yy8RpF0glJRVM2FAgG0zz8bBvEYJMRVSVi9+Q1u+cFgIPvHDpkaOEezLq+pR3uBGKJ92KhAkBm3n5g+UDsEUN/sYFl/36E0JAjEkkZCxk90ei9C8CJUPAcB2QDf1gN8++DII68afLLld0jVVi+yVv1n1GiTlfrAkEAhrCCj47u+dwap4jHCjYoIDiRl+GcqVNUDa33MBPA6EOY529tSZSFfBxeHb8zT8DbZ2xTRlZqlzMQh+xustbOgQJBAJSq6ioVUR8YwYMl0VD4svuZiuv6aAu2P1BK3f/ftbPyDPm3SKn3TV0/Rpe3KJO1Di2G+8gXyR8tge6Dm3RAdoU=";

// 刚才我们获得的加密数据,一般通过各种传输途径接收到

String encryptReceiveMsg = "dBz/nSJ+jK13dhEhNZOeBcMgQjJfauWP9xl0OLYKiuhKOzYbI+zOezyM1PhHqTvl3hjaTf+wzpzUd+2p75v4Zn8sxSmRw8CIzXTtY/4g3v94cdZbvTfWe+snLXt7qTMdK9grrBqSvBhp/JsOPhd336h/lo77mYd0XEUNJhIFyl0=";

try {

// 把私钥字符串转换成对象

byte[] privateKeyBy = Base64.getDecoder().decode(privateKeyStr.getBytes());

KeyFactory keyFactory = KeyFactory.getInstance("RSA");

PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyBy));

// 同样的,可以固化cipherPrivate ,但是不能固化cipherPrivate,因为它不是线程安全的

Cipher cipherPrivate = Cipher.getInstance("RSA");

// 设置为解密模式并设置私钥

cipherPrivate.init(Cipher.DECRYPT_MODE, privateKey);

// 进行解密

byte[] decryptByte = cipherPrivate.doFinal(Base64.getDecoder().decode(encryptReceiveMsg));

// 转换成字符串

String receiveMsg = new String(decryptByte, "UTF-8");

System.out.println("解密后的数据:" + receiveMsg);

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

得到解密结果:

解密后的数据:你好呀!

人脸识别的奥秘:为什么我们会脸盲?一文读懂人脸识别技术
有哪些好看的古典音乐杂志?