RSA算法代码如下:
package gj.secure;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
/**
* @author areful
* Date: 2019/2/12
*/
@SuppressWarnings("WeakerAccess")
public class RSAUtil {
public static final String KEY_ALGORITHM_AES = "RSA";
public static final String KEY_ALGORITHM_AES_PCKS1PADDING = "RSA/ECB/PKCS1PADDING";
public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
private static final int MAX_ENCRYPT_BLOCK = 117;
private static final int MAX_DECRYPT_BLOCK = 128;
public static KeyPair genKeyPair() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM_AES);
keyPairGen.initialize(1024);
return keyPairGen.generateKeyPair();
}
public static byte[] encryptByPublicKey(byte[] data, byte[] pubKey) throws Exception {
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM_AES_PCKS1PADDING);
cipher.init(Cipher.ENCRYPT_MODE, KeyFactory.getInstance(KEY_ALGORITHM_AES).generatePublic(new X509EncodedKeySpec(pubKey)));
return doFinal(cipher, data, data.length, true);
}
public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM_AES);
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM_AES_PCKS1PADDING);
cipher.init(Cipher.ENCRYPT_MODE, keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKey)));
return doFinal(cipher, data, data.length, true);
}
public static byte[] decryptByPublicKey(byte[] encryptedData, byte[] publicKey) throws Exception {
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM_AES_PCKS1PADDING);
cipher.init(Cipher.DECRYPT_MODE, KeyFactory.getInstance(KEY_ALGORITHM_AES).generatePublic(new X509EncodedKeySpec(publicKey)));
return doFinal(cipher, encryptedData, encryptedData.length, false);
}
public static byte[] decryptByPrivateKey(byte[] encryptedData, byte[] privateKey) throws Exception {
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM_AES_PCKS1PADDING);
cipher.init(Cipher.DECRYPT_MODE, KeyFactory.getInstance(KEY_ALGORITHM_AES).generatePrivate(new PKCS8EncodedKeySpec(privateKey)));
return doFinal(cipher, encryptedData, encryptedData.length, false);
}
public static byte[] sign(byte[] data, byte[] privateKey) throws Exception {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(KeyFactory.getInstance(KEY_ALGORITHM_AES).generatePrivate(new PKCS8EncodedKeySpec(privateKey)));
signature.update(data);
return signature.sign();
}
public static boolean verify(byte[] data, byte[] publicKey, byte[] sign) throws Exception {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(KeyFactory.getInstance(KEY_ALGORITHM_AES).generatePublic(new X509EncodedKeySpec(publicKey)));
signature.update(data);
return signature.verify(sign);
}
private static byte[] doFinal(Cipher cipher, byte[] data, int inputLen, boolean isEncryptMode) throws Exception {
int maxBlockSize = isEncryptMode ? MAX_ENCRYPT_BLOCK : MAX_DECRYPT_BLOCK;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
while (inputLen - offSet > 0) {
if (inputLen - offSet > maxBlockSize) {
cache = cipher.doFinal(data, offSet, maxBlockSize);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * maxBlockSize;
}
byte[] result = out.toByteArray();
out.close();
return result;
}
}
如果在网上传输,不能直接传byte[]类型数组,部分字节会和网络传输协议控制类字符冲突。通常都是转换一次,例如使用Base64编码发送,接收方收到后再Base64解码,这样就不会有冲突了。
以下是Base64封装:
package gj.secure;
import java.security.KeyFactory;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
/**
* @author areful
* Date: 2019/2/12
*/
public class RSAWrapper extends RSAUtil {
public static String encryptByPublicKey(String data, String publicKey) throws Exception {
return encode2Base64(encryptByPublicKey(decodeFromBase64(data), decodeFromBase64(publicKey)));
}
public static String encryptByPrivateKey(String data, String privateKey) throws Exception {
return encode2Base64(encryptByPrivateKey(decodeFromBase64(data), decodeFromBase64(privateKey)));
}
public static String decryptByPublicKey(String data, String publicKey) throws Exception {
return new String(decryptByPublicKey(decodeFromBase64(data), decodeFromBase64(publicKey)));
}
public static String decryptByPrivateKey(String data, String privateKey) throws Exception {
return new String(decryptByPrivateKey(decodeFromBase64(data), decodeFromBase64(privateKey)));
}
public static String sign(String data, String privateKey) throws Exception {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(KeyFactory.getInstance(KEY_ALGORITHM_AES)
.generatePrivate(new PKCS8EncodedKeySpec(decodeFromBase64(privateKey))));
signature.update(decodeFromBase64(data));
return encode2Base64(signature.sign());
}
public static boolean verify(String data, String publicKey, String sign) throws Exception {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(KeyFactory.getInstance(KEY_ALGORITHM_AES)
.generatePublic(new X509EncodedKeySpec(decodeFromBase64(publicKey))));
signature.update(decodeFromBase64(data));
return signature.verify(decodeFromBase64(sign));
}
private static String encode2Base64(byte[] data) {
return java.util.Base64.getEncoder().encodeToString(data);
}
private static byte[] decodeFromBase64(String src) {
return java.util.Base64.getDecoder().decode(src);
}
}
测试代码:
package gj.secure;
import org.junit.Test;
import java.security.KeyPair;
import java.util.Arrays;
/**
* @author areful
* Date: 2019/2/12
*/
public class TestRSAUtil {
@Test
public void testEncryptByPublicKey() throws Exception {
KeyPair keyPair = RSAUtil.genKeyPair();
byte[] publicKey = keyPair.getPublic().getEncoded();
byte[] privateKey = keyPair.getPrivate().getEncoded();
System.err.println("私钥加密——公钥解密");
String src = "第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。";
System.out.println("原文字:\t" + src);
byte[] encodedData = RSAUtil.encryptByPublicKey(src.getBytes(), publicKey);
System.out.println("加密后:\t" + Arrays.toString(encodedData));
String plainText = new String(RSAUtil.decryptByPrivateKey(encodedData, privateKey));
System.out.println("解密后: \t" + plainText);
System.err.println("私钥签名——公钥验证签名");
byte[] sign = RSAUtil.sign(encodedData, privateKey);
System.err.println("签名:\t\t" + Arrays.toString(sign));
boolean status = RSAUtil.verify(encodedData, publicKey, sign);
System.err.println("验证结果:\t" + status);
}
}
package gj.secure;
import org.junit.Test;
import java.util.Base64;
/**
* @author areful
* Date: 2019/2/12
*/
public class TestRSAWrapper {
@Test
public void testEncryptByPrivateKey() throws Exception {
String pubKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDW7SUABMZltXXlQ0ZG2WZe6i64Jq0hb6QpC0cvA49zUyrzkfQrH2" +
"JYoPohmVWqKn+vYj4HKFtBHsPUI/3COLv/tQ7oOQGrf9o0JhaZwktiq+pJbTe2jlw8UZm8+xhIDGGDZ/dXQyRHKfkTyJJqwVv1" +
"dE1CIFenCoPp2JztsYS7iQIDAQAB";
String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANbtJQAExmW1deVDRkbZZl7qLrgmrSFvpCkLRy8Dj3" +
"NTKvOR9CsfYlig+iGZVaoqf69iPgcoW0Eew9Qj/cI4u/+1Dug5Aat/2jQmFpnCS2Kr6kltN7aOXDxRmbz7GEgMYYNn91dDJEcp" +
"+RPIkmrBW/V0TUIgV6cKg+nYnO2xhLuJAgMBAAECgYByhAKN4v1u3ePGVzUPtPAlrHNeLUVcJmb6c4bnFueNFAgzpVXK0DsPbB" +
"46Xr/VHjXQVfEk0SzmIqVG2DJyFNadq0RqGmPDTPit1cO7aWQb3fZEUUpORZt1TCqIShirzoO830w1dJJW7MhyoKUAPLLsi5be" +
"rFj7VaagOnmnZTgXsQJBAPSt1Qg++6Pat/7rwB46GhlTQvY6HOa0O9IcFWf262ihTJHJApYpvEvuLA6TKRAdP7EJ2ItwkoFFjQ" +
"bbKDq6I5UCQQDg3uYGKNmoIwkfVVzgcaLg4wEaAPftmS+pp3Q8l66BonBsYhG4kiYr9NepwPa9ZiSdZtXKEkkeWM6qZ1OeMXsl" +
"AkEAqBsiqWa0d3BXSBLrTRk4QzwcXpWws6UTEJlw75wLQzjHJcaIO2lzUGvT4zOiW8rsrpMIL01pqt2BNjuumSK4PQJAB9K5Xe1" +
"95QOTBawKlyRc7kX3e9gcx/9UUSqqOJFuWMQ19Q9UXn93JIBYIGe+Lcin7XHubiFEufGM/xCpMA+4oQJBAJRp1TLVinccyGw3v3" +
"vB96WQH89SUnmk5tR5ydSrB+3qr2lsiJtcH0i5R5EjYdFpIgpUEBEmL+s/LLLP9Rd7I+k=";
String text = "第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1," +
"ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。";
String base64Text = Base64.getEncoder().encodeToString(text.getBytes());
//公钥加密私钥解密
String cipherText = RSAWrapper.encryptByPublicKey(base64Text, pubKey);
System.out.println("公钥加密:\t" + cipherText);
String plainText = RSAWrapper.decryptByPrivateKey(cipherText, privateKey);
System.out.println("私钥解密:\t" + plainText);
text = "第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1," +
"并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功," +
"Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。";
base64Text = Base64.getEncoder().encodeToString(text.getBytes());
//私钥加密公钥解密
cipherText = RSAWrapper.encryptByPrivateKey(base64Text, privateKey);
System.out.println("私钥加密:\t" + cipherText);
plainText = RSAWrapper.decryptByPublicKey(cipherText, pubKey);
System.out.println("公钥解密:\t" + plainText);
System.err.println("私钥签名——公钥验证签名");
String sign = RSAWrapper.sign(cipherText, privateKey);
System.err.println("签名:\t\t" + sign);
boolean status = RSAWrapper.verify(cipherText, pubKey, sign);
System.err.println("验证结果:\t" + status);
}
}