RSA加密算法总结

来源:互联网 发布:电脑tv电视直播软件 编辑:程序博客网 时间:2024/06/05 16:14

RSA算法使用步骤如下:


一、获取公钥和私钥

  1. 找到两个素数p, q,计算 N =p * q
  2. r = (p - 1) * (q - 1)
  3. 取 e,使得 e 满足 1 < e < r, 且 e 与 r 互质
  4. 取 d 使得 (d * e) % r = 1, 即 ed ≡ 1 (mod r)
    相当于方程 ex - ry = 1, 求得一组解即可

    这样就得到三个整数 N, e, d
    公钥 KU = (N, e) 私钥 RU = (N, d)

二、加密与解密

  1. 加密
    已知:公钥 KU = (N, e), 明文为 m
    则加密后的密文 M = m^e% N
    ^ 表示次方
  2. 解密
    已知:私钥为 RU = (N, d), 密文为 M
    则解密后的明文 m = M^d % N

三、实例详解
例题:已知 p = 3, q = 11, 明文 m = 15, 求公钥、密钥及密文。

解:

N = p * q = 33,r = (p - 1) * (q - 1) = 2 x 10 = 20,取 e = 7 (e满足1 < e < r, 且 er 互质)(d * e) % r = 1, 即 d 要满足 (7d) % 20 = 1利用穷举法,取 d = 3则公钥 KU = (33, 7), 密钥 RU = (33, 3)密文 M = m^e % N = 15^7 % 33 = 27(若要根据 M = 27 解密,则 m = M^d % 33 = 27^3 % 33 = 15)

三、JAVA实现

package util.encrypt;import java.math.BigInteger;/** * @Author: 你本来就很二 * @Date: 2017/6/13 * @Description: RSA加密 */public class RSA {    private BigInteger p;    private BigInteger q;    private BigInteger N;    private BigInteger r;    private BigInteger e;    private BigInteger d;    public RSA(BigInteger p, BigInteger q) {        //判断p、q是否为素数        if (!isPrimeNum(p) || !isPrimeNum(q))            throw new IllegalArgumentException("p or q is not prime number.");        this.p = p;        this.q = q;        //计算N        N = p.multiply(q);        //计算r        setR();        //以r/9位基数得到质数e        setE();        //取d        setD(r, e);    }    /**     * 加密, 已知公钥(e, N)     * @param e     * @param N     * @param m 明文     * @return     */    public static BigInteger encrypt(BigInteger e, BigInteger N, int m) {        return BigInteger.valueOf(m).modPow(e, N);    }    /**     * 解密, 已知密钥(d, N)     * @param d     * @param N     * @param M 密文     * @return     */    public static BigInteger dencrypt(BigInteger d, BigInteger N, int M) {        return BigInteger.valueOf(M).modPow(d, N);    }    private boolean isPrimeNum(BigInteger n) {        double value = Math.sqrt(n.doubleValue());        for (int i = 2; i < value; i++) {            if (n.mod(BigInteger.valueOf(i)).intValue() == 0) {                return false;            }        }        return true;    }    private void setD(BigInteger d1, BigInteger d2) {        BigInteger[] ret = new BigInteger[3];        BigInteger u = BigInteger.ONE;        BigInteger u1 = BigInteger.ZERO;        BigInteger v = BigInteger.ZERO;        BigInteger v1 = BigInteger.ONE;        if (d1.compareTo(d2) > 0) {            BigInteger tmp = d1;            d1 = d2;            d2 = tmp;        }        while (d2.compareTo(BigInteger.ZERO) != 0) {            BigInteger tq = d1.divide(d2);            BigInteger tu = u;            u = u1;            u1 = tu.subtract(tq.multiply(u1));            BigInteger tv = v;            v = v1;            v1 = tv.subtract(tq.multiply(v1));            BigInteger td1 = d1;            d1 = d2;            d2 = td1.subtract(tq.multiply(d2));            ret[0] = u;            ret[1] = v;            ret[2] = d1;        }        d = ret[0];    }    public BigInteger getD() {        return d;    }    public BigInteger getN() {        return N;    }    public BigInteger getE() {        return e;    }    public void setE() {        BigInteger tmp;        for (int i = 2; i < r.intValue(); i++) {            tmp = BigInteger.valueOf(i);            if (r.mod(tmp).intValue() != 0) {                e = tmp;                break;            }        }        if (e == null) {            throw new IllegalArgumentException("No value can set to e");        }    }    public BigInteger getR() {        return r;    }    public void setR() {        r = (p.subtract(                BigInteger.ONE)).multiply(                q.subtract(BigInteger.ONE));        if (r.intValue() == 2) {            throw new IllegalArgumentException("the value of r equals 2, e is not allowed this (1 < e < r).");        }    }    public BigInteger getP() {        return p;    }    public void setP(BigInteger p) {        this.p = p;    }    public BigInteger getQ() {        return q;    }    public void setQ(BigInteger q) {        this.q = q;    }    @Override    public String toString() {        return "RSA{" +                "p=" + p +                ", q=" + q +                ", N=" + N +                ", r=" + r +                ", e=" + e +                ", d=" + d +                '}';    }}

测试

package util.encrypt;import java.math.BigInteger;/** * @Author: 你本来就很二 * @Date: 2017/6/13 * @Description: */public class Test {    public static void main(String[] args) {        //得到密钥        RSA rsa = new RSA(BigInteger.valueOf(5), BigInteger.valueOf(37));        System.out.println(rsa);        System.out.println("公钥: (" + rsa.getE() + ", " + rsa.getN() + ")");        System.out.println("密钥: (" + rsa.getD() + ", " + rsa.getN() + ")");        //加密        BigInteger e = rsa.getE();        BigInteger N = rsa.getN();        int m = 17;        BigInteger strM = RSA.encrypt(e, N, m);        System.out.println("明文 " + m + " 加密后的密文是: " + strM.intValue());        //解密        BigInteger d = rsa.getD();        BigInteger strm = RSA.dencrypt(d, N, Integer.valueOf(strM.intValue()));        System.out.println("密文 " + strM + " 解密后的明文是: " + strm);    }}

测试结果

RSA{p=5, q=37, N=185, r=144, e=5, d=29}公钥: (5, 185)密钥: (29, 185)明文 17 加密后的密文是: 167密文 167 解密后的明文是: 17

RSA算法原理(一)
RSA算法原理(二)