【Java小工匠聊密码学】--非对称加密--RSA1

1、什么是RSA 算法

  RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用。RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。   对极大整数做因数分解的难度决定了RSA算法的可靠性。换言之,对一极大整数做因数分解愈困难,RSA算法愈可靠。假如有人找到一种快速因数分解的算法的话,那么用RSA加密的信息的可靠性就肯定会极度下降。但找到这样的算法的可能性是非常小的。今天只有短的RSA钥匙才可能被强力方式解破。到目前为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。

2、RSA加密于解密

2.1、RSA 加密

密文=明文^E mod N

RSA加密,是明文的E次方,然后除以N的余数。 公式中的{E,N}的组合是RSA的公钥 。E,N 不是随便的数就可以的,需要经过严密的计算。

2.2、RSA 解密

明文=密文^D mod N

RSA解密,是对密文的D次方,然后除以N的余数。公式中的 {D,N}的组合是RSA的私钥匙 ,同样 N 是加密过程中的N,D也不是任意一个数字就可以的,也是需要经过严密的计算的。

2.3、生成密钥对

我们知道了RSA加密和解密的过程,运算过程中,需要使用的 E、D、N 这些数字需要严密的计算,那E、D、N 到底是应该如何计算呢? 计算分为如下几个步骤: (1)求N 首先准备两个很大的质数,p和q ,p 和q 太小的话,密钥很拥有被破解。

N = P*Q

(2)求L L 是 P-1 和 Q-1 的最小公倍数。lcm(X,Y)表示 “X和Y的最小公倍数”。

L = lcm(P-1,Q-1)

(3)求E E是一个比 1 大,比L小的数,此外 E 和 L的最大公约数必须是1,gcd(X,Y)表示"X和Y的最小公约数", E和L的关系需满足如下等式。

第一等式: 1 < E <L 第二等式: gcd(E,L)=1

要找出满足 gcd(E,L) =1 的数据,需要使用伪随机数生成器,通过伪随机数生成器,在1<E<L 的范围内生成E的候选数,然后判断是否满足 gcd(E,L) =1这个条件,求最大公约数可以使用 欧几里得的辗转相处法。 这么复杂的过程,找出N,目的是为了保证一定存在解密的时候需要的D。 (4)求D 数字 D 是由 E 计算出来的,D ,E ,L 满足如下关系。

第一等式 : 1<D < L 第二等式 : E * D mod L = 1

2.4、实践一把

(1)求 N 我们首先准备两个质数,

P = 13 Q = 17 N = P *Q = 221

(2) 求 L

L = lcm(p-1,q-1) L=lcm(12,16) L=48

(3) 求 E

第一等式: 1 < E <48 第二等式: gcd(E,48)=1 E 和L 的最大公约数是1 。

满足 E 的数据 5、7、11、13、17、19、23、25、29、31、35、37、41、43 我们这些选择 7 作为 E。 公钥 E = 13 ,N = 221 (4) 求 D

第一等式 : 1<D < L , 1 < D < 48 第二等式 : E * D mod L = 1 , 5 * D mod 48 = 1

D=37 满足上述条件。 (5) 公钥与私有

E = 13 D = 37 N = 221

(6) 加密

密文 = (m明文=10)^E(13)% N(221) =62

(7)解密

明文 = (密文=62)^(D)37 % N (221) = 62 ^37%221 = ( 62^10%221 ) * ( 62^10%221 ) * ( 62^7%221 ) % 221 = (62^5%221 * 62^5%221 %221)* (62^5%221 * 62^5%221 %221) * (62^5%221 * 62^5%221 %221) * (62^5%221 * 62^2%221 %221) %221 = (95 * 95 % 221) * (95 * 95 %221)(95 * 95 %221)* (95 * 62 * 62 %221) % 221 = 10

3、RAS算法实现

3.1、JDK算法实现

package lzf.cipher.jdk;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

/**
 * @author Java小工匠
 */
public class JdkRsaUtils {

