目录

一、RSA加密简介

二、公钥与私钥的理解

三、RSA加密解密

四、RSA签名和验证

五、加密的作用

六、两种不同的加密与解密

七、RSA加密、签名区别

八、RSA加密、签名的方法,代码例子如下:


一、RSA加密简介

  RSA加密是一种非对称加密。可以在不直接传递密钥的情况下,完成解密。这能够确保信息的安全性,避免了直接传递密钥所造成的被破解的风险。是由一对密钥来进行加解密的过程,分别称为公钥和私钥。两者之间有数学相关,该加密算法的原理就是对一极大整数做因数分解的困难性来保证安全性。通常个人保存私钥,公钥是公开的。

二、公钥与私钥的理解

 (1).私钥用来进行解密和签名,是给自己用的。
 (2).公钥由本人公开,用于加密和验证签名,是给别人用的。
    (3).当该用户发送文件时,用私钥签名,别人用他给的公钥验证签名,可以保证该信息是由他发送的。当该用户接受文件时,别人用他的公钥加密,他用私钥解密,可以保证该信息只能由他接收到解密读取。

三、RSA加密解密

 (1).获取密钥,这里是产生密钥,实际应用中可以从各种存储介质上读取密钥

(2).加密

(3).解密

四、RSA签名和验证

(1).获取密钥,这里是产生密钥,实际应用中可以从各种存储介质上读取密钥

(2).获取待签名的Hash码

(3).获取已经签名的字符串

(4).验证

五、加密的作用

(1).明文变密文(你不知道密钥是很难解密的); 
    (2).数据的一致性(hash值一样); 
    (3).数据的可信任性(验签)。

六、两种不同的加密与解密

(1)对称加密:加密与解密使用相同的密钥,处理速度快; 
   (2)非对称加密:加密与解密使用不同的密钥(生对生成),处理速度不及对称加密。 
   (3).在非对称加密中,究竟是公钥加密还是私钥加密的问题

1)如果只是用加密的用途 
   公钥加密,私钥解密(私钥只有一个,公钥大家都知道)。 
2)如果用验签 
   私钥加密,公钥解密(解密的来源是私钥,其它的来源是不可信任的)。

七、RSA加密、签名区别

  加密和签名都是为了安全性考虑,但略有不同。常有人问加密和签名是用私钥还是公钥?其实都是对加密和签名的作用有所混淆。简单的说,加密是为了防止信息被泄露,而签名是为了防止信息被篡改。这里举2个例子说明。

第一个场景:战场上,B要给A传递一条消息,内容为某一指令。

RSA的加密过程如下:

(1)A生成一对密钥(公钥和私钥),私钥不公开,A自己保留。公钥为公开的,任何人可以获取。

(2)A传递自己的公钥给B,B用A的公钥对消息进行加密。

(3)A接收到B加密的消息,利用A自己的私钥对消息进行解密。

  在这个过程中,只有2次传递过程,第一次是A传递公钥给B,第二次是B传递加密消息给A,即使都被敌方截获,也没有危险性,因为只有A的私钥才能对消息进行解密,防止了消息内容的泄露。

第二个场景:A收到B发的消息后,需要进行回复“收到”。

RSA签名的过程如下:

(1)A生成一对密钥(公钥和私钥),私钥不公开,A自己保留。公钥为公开的,任何人可以获取。

(2)A用自己的私钥对消息加签,形成签名,并将加签的消息和消息本身一起传递给B。

