非对称密码之RSA算法

1、RSA算法的简介

     由Ron Rivest、 Adi Shamir 和 Leonard Adleman三位学者提出的非对称加密算法。RSA 算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。它是第一个既能用于数据加密也能用于数字签名的算法。

2、RSA 数学原理

    (1)加解密公式
            RSA加密:密文 = 明文E mod N      公钥(E,N)
            RSA解密:明文 = 密文D mod N      私钥(D,N)
    (2)模拟生成密钥对
            1)求N:p=17 q=19           N=p*q = 323
            2)求L:L=lcm(p-1,q-1)=lcm(16,18) = 144
            3)求E:gcd(E,L)=1           E=5
            4)求D:E*D mod L = 1    D=29
                 公钥(5,323)     私钥(29,323)
             

    (3)加密
            密文 = 明文E mod N = 1235 mod 323 = 225
    (4)解密
            明文 = 密文D mod N = 22529 mod 323 = 123

3、JDK的实现

      

4、RSA算法编程步骤

     4.1  生成公钥和私钥

        

     4.2  加密/解密

         

5、RSA算法的实现

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;

public class RSAUtil {

	public static final String PUBLIC_KEY = "RSAPublicKey";
	public static final String PRIVATE_KEY = "RSAPrivateKey";
	public static final String KEY = "RSA";

	/**
	 * 生成 RSA 的 公钥 和 私钥
	 * 
	 * @return
	 */
	public static Map<String, Object> initKey() {
		try {
			KeyPairGenerator keyPairGenerator = KeyPairGenerator
					.getInstance(KEY);
			keyPairGenerator.initialize(1024); // 512-65536 & 64的倍数
			KeyPair keyPair = keyPairGenerator.generateKeyPair();
			RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
			RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
			Map<String, Object> keyMap = new HashMap<String, Object>();
			keyMap.put(PUBLIC_KEY, publicKey);
			keyMap.put(PRIVATE_KEY, privateKey);
			return keyMap;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}

	/**
	 * 获取RSA的公钥
	 * 
	 * @param keyMap
	 * @return
	 */
	public static RSAPublicKey getPublicKey(Map<String, Object> keyMap) {
		RSAPublicKey publicKey = (RSAPublicKey) keyMap.get(PUBLIC_KEY);
		return publicKey;
	}

	/**
	 * 获取RSA的私钥
	 * 
	 * @param keyMap
	 * @return
	 */
	public static RSAPrivateKey getPrivateKey(Map<String, Object> keyMap) {
		RSAPrivateKey privateKey = (RSAPrivateKey) keyMap.get(PRIVATE_KEY);
		return privateKey;
	}

	/**
	 * 公钥加密
	 * 
	 * @param data
	 *            要加密的数据
	 * @param publicKey
	 *            公钥
	 * @return
	 * @throws Exception
	 */
	public static byte[] encrypt(byte[] data, RSAPublicKey publicKey) {
		try {
			Cipher cipher = Cipher.getInstance(KEY);
			cipher.init(Cipher.ENCRYPT_MODE, publicKey);
			byte[] cipherBytes = cipher.doFinal(data);
			return cipherBytes;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}

	/**
	 * 私钥解密
	 * 
	 * @param data
	 *            要解密的数据
	 * @param privateKey
	 *            私钥
	 * @return
	 * @throws Exception
	 */
	public static byte[] decrypt(byte[] data, RSAPrivateKey privateKey) {
		try {
			Cipher cipher = Cipher.getInstance(KEY);
			cipher.init(Cipher.DECRYPT_MODE, privateKey);
			byte[] plainBytes = cipher.doFinal(data);
			return plainBytes;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}

}


字节数组转16进制

public class BytesToHex {

	public static String fromBytesToHex(byte[] resultBytes) {
		StringBuilder builder = new StringBuilder();
		for (int i = 0; i < resultBytes.length; i++) {
			if (Integer.toHexString(0xFF & resultBytes[i]).length() == 1) {
				builder.append("0").append(
						Integer.toHexString(0xFF & resultBytes[i]));
			} else {
				builder.append(Integer.toHexString(0xFF & resultBytes[i]));
			}
		}
		return builder.toString();
	}

}
测试代码

public class Test {
	// 待加密的明文
	public static final String DATA = "test";

	public static void main(String[] args) throws Exception {
		/* Test RSA */
		Map<String, Object> keyMap = RSAUtil.initKey();
		RSAPublicKey rsaPublicKey = RSAUtil.getPublicKey(keyMap);
		RSAPrivateKey rsaPrivateKey = RSAUtil.getPrivateKey(keyMap);
		System.out.println("RSA PublicKey : " + rsaPublicKey);
		System.out.println("RSA PrivateKey : " + rsaPrivateKey);

		byte[] rsaResult = RSAUtil.encrypt(DATA.getBytes(), rsaPublicKey);
		System.out.println(DATA + ">>>RSA 加密>>>"
				+ BytesToHex.fromBytesToHex(rsaResult));

		byte[] plainResult = RSAUtil.decrypt(rsaResult, rsaPrivateKey);
		System.out.println(DATA + ">>>RSA 解密>>>" + new String(plainResult));

	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值