zoukankan      html  css  js  c++  java
  • RSA算法浅入浅出

    RSA算法流程

    生成公钥私钥

    1. 找出两个大质数p,q,位数最好超过1024位,质数越大破解难度越大,这两个质数不能公开
    2. n = p * q
    3. f(n) = (p - 1) * (q - 1)
    4. 公钥e,满足1 < e < f(n),且e与f(n)互质
    5. 私钥d,满足e * d % f(n) = 1

    加密过程

    1. 加密方需要知道n,和公钥e。
    2. 设加密信息为m,m必须小于n,大于的话则将信息分组再传
    3. 加密过程:明文m -> m^e % n -> 密文c(注意这里的^是幂运算,不是异或,下同)

    解密过程

    1. 解密方需要知道n,和私钥d
    2. 设收到的密码信息为c,解密过程:密文c -> c^d % n -> 明文m

    补充

    加解密过程可以互换,公钥加密的信息只有私钥才可以解密,所以可以用于给传递信息。

    同理,私钥加密的内容公钥可以解密,因此可以用于验证信息。

    大质数可以考虑通过Miller-Rabin素数检测算法生成,公钥似乎都选65537,私钥通过扩展欧几里得算法计算,加解密过程可使用快速幂

    Java实现

    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.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import java.util.Date;
    import java.util.Scanner;
    import javax.crypto.Cipher;
    import org.springframework.util.Base64Utils;
    
    public class RSADemo {
    
    	private static final int KEY_SIZE = 2048;
    	private static final String KEY_ALGORITHM = "RSA";
    	private static KeyFactory KEY_FACTORY;
    	
    	static {
    		try {
    			KEY_FACTORY = KeyFactory.getInstance(KEY_ALGORITHM);
    		} catch (NoSuchAlgorithmException e) {
    			e.printStackTrace();
    		}
    	}
    
    	/**
    	 * 私钥加密
    	 * 
    	 * @param data
    	 * @param key
    	 * @return
    	 * @throws Exception
    	 */
    	public static byte[] encryptByPrivateKey(byte[] data, byte[] key) throws Exception {
    		PKCS8EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec(key);
    		PrivateKey privateKey = KEY_FACTORY.generatePrivate(encodedKeySpec);
    		Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
    		cipher.init(Cipher.ENCRYPT_MODE, privateKey);
    		return cipher.doFinal(data);
    	}
    
    	/**
    	 * 私钥解密
    	 * 
    	 * @param data
    	 * @param key
    	 * @return
    	 * @throws Exception
    	 */
    	public static byte[] decryptByPrivateKey(byte[] data, byte[] key) throws Exception {
    		PKCS8EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec(key);
    		PrivateKey privateKey = KEY_FACTORY.generatePrivate(encodedKeySpec);
    		Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
    		cipher.init(Cipher.DECRYPT_MODE, privateKey);
    		return cipher.doFinal(data);
    	}
    
    	/**
    	 * 公钥加密
    	 * 
    	 * @param data
    	 * @param key
    	 * @return
    	 * @throws Exception
    	 */
    	public static byte[] encryptByPublicKey(byte[] data, byte[] key) throws Exception {
    		X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(key);
    		PublicKey publicKey = KEY_FACTORY.generatePublic(encodedKeySpec);
    		Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
    		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    		return cipher.doFinal(data);
    	}
    
    	/**
    	 * 公钥解密
    	 * @param data
    	 * @param key
    	 * @return
    	 * @throws Exception
    	 */
    	public static byte[] decryptByPublicKey(byte[] data, byte[] key) throws Exception {
    		X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(key);
    		PublicKey publicKey = KEY_FACTORY.generatePublic(encodedKeySpec);
    		Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
    		cipher.init(Cipher.DECRYPT_MODE, publicKey);
    		return cipher.doFinal(data);
    	}
    
    	/**
    	 * 生成公钥、私钥
    	 * 
    	 * @return
    	 * @throws NoSuchAlgorithmException
    	 */
    	public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
    		KeyPairGenerator generator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
    		SecureRandom random = new SecureRandom(new Date().toString().getBytes());
    		generator.initialize(KEY_SIZE, random);
    		KeyPair keyPair = generator.generateKeyPair();
    		return keyPair;
    	}
    	
    	public static void main(String[] args) throws Exception {
    		KeyPair keyPair = generateKeyPair();
    		byte[] publicKey = keyPair.getPublic().getEncoded();
    		byte[] privateKey = keyPair.getPrivate().getEncoded();
    		System.out.println("公钥:
    " + Base64Utils.encodeToString(publicKey));
    		System.out.println("私钥:
    " + Base64Utils.encodeToString(privateKey));
    		System.out.println("----------------------");
    		System.out.println("开始测试");
    		Scanner scanner = new Scanner(System.in);
    		while (scanner.hasNext()) {
    			String text = scanner.next();
    			byte[] encode = encryptByPrivateKey(text.getBytes(), privateKey);
    			byte[] decode = decryptByPublicKey(encode, publicKey);
    			System.out.println("原文:" + text);
    			System.out.println("私钥加密:" + Base64Utils.encodeToString(encode));
    			System.out.println("公钥解密:" + new String(decode));
    			System.out.println("-----------------------");
    			encode = encryptByPublicKey(text.getBytes(), publicKey);
    			decode = decryptByPrivateKey(encode, privateKey);
    			System.out.println("公钥加密:" + Base64Utils.encodeToString(encode));
    			System.out.println("私钥解密:" + new String(decode));
    			System.out.println("-----------------------");
    		}
    		scanner.close();
    	}
    }
    

    测试结果如下:

    公钥:
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqMQk9jmhovxJrPWO/3BLGmgU+v3AVNBaXA4QZJRQX86F9Yaof5tV3mpTUV4mhHoJJ16zr7m81LAgoYxaP6iQ+sLw/Z4YEtV+Ze7ghRVYnfgdgSbM0GVD26Wo/Zaz/Qn4NdC6oAigXEM6o+RffZdvkuFyzxG9PRBppVweTXvhv3fo3F/U/sc+rrJuny5DMamF7Vm4WUgKraEcEg+ijl7eSszG8Qh7waY1eum2uklSCtSKwvTiV0A+ICdobKIyNl2syX9wUWMJW9fHRBwxGAIGjwO5cJID6HF2iYm/7+ZBkurWhkvGOLxlCshX1W12VbKj0KMiBF8BMiMdCPUvMFg7qwIDAQAB
    私钥:
    MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCoxCT2OaGi/Ems9Y7/cEsaaBT6/cBU0FpcDhBklFBfzoX1hqh/m1XealNRXiaEegknXrOvubzUsCChjFo/qJD6wvD9nhgS1X5l7uCFFVid+B2BJszQZUPbpaj9lrP9Cfg10LqgCKBcQzqj5F99l2+S4XLPEb09EGmlXB5Ne+G/d+jcX9T+xz6usm6fLkMxqYXtWbhZSAqtoRwSD6KOXt5KzMbxCHvBpjV66ba6SVIK1IrC9OJXQD4gJ2hsojI2XazJf3BRYwlb18dEHDEYAgaPA7lwkgPocXaJib/v5kGS6taGS8Y4vGUKyFfVbXZVsqPQoyIEXwEyIx0I9S8wWDurAgMBAAECggEAcrBBEhdeMf3TL7f8wriUQVDEGUGCh+DD11UzbLah3EnkHVOyhG2SsEB/eIdME7E/MUMZR20o1z0OH9rapfIu/EqoLSJX58ywRiNM7wPvogKwQkmU3HZE5CqzKgpVLLuusxuzB/h0yd5iJmiXQCk+iImvVOsQOEREFzz/1tY+NrfuuBUo3qZVZEGYLPylz2Lpv0AjNecR50OC2wEHwmPlbU28dJYksTPYLhAmk5PSXaQ8IrSTcs0IK2JTrtbQV1Bk05W9CWSmkQoZiGwqJ2nOdeQce9e7ID1Avj8QgPhdDvf66FO9wLucyhscbji2DU7Hv+5jfRKVHWwCFzfXOwg1UQKBgQD2I3VvMhskqrOMb19IP3cw0YRxkjm44q/0GUXdGhd2wYKEXpwa1K653ojYC1ZX1UsYyHk7s6HWDQzgcq9mJ/XmEQxKBgozdEmV7jRUfjPjRQaslo3TOsAmm9sjvp9aoh7dYZs9NYC6cxqSY4tkZHwJ40AEhZ6bgA7Glt3oxoYnswKBgQCvhxwRECoanCnOrisgynk7z4pI96L81zepKV2Me6rIfi8XKq9qkaCgv9j7lgd1O0aV3pboPrcQ1ZpE7LU2L+mDpCCU0RIrZZDPfs94MldGar5DJ02aqqTcsd/7PGfpsqA4TQgCHXn6TstacYC+LRR5ksNP0/W+XtX1BWD6vcSgKQKBgEdKgesREjeOka6tW2WrrDQhm0Dh34Ijdl83KrsdoYouBkWcuY4z59/CCtS4g+uwxa2J80NNhiRfZ0ljLlZiYKCgc3TFRxMcLWwVsGaAnzrGdWZrvOxfaeRE5DX4MmOn7VSlvrb91ikqyZl455jOWfbrMVGd+hCECMOQUvnm9lhtAoGAdTy77VWrmZxmfCpumfdCpEVJqtTkIxaoka8UUamj90f4sfOLuJVOATBCgD/D+XQ/AAjtKHADHBZfdNvZaTj1MjzkmiFOjnfHEiAz+Kc/DcRsEjRlLAIAHXwdCxRcn4X0Z8Zjq+3+M8Z/IoifIebAPzdchqwe/ikfpQkTrkYj14kCgYB1rBYcgzvoMkI7+OgTiU2d2SJcLMKK0Ctem4WEz/qHOZtx+K74lL5ixs/4WrRKLQzo/2junZHU4weucaW39CXHMszjh5DCjnkTwN9857mTxAy8UTGmUS6prv+HgwvxKJDuYRwsGWDV6gKvWWU+guUIwyuq5wFmzWt67mmUSaoEJw==
    ----------------------
    开始测试
    原文:沙雕网友发的什么玩意儿?
    私钥加密:CJ+TXFiHP6nj7RoGVntXnaPHi0bPFTAapbhh1f3IZpNiupi1GH+fR+C7y7B25vACqfCgbRK8mV/UORhtCfcQySttKDufQZF9NnWsbNzDa+6Y1ElEsFVfk4xUThxEKHYsMdHK2NUt4LmaHyd3NMjFvwL7CHr9u0M+7DjzXtejsAH3vKUtdn/JTcfml8NDRFkGhkvqj/GdmOa8iw682nkQFot4R9HYu1/4a36TV2L++BNKU2rBis/BGgNslrgOea4nnYVdx/LjEBmr5FNpkijpLFVu8VjOjgZmCgixFsT9rD5rQCO45y/346JOOBDSkeH9DCHoKOZ3tMP6CSo84iuwPw==
    公钥解密:沙雕网友发的什么玩意儿?
    -----------------------
    公钥加密:T4Y9iu1H199KD1GoodrUFVkY+uqP2pFlVoHauT8837et1iiv4pOGqFwXGWvCDlNqFVXHejyqLWmVghyPG1rKagG53ytW4kpw+8wVPRJFvHnpWPPgR7Cft69owbYCJwjoknTnEf4TYTHZd3EuyMSxgzb8b9hIrzdWCJ0JyDNbmnj6IgIPf0MoQ1hehzSXlXQbaRKu5EGesZLtlezH73bN5DtAhog2avjREfOVkbJmbcqt5SIUEM+DVljY2IVGVw2ibj848PRaLTL2THAgSrIEGsQoOSXUz8s9ufLPmdXiogxsxh72buRct3qRN3wEmP5kEL7SdYCSf1YIygPeZ5FrpQ==
    私钥解密:沙雕网友发的什么玩意儿?
    

    初次了解加密算法,可能理解的比较肤浅。先记录一下,日后有机会再深究。

  • 相关阅读:
    通信错误:(-1)[描述:无法解析路由器DDNS地址,请检查DDNS状态.] 解析办法
    小数量宽带用户的福音,Panabit 云计费easyradius 接口隆重发布,PA宽带计费系统
    送给那些经常问我如何设置360测速结果为电信的朋友,360测速模块原理简单分析
    Universal-Image-Loader(UIL)使用方法&流程图&源码分析 ----- 未完
    Android开发框架
    Android线程池的使用(未完)
    Android LruCache究竟是什么
    Java finally语句到底是在return之前还是之后执行?
    Android自定义图片加载框架
    Android 自定义View实现单击和双击事件
  • 原文地址:https://www.cnblogs.com/corvey/p/10469747.html
Copyright © 2011-2022 走看看