(3)B收到消息后,在获取A的公钥进行验签,如果验签出来的内容与消息本身一致,证明消息是A回复的。

  在这个过程中,只有2次传递过程,第一次是A传递加签的消息和消息本身给B,第二次是B获取A的公钥,即使都被敌方截获,也没有危险性,因为只有A的私钥才能对消息进行签名,即使知道了消息内容,也无法伪造带签名的回复给B,防止了消息内容的篡改。

  但是,综合两个场景你会发现,第一个场景虽然被截获的消息没有泄露,但是可以利用截获的公钥,将假指令进行加密,然后传递给A。第二个场景虽然截获的消息不能被篡改,但是消息的内容可以利用公钥验签来获得,并不能防止泄露。所以在实际应用中,要根据情况使用,也可以同时使用加密和签名,比如A和B都有一套自己的公钥和私钥,当A要给B发送消息时,先用B的公钥对消息加密,再对加密的消息使用A的私钥加签名,达到既不泄露也不被篡改,更能保证消息的安全性。

  总结:公钥加密、私钥解密、私钥签名、公钥验签。

八、RSA加密、签名的方法,代码例子如下:

(1).以常规字符串形式传递密匙

import java.io.ByteArrayOutputStream;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import org.apache.commons.codec.binary.Base64;public class TestRSA {/*** RSA最大加密明文大小*/private static final int MAX_ENCRYPT_BLOCK = 117;/*** RSA最大解密密文大小*/private static final int MAX_DECRYPT_BLOCK = 128;/*** 获取密钥对* * @return 密钥对*/public static KeyPair getKeyPair() throws Exception {KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");generator.initialize(1024);return generator.generateKeyPair();}/*** 获取私钥* * @param privateKey 私钥字符串* @return*/public static PrivateKey getPrivateKey(String privateKey) throws Exception {KeyFactory keyFactory = KeyFactory.getInstance("RSA");byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);return keyFactory.generatePrivate(keySpec);}/*** 获取公钥* * @param publicKey 公钥字符串* @return*/public static PublicKey getPublicKey(String publicKey) throws Exception {KeyFactory keyFactory = KeyFactory.getInstance("RSA");byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);return keyFactory.generatePublic(keySpec);}/*** RSA加密* * @param data 待加密数据* @param publicKey 公钥* @return*/public static String encrypt(String data, PublicKey publicKey) throws Exception {Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, publicKey);int inputLen = data.getBytes().length;ByteArrayOutputStream out = new ByteArrayOutputStream();int offset = 0;byte[] cache;int i = 0;// 对数据分段加密while (inputLen - offset > 0) {if (inputLen - offset > MAX_ENCRYPT_BLOCK) {cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);} else {cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);}out.write(cache, 0, cache.length);i++;offset = i * MAX_ENCRYPT_BLOCK;}byte[] encryptedData = out.toByteArray();out.close();// 获取加密内容使用base64进行编码,并以UTF-8为标准转化成字符串// 加密后的字符串return new String(Base64.encodeBase64String(encryptedData));}/*** RSA解密* * @param data 待解密数据* @param privateKey 私钥* @return*/public static String decrypt(String data, PrivateKey privateKey) throws Exception {Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, privateKey);byte[] dataBytes = Base64.decodeBase64(data);int inputLen = dataBytes.length;ByteArrayOutputStream out = new ByteArrayOutputStream();int offset = 0;byte[] cache;int i = 0;// 对数据分段解密while (inputLen - offset > 0) {if (inputLen - offset > MAX_DECRYPT_BLOCK) {cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);} else {cache = cipher.doFinal(dataBytes, offset, inputLen - offset);}out.write(cache, 0, cache.length);i++;offset = i * MAX_DECRYPT_BLOCK;}byte[] decryptedData = out.toByteArray();out.close();// 解密后的内容 return new String(decryptedData, "UTF-8");}/*** 签名* * @param data 待签名数据* @param privateKey 私钥* @return 签名*/public static String sign(String data, PrivateKey privateKey) throws Exception {byte[] keyBytes = privateKey.getEncoded();PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PrivateKey key = keyFactory.generatePrivate(keySpec);Signature signature = Signature.getInstance("MD5withRSA");signature.initSign(key);signature.update(data.getBytes());return new String(Base64.encodeBase64(signature.sign()));}/*** 验签* * @param srcData 原始字符串* @param publicKey 公钥* @param sign 签名* @return 是否验签通过*/public static boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception {byte[] keyBytes = publicKey.getEncoded();X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PublicKey key = keyFactory.generatePublic(keySpec);Signature signature = Signature.getInstance("MD5withRSA");signature.initVerify(key);signature.update(srcData.getBytes());return signature.verify(Base64.decodeBase64(sign.getBytes()));}public static void main(String[] args) {try {// 生成密钥对KeyPair keyPair = getKeyPair();String privateKey = new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));String publicKey = new String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));System.out.println("私钥:" + privateKey);System.out.println("公钥:" + publicKey);// RSA加密String data = "待加密的文字内容";String encryptData = encrypt(data, getPublicKey(publicKey));System.out.println("加密后内容:" + encryptData);// RSA解密String decryptData = decrypt(encryptData, getPrivateKey(privateKey));System.out.println("解密后内容:" + decryptData);// RSA签名String sign = sign(data, getPrivateKey(privateKey));// RSA验签boolean result = verify(data, getPublicKey(publicKey), sign);System.out.print("验签结果:" + result);} catch (Exception e) {e.printStackTrace();System.out.print("加解密异常");}}
}

(2).以文件形式形式保存在本地

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;import javax.crypto.Cipher;import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;/*** RSA加密,支持分片加密* <pre>* BCD码(Binary-Coded Decimal‎)亦称二进码十进数或二-十进制代码。* 用4位二进制数来表示1位十进制数中的0~9这10个数码。* 是一种二进制的数字编码形式,用二进制编码的十进制代码。* 注:日常所说的BCD码大都是指8421BCD码形式* @author Ming* */
public class RSAUtil {/** 指定加密算法为RSA */private static String ALGORITHM = "RSA";/** 指定key的大小 */private static int KEYSIZE = 1024;/** 指定公钥存放文件 */private static String PUBLIC_KEY_FILE = "d:/PublicKey";/** 指定私钥存放文件 */private static String PRIVATE_KEY_FILE = "d:/PrivateKey";public static final String KEY_ALGORITHM = "RSA";/** 自定义一个串 */public static final String SIGNATURE_ALGORITHM = "shihaiming@#!RSA";/*** 生成密钥对*/public static void generateKeyPair() throws Exception {if (getpublickey() == null || getprivatekey() == null) {/** RSA算法要求有一个可信任的随机数源 */SecureRandom sr = new SecureRandom();/** 为RSA算法创建一个KeyPairGenerator对象 */KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM);/** 利用上面的随机数据源初始化这个KeyPairGenerator对象 */kpg.initialize(KEYSIZE, sr);/** 生成密匙对 */KeyPair kp = kpg.generateKeyPair();/** 得到公钥 */Key publicKey = kp.getPublic();/** 得到私钥 */Key privateKey = kp.getPrivate();/** 用对象流将生成的密钥写入文件 */ObjectOutputStream oos1 = new ObjectOutputStream(new FileOutputStream(PUBLIC_KEY_FILE));ObjectOutputStream oos2 = new ObjectOutputStream(new FileOutputStream(PRIVATE_KEY_FILE));oos1.writeObject(publicKey);oos2.writeObject(privateKey);/** 清空缓存,关闭文件输出流 */oos1.close();oos2.close();}}/*** 产生签名* * @param data* @param privateKey* @return* @throws Exception*/public static String sign(byte[] data, String privateKey) throws Exception {// 解密由base64编码的私钥byte[] keyBytes = decryptBASE64(privateKey);// 构造PKCS8EncodedKeySpec对象PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);// KEY_ALGORITHM 指定的加密算法KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);// 取私钥对象PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);// 用私钥对信息生成数字签名Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);signature.initSign(priKey);signature.update(data);return encryptBASE64(signature.sign());}/*** 验证签名* * @param data* @param publicKey* @param sign* @return* @throws Exception*/public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {// 解密由base64编码的公钥byte[] keyBytes = decryptBASE64(publicKey);// 构造X509EncodedKeySpec对象X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);// KEY_ALGORITHM 指定的加密算法KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);// 取公钥对象PublicKey pubKey = keyFactory.generatePublic(keySpec);Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);signature.initVerify(pubKey);signature.update(data);// 验证签名是否有效return signature.verify(decryptBASE64(sign));}/*** BASE64解密* * @param key* @return* @throws Exception*/public static byte[] decryptBASE64(String key) throws Exception {return (new BASE64Decoder()).decodeBuffer(key);}/*** BASE64加密* * @param key* @return* @throws Exception*/public static String encryptBASE64(byte[] key) throws Exception {return (new BASE64Encoder()).encodeBuffer(key);}/*** 加密方法 source: 源数据*/public static String encrypt(String source) throws Exception {/** 将文件中的公钥对象读出 */ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));Key key = (Key) ois.readObject();ois.close();/** 得到Cipher对象来实现对源数据的RSA加密 */Cipher cipher = Cipher.getInstance(ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, key);int MaxBlockSize = KEYSIZE / 8;int len = (MaxBlockSize - 11) / 8;String[] datas = splitString(source, len);StringBuffer mi = new StringBuffer();for (String s : datas) {mi.append(bcd2Str(cipher.doFinal(s.getBytes())));}return mi.toString();}/*** 字符串分片* * @param string*            源字符串* @param len*            单片的长度(keysize/8)* @return*/public static String[] splitString(String string, int len) {int x = string.length() / len;int y = string.length() % len;int z = 0;if (y != 0) {z = 1;}String[] strings = new String[x + z];String str = "";for (int i = 0; i < x + z; i++) {if (i == x + z - 1 && y != 0) {str = string.substring(i * len, i * len + y);} else {str = string.substring(i * len, i * len + len);}strings[i] = str;}return strings;}/*** bcd 转 Str* * @param bytes* @return*/public static String bcd2Str(byte[] bytes) {char temp[] = new char[bytes.length * 2], val;for (int i = 0; i < bytes.length; i++) {val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');val = (char) (bytes[i] & 0x0f);temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');}return new String(temp);}/*** 解密* * @param cryptograph*            :密文* @return 解密后的明文* @throws Exception*/public static String decrypt(String cryptograph) throws Exception {/** 将文件中的私钥对象读出 */@SuppressWarnings("resource")ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));Key key = (Key) ois.readObject();/** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */Cipher cipher = Cipher.getInstance(ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, key);int key_len = KEYSIZE / 8;byte[] bytes = cryptograph.getBytes();byte[] bcd = ASCII2BCD(bytes, bytes.length);StringBuffer sBuffer = new StringBuffer();byte[][] arrays = splitArray(bcd, key_len);for (byte[] arr : arrays) {sBuffer.append(new String(cipher.doFinal(arr)));}return sBuffer.toString();}/*** ASCII 转 BCD* * @param ascii* @param asc_len* @return*/public static byte[] ASCII2BCD(byte[] ascii, int asc_len) {byte[] bcd = new byte[asc_len / 2];int j = 0;for (int i = 0; i < (asc_len + 1) / 2; i++) {bcd[i] = asc2bcd(ascii[j++]);bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc2bcd(ascii[j++])) + (bcd[i] << 4));}return bcd;}/*** asc转bcd* * @param asc* @return*/public static byte asc2bcd(byte asc) {byte bcd;if ((asc >= '0') && (asc <= '9'))bcd = (byte) (asc - '0');else if ((asc >= 'A') && (asc <= 'F'))bcd = (byte) (asc - 'A' + 10);else if ((asc >= 'a') && (asc <= 'f'))bcd = (byte) (asc - 'a' + 10);elsebcd = (byte) (asc - 48);return bcd;}/*** 字节数组分片* * @param data* @param len* @return*/public static byte[][] splitArray(byte[] data, int len) {int x = data.length / len;int y = data.length % len;int z = 0;if (y != 0) {z = 1;}byte[][] arrays = new byte[x + z][];byte[] arr;for (int i = 0; i < x + z; i++) {arr = new byte[len];if (i == x + z - 1 && y != 0) {System.arraycopy(data, i * len, arr, 0, y);} else {System.arraycopy(data, i * len, arr, 0, len);}arrays[i] = arr;}return arrays;}/** 将文件中的公钥对象读出 */public static String getpublickey() {try {@SuppressWarnings("resource")ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));Key key = (Key) ois.readObject();String publickey = encryptBASE64(key.getEncoded());return publickey;} catch (Exception e) {e.printStackTrace();}return null;}/** 将文件中的私钥对象读出 */public static String getprivatekey() {try {@SuppressWarnings("resource")ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));Key key = (Key) ois.readObject();String privatekey = encryptBASE64(key.getEncoded());return privatekey;} catch (Exception e) {e.printStackTrace();}return null;}public static void main(String[] args) {try {//生成公钥、私钥文件
//            generateKeyPair();String s = encrypt("https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&ch=3");System.out.println("加密:"+s);System.out.println("解密:"+decrypt(s));//再用base64加解密String a = encryptBASE64(s.getBytes());System.out.println(a);String b = new String(decryptBASE64(a));System.out.println(b);System.out.println("解密b:"+decrypt(b));} catch (Exception e) {e.printStackTrace();}}
}
import com.adph.jms.Base64Utils;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;public class RSAKeyUtils {private static String RAS_PUBLICKEY_PATH = "D://security.key";private static String RSA_PRIVATEKEY_PATH= "D://security.crt";public RSAKeyUtils() {}protected static void init(String RAS_PUBLICKEY_PATH,String RSA_PRIVATEKEY_PATH) {try {FileUtils.forceMkdir(new File(new File(RAS_PUBLICKEY_PATH).getParent()));Map<String, Object> keyPair = new HashMap();RSAHelper.generateKeyPair(keyPair);RSAHelper.saveKeyPair(keyPair, RAS_PUBLICKEY_PATH,RSA_PRIVATEKEY_PATH);} catch (IOException e) {e.printStackTrace();}}public static void setKeyPath(String keyPath) {RAS_PUBLICKEY_PATH = keyPath;}public static void setCrtPath(String crtPath) {RSA_PRIVATEKEY_PATH = crtPath;}public static String encByPublicKey(String data) {String dataBack = "";try {if (!StringUtils.isEmpty(data)) {byte[] Bytes = RSAHelper.encryptWithPublicKey(data.getBytes(),0, data.getBytes().length,RSAHelper.getKey(RAS_PUBLICKEY_PATH));dataBack = Base64Utils.encode(Bytes);}} catch (Exception e) {e.printStackTrace();}return dataBack;}public static String encByPrivateKey(String data) {String dataBack = "";try {if (!StringUtils.isEmpty(data)) {byte[] Bytes = RSAHelper.encryptWithPrivateKey(data.getBytes(),0, data.getBytes().length,RSAHelper.getKey(RSA_PRIVATEKEY_PATH));dataBack = Base64Utils.encode(Bytes);}} catch (Exception e) {e.printStackTrace();}return dataBack;}public static String decByPublicKey(String data) {String dataBack = "";try {if (!StringUtils.isEmpty(data)) {byte[] Bytes = RSAHelper.decryptWithPublicKey(Base64Utils.decode(data), 0,Base64Utils.decode(data).length,RSAHelper.getKey(RAS_PUBLICKEY_PATH));dataBack = new String(Bytes);}} catch (Exception e) {e.printStackTrace();}return dataBack;}public static String decByPrivateKey(String data) {String dataBack = "";try {if (!StringUtils.isEmpty(data)) {byte[] Bytes = RSAHelper.decryptWithPrivateKey(Base64Utils.decode(data), 0,Base64Utils.decode(data).length,RSAHelper.getKey(RSA_PRIVATEKEY_PATH));dataBack = new String(Bytes);}} catch (Exception e) {e.printStackTrace();}return dataBack;}public static String doSignPrivateKey(String data) {String dataBack = "";try {if (!StringUtils.isEmpty(data)) {byte[] Bytes = RSAHelper.sign(data.getBytes(), 0,data.getBytes().length,RSAHelper.getKey(RSA_PRIVATEKEY_PATH));dataBack = Base64Utils.encode(Bytes);}} catch (Exception e) {e.printStackTrace();}return dataBack;}public static boolean doVerifyPublicKey(String data, String sign) {Boolean returnFlag = Boolean.FALSE;if ((StringUtils.isEmpty(data)) || (StringUtils.isEmpty(sign))) {return Boolean.FALSE.booleanValue();}try {returnFlag = Boolean.valueOf(RSAHelper.verify(data.getBytes(), 0,data.getBytes().length,RSAHelper.getKey(RAS_PUBLICKEY_PATH),Base64Utils.decode(sign)));} catch (Exception e) {e.printStackTrace();}return returnFlag.booleanValue();}//  public static void main(String[] args) {
//      init("D://security.key", "D://security.crt");
//  }
}
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Cipher;public class RSAHelper {public static final String KEY_ALGORITHM = "RSA";private static final int KEY_LENGTH = 1024;public static final String PUBLIC_KEY = "PublicKey";public static final String PRIVATE_KEY = "PrivateKey";private static final int MAX_ENCRYPT_BLOCK = 117;private static final int MAX_DECRYPT_BLOCK = 128;private static final String SIGNATURE_ALGORITHM = "MD5withRSA";public RSAHelper() {}public static void generateKeyPair(Map<String, Object> keyMap) {boolean result = false;KeyPairGenerator keyPairGenerator = null;try {keyPairGenerator = KeyPairGenerator.getInstance("RSA");result = true;} catch (NoSuchAlgorithmException ex) {Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null,ex);}if (result) {SecureRandom secureRandom = new SecureRandom();String currentDateTime = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());secureRandom.setSeed(currentDateTime.getBytes());keyPairGenerator.initialize(1024, secureRandom);KeyPair keyPair = keyPairGenerator.genKeyPair();PublicKey publicKey = keyPair.getPublic();PrivateKey privateKey = keyPair.getPrivate();keyMap.put("PublicKey", publicKey.getEncoded());keyMap.put("PrivateKey", privateKey.getEncoded());}}public static void saveKeyPair(Map<String, Object> keyPair,String publicKeyFileName, String privateKeyFileName) {try {FileOutputStream fileOutputStream = new FileOutputStream(publicKeyFileName);byte[] publicKey = (byte[]) keyPair.get("PublicKey");fileOutputStream.write(publicKey);fileOutputStream.close();} catch (FileNotFoundException ex) {Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null,ex);} catch (IOException ex) {Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null,ex);}try {FileOutputStream fileOutputStream = new FileOutputStream(privateKeyFileName);byte[] privateKey = (byte[]) keyPair.get("PrivateKey");fileOutputStream.write(privateKey);fileOutputStream.close();} catch (FileNotFoundException ex) {Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null,ex);} catch (IOException ex) {Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null,ex);}}public static byte[] getKey(String keyFileName) {byte[] keyBytes = null;try {File file = new File(keyFileName);FileInputStream fileInputStream = new FileInputStream(file);DataInputStream dataInputStream = new DataInputStream(fileInputStream);keyBytes = new byte[(int) file.length()];dataInputStream.readFully(keyBytes);dataInputStream.close();fileInputStream.close();} catch (FileNotFoundException ex) {Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null,ex);} catch (IOException ex) {Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null,ex);}return keyBytes;}public static byte[] encryptWithPublicKey(byte[] data, int offSet,int length, byte[] keyBytes) throws Exception {X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");Key publicK = keyFactory.generatePublic(x509KeySpec);Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(1, publicK);ByteArrayOutputStream out = new ByteArrayOutputStream();int i = 0;while (length - offSet > 0) {byte[] cache;if (length - offSet > 117) {cache = cipher.doFinal(data, offSet, 117);} else {cache = cipher.doFinal(data, offSet, length - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * 117;}byte[] encryptedData = out.toByteArray();out.close();return encryptedData;}public static byte[] encryptWithPrivateKey(byte[] data, int offSet,int length, byte[] keyBytes) throws Exception {PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(1, privateK);ByteArrayOutputStream out = new ByteArrayOutputStream();int i = 0;while (length - offSet > 0) {byte[] cache;if (length - offSet > 117) {cache = cipher.doFinal(data, offSet, 117);} else {cache = cipher.doFinal(data, offSet, length - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * 117;}byte[] encryptedData = out.toByteArray();out.close();return encryptedData;}public static byte[] decryptWithPublicKey(byte[] data, int offSet,int length, byte[] keyBytes) throws Exception {X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");Key publicK = keyFactory.generatePublic(x509KeySpec);Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(2, publicK);ByteArrayOutputStream out = new ByteArrayOutputStream();int i = 0;while (length - offSet > 0) {byte[] cache;if (length - offSet > 128) {cache = cipher.doFinal(data, offSet, 128);} else {cache = cipher.doFinal(data, offSet, length - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * 128;}byte[] decryptedData = out.toByteArray();out.close();return decryptedData;}public static byte[] decryptWithPrivateKey(byte[] data, int offSet,int length, byte[] keyBytes) throws Exception {PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(2, privateK);ByteArrayOutputStream out = new ByteArrayOutputStream();int i = 0;while (length - offSet > 0) {byte[] cache;if (length - offSet > 128) {cache = cipher.doFinal(data, offSet, 128);} else {cache = cipher.doFinal(data, offSet, length - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * 128;}byte[] decryptedData = out.toByteArray();out.close();return decryptedData;}public static byte[] sign(byte[] data, int offset, int length,byte[] privateKeyBytes) {byte[] signedData = null;try {PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);Signature signature = Signature.getInstance("MD5withRSA");signature.initSign(privateKey);signature.update(data, offset, length);signedData = signature.sign();} catch (Exception ex) {Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null,ex);}return signedData;}public static boolean verify(byte[] data, int offset, int length,byte[] publicKeyBytes, byte[] dataSignature) {boolean result = false;try {X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);Signature signature = Signature.getInstance("MD5withRSA");signature.initVerify(publicKey);signature.update(data, offset, length);result = signature.verify(dataSignature);} catch (Exception ex) {Logger.getLogger(RSAHelper.class.getName()).log(Level.SEVERE, null,ex);}return result;}
}