    // 初始化密钥对
    public static KeyPair initKey() {
        try {
            KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
            // 512 -65536 && 64 的倍数
            generator.initialize(1024);
            return generator.generateKeyPair();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    // 获取公钥
    public static byte[] getPublicKey(KeyPair keyPair) {
        byte[] bytes = keyPair.getPublic().getEncoded();
        return bytes;
    }

    // 获取公钥
    public static String getPublicKeyStr(KeyPair keyPair) {
        byte[] bytes = keyPair.getPublic().getEncoded();
        return encodeHex(bytes);
    }

    // 获取私钥
    public static byte[] getPrivateKey(KeyPair keyPair) {
        byte[] bytes = keyPair.getPrivate().getEncoded();
        return bytes;
    }

    // 获取私钥
    public static String getPrivateKeyStr(KeyPair keyPair) {
        byte[] bytes = keyPair.getPrivate().getEncoded();
        return encodeHex(bytes);
    }

    // 加密数据
    public static byte[] encryptRsa(byte[] data, byte[] key) {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
            RSAPublicKey secretKey = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.PUBLIC_KEY, secretKey);
            byte[] rs = cipher.doFinal(data);
            return rs;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    // 解密数据
    public static byte[] decryptRsa(byte[] data, byte[] key) {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(key);
            RSAPrivateCrtKey secretKey = (RSAPrivateCrtKey) keyFactory.generatePrivate(keySpec);
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.PRIVATE_KEY, secretKey);
            byte[] rs = cipher.doFinal(data);
            return rs;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    // 数据准16进制编码
    public static String encodeHex(final byte[] data) {
        return encodeHex(data, true);
    }

    // 数据转16进制编码
    public static String encodeHex(final byte[] data, final boolean toLowerCase) {
        final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
        final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        final char[] toDigits = toLowerCase ? DIGITS_LOWER : DIGITS_UPPER;
        final int l = data.length;
        final char[] out = new char[l << 1];
        // two characters form the hex value.
        for (int i = 0, j = 0; i < l; i++) {
            out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
            out[j++] = toDigits[0x0F & data[i]];
        }
        return new String(out);
    }

    public static void main(String[] args) throws Exception {
        String str = "java小工匠";
        KeyPair keyPair = initKey();
        byte[] publicKey = getPublicKey(keyPair);
        byte[] privateKey = getPrivateKey(keyPair);
        byte[] secretData = encryptRsa(str.getBytes(), publicKey);
        System.out.println("RSA加密:" + encodeHex(secretData));
        byte[] data = decryptRsa(secretData, privateKey);
        System.out.println("RSA解密:" + new String(data));
    }
}

原文发布于微信公众号 - 小工匠技术圈(xgn177971793771)

原文发表时间:2018-07-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏杂文共赏

Node.Js生成比特币地址

1.生成随机私钥,私钥是一个32字节的数 例如: 8F72F6B29E6E225A36B68DFE333C7CE5E55D83249D3D2CD6332671F...

77215
来自专栏吴伟祥

加密 原

在日常设计及开发中,为确保数据传输和数据存储的安全,可通过特定的算法,将数据明文加密成复杂的密文。目前主流加密手段大致可分为单向加密和双向加密。

803
来自专栏一名叫大蕉的程序员

RSA 这俩世纪最重要的算法之一No.91

本文大概1000字,读完共需5分钟 Diffie–Hellman加密算法的劣势 上一篇文章我们聊到 Diffie–Hellman key exchange ...

3245
来自专栏安恒网络空间安全讲武堂

学习分享 | Padding Oracle

0x00前言 之前写CBC翻转攻击的时候就在想什么时候能遇到Padding Oracle的题目hhhhh 想不到这么快就遇到了hhhhh ------- 0x0...

2338
来自专栏贾老师の博客

加密与签名算法

3073
来自专栏企鹅号快讯

黑客们都是如何给勒索软件加密的?

加密是计算机科学中历史最长久的一种计算了。早在二战时期,德国就制造了Enigma密码机,来传输机密信息。计算机科学的祖师爷之一图灵也参与了对Enigma密码的破...

2269
来自专栏Java技术栈

常用加密算法解析

今天介绍下工作当中常用的加密算法、分类、应用。 1、对称加密算法 所谓对称,就是采用这种加密方法的双方使用方式用同样的密钥进行加密和解密。密钥是控制加密及解密过...

6937
来自专栏漏斗社区

CTF|玩转RSA加密算法(一)

RSA是一种非对称加密算法,它由 公钥(n/e),私钥(n/d),明文M和密文C组成。我们做CTF题目时,一般题目中会给出公钥和密文让我们推出对应的私钥或者明文...

7459
来自专栏上善若水

011各种加密算法比较

算法选择:对称加密AES,非对称加密: ECC,消息摘要: MD5,数字签名:DSA

2673
来自专栏jouypub

区块链之非对称加密算法

非对称加密,在现在网络应用中,有这非常广泛的场景,更是加密货币的基础。本文主要介绍非对称加密、解密的原理和过程,以及在区块链中的使用。

1831

扫码关注云+社区

领取腾讯云代金券