PS:RSA加密对明文的长度有所限制,规定需加密的明文最大长度=密钥长度-11(单位是字节,即byte),所以在加密和解密的过程中需要分块进行。而密钥默认是1024位,即1024位/8位-11=128-11=117字节。所以默认加密前的明文最大长度117字节,解密密文最大长度为128字。那么为啥两者相差11字节呢?是因为RSA加密使用到了填充模式(padding),即内容不足117字节时会自动填满,用到填充模式自然会占用一定的字节,而且这部分字节也是参与加密的。

  密钥长度的设置就是上面例子的第32行。可自行调整,当然非对称加密随着密钥变长,安全性上升的同时性能也会有所下降。

RSA加密、解密、签名、验签的原理及方法相关推荐

  1. RSA 加密解密签名验签

    api package v1// get请求 import "github.com/gogf/gf/v2/frame/g"type GetKeyReq struct {g.Meta ...

  2. RSACryptoServiceProvider加密解密签名验签和DESCryptoServiceProvider加解密

    RSACryptoServiceProvider加密解密签名验签和DESCryptoServiceProvider加解密 原文:RSACryptoServiceProvider加密解密签名验签和DES ...

  3. js rsa验签_js rsa sign使用笔记(加密,解密,签名,验签)

    你将会收获: js如何加密, 解密 js如何签名, 验签 js和Java交互如何相互解密, 验签(重点) 通过谷歌, 发现jsrsasign库使用者较多. 查看api发现这个库功能很健全. 本文使用方 ...

  4. C# RSACryptoServiceProvider加密解密签名验签和DESCryptoServic

    C#在using System.Security.Cryptography下有 DESCryptoServiceProvider RSACryptoServiceProvider  DESCrypto ...

  5. RSA加密和验签的原理及方法

    RSA加密和验签的原理及方法 本文大纲 一.RSA加密简介 二.RSA加密.签名区别 三.RSA的加密过程 四.RSA签名的过程 一.RSA加密简介 RSA加密:属于非对称加密的范畴 这种加密方式可在 ...

  6. iOS使用Security.framework进行RSA 加密解密签名和验证签名

    iOS 上 Security.framework为我们提供了安全方面相关的api: Security框架提供的RSA在iOS上使用的一些小结 支持的RSA keySize 大小有:512,768,10 ...

  7. golang RSA base64 加解密 签名验签

    1.秘钥.加密/签名字符串加密的格式 目前主要见到有hex及base64 (1)hex 针对hex的加解密 import ("encoding/hex" ) hex.DecodeS ...

  8. java rsa 验_Java使用RSA加密解密签名及校验

    RSA加密解密类: package com.ihep; import java.io.BufferedReader; import java.io.BufferedWriter; import jav ...

  9. 数据安全管理:RSA加密算法,签名验签流程详解

    本文源码:GitHub·点这里 || GitEE·点这里 一.RSA算法简介 1.加密解密 RSA加密是一种非对称加密,在公开密钥加密和电子商业中RSA被广泛使用.可以在不直接传递密钥的情况下,完成加 ...

最新文章

  1. easyUI与选择WebUI
  2. ajax回调函数ifelse,实现AJAX及用Promise解决回调函数命名问题
  3. 为什么要开发抽象编程语言(APL)?
  4. Flash数据的采集方法-搜房房价走势采集
  5. 使用jar的两点注意事项
  6. ML之K-means:基于K-means算法利用电影数据集实现对top 100 电影进行文档分类
  7. wx.createInnerAudioContext seek方法执行后,监听事件onTimeUpdate无效?
  8. Installshield 文件及文件夹操作
  9. 设计模式学习笔记——抽象工厂(Abstract Factory)模式
  10. Django学习手册 - 前端input数据获取
  11. 三天花三万!跟董事长女儿相亲却被骗财?世纪佳缘致歉杭州小吴并承诺赔偿...
  12. Linux tar命令
  13. 算法之【折半插入法】
  14. 设计模式二:结构型模式
  15. xml文件、jsp文件、sql文件、shell脚本文件注释
  16. 【数据结构的魅力】008.图
  17. SVN server
  18. 自解压shell文件的制作
  19. 哪款投影仪做家庭影院效果好?家用投影仪哪个好
  20. 腾讯视频云流媒体技术探索

热门文章

  1. 计算机研究生开题,计算机研究生论文开题报告
  2. 在Apple Watch上使用Siri发送消息的方法
  3. CPU变频工具包cpufrequtils
  4. 机器学习笔记-神经网络的原理、数学、代码与手写数字识别
  5. 年薪25k*14| 华睿科技招聘机器人算法工程师
  6. am335x omap serial 驱动分析
  7. 制表符和空格 python_Python编程中的制表符与空格
  8. java maven项目更改项目名字
  9. FZU - 2230 翻翻棋
  10. Java学习路线【转载自topinking老兄的blog】