赞
踩
RSA非对称加密技术实现过程,代码如下:
- package com.zhongji.utils;
-
- import java.math.BigInteger;
- import java.util.Random;
-
- public class RSA {
- private final static int numLength = 1024;//素数长度
- private final static int accuracy = 100;//素数的准确率为1-(2^(-accuracy))
-
- //获取最大公约数
- private BigInteger getGCD(BigInteger a, BigInteger b) {
- if (b.byteValue() == 0) return a;
- return getGCD(b, a.mod(b));
- }
-
- //扩展欧几里得方法,计算 ax + by = 1中的x与y的整数解(a与b互质)
- private static BigInteger[] extGCD(BigInteger a, BigInteger b) {
- if (b.signum() == 0) {
- return new BigInteger[]{a, new BigInteger("1"), new BigInteger("0")};
- } else {
- BigInteger[] bigIntegers = extGCD(b, a.mod(b));
- BigInteger y = bigIntegers[1].subtract(a.divide(b).multiply(bigIntegers[2]));
- return new BigInteger[]{bigIntegers[0], bigIntegers[2], y};
- }
- }
-
- //超大整数超大次幂然后对超大的整数取模,利用蒙哥马利乘模算法,
- //(base ^ exp) mod n
- //依据(a * b) mod n=(a % n)*(b % n) mod n
- private static BigInteger expMode(BigInteger base, BigInteger exp, BigInteger mod) {
- BigInteger res = BigInteger.ONE;
- //拷贝一份防止修改原引用
- BigInteger tempBase = new BigInteger(base.toString());
- //从左到右实现简答
- for (int i = 0; i < exp.bitLength(); i++) {
- if (exp.testBit(i)) {//判断对应二进制位是否为1
- res = (res.multiply(tempBase)).mod(mod);
- }
- tempBase = tempBase.multiply(tempBase).mod(mod);
- }
- return res;
- }
-
- //产生公钥与私钥
- public static SecretKey generateKey(BigInteger p, BigInteger q) {
- //令n = p * q。取 φ(n) = (p-1) * (q-1)。
- BigInteger n = p.multiply(q);
- //计算与n互质的整数个数 欧拉函数
- BigInteger fy = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));
- //取 e ∈ [1 < e < φ(n) ] ,( n , e )作为公钥对,这里取65537
- BigInteger e = new BigInteger("65537");
- //计算ed与fy的模反元素d。令 ed mod φ(n) = 1,计算d,然后将( n , d ) 作为私钥对
- BigInteger[] bigIntegers = extGCD(e, fy);
- //计算出的x不能是负数,如果是负数,则进行x=x+fy。使x为正数,但是x<fy。
- BigInteger x = bigIntegers[1];
- if (x.signum() == -1) {
- x = x.add(fy);
- }
- //返回计算出的密钥
- return new SecretKey(n, e, x);
- }
-
- public static SecretKey generateKey() {
- BigInteger[] pq = getRandomPQ();
- return generateKey(pq[0], pq[1]);
- }
-
- //加密
- public static BigInteger encrypt(BigInteger text, SecretKey.PublicKey publicKey) {
- return expMode(text, publicKey.e, publicKey.n);
- }
-
- //解密
- public static BigInteger decrypt(BigInteger cipher, SecretKey.PrivateKey privateKey) {
- return expMode(cipher, privateKey.d, privateKey.n);
- }
-
- //加密
- public static String encrypt(String text, SecretKey.PublicKey publicKey) {
- return encrypt(new BigInteger(text.getBytes()), publicKey).toString();
- }
-
- //解密
- public static String decrypt(String chipper, SecretKey.PrivateKey privateKey) {
- BigInteger bigInteger = expMode(new BigInteger(chipper), privateKey.d, privateKey.n);
- byte[] bytes = new byte[bigInteger.bitLength() / 8 + 1];
- for (int i = 0; i < bytes.length; i++) {
- for (int j = 0; j < 8; j++) {
- if (bigInteger.testBit(j + i * 8)) {
- bytes[bytes.length - 1 - i] |= 1 << j;
- }
- }
- }
- return new String(bytes);
- }
-
- //产生两个随机1024位大质数
- public static BigInteger[] getRandomPQ() {
- BigInteger p = BigInteger.probablePrime(numLength, new Random());
- while (!p.isProbablePrime(accuracy)) {
- p = BigInteger.probablePrime(numLength, new Random());
- }
- BigInteger q = BigInteger.probablePrime(numLength, new Random());
- while (!q.isProbablePrime(accuracy)) {
- q = BigInteger.probablePrime(numLength, new Random());
- }
- return new BigInteger[]{p, q};
- }
-
- //密匙对
- static class SecretKey {
- BigInteger n, e, d;
-
- public SecretKey(BigInteger n, BigInteger e, BigInteger d) {
- this.n = n;
- this.e = e;
- this.d = d;
- }
-
- public PublicKey getPublicKey() {
- return new PublicKey(n, e);
- }
-
- public PrivateKey getPrivateKey() {
- return new PrivateKey(n, d);
- }
-
- //密钥
- static class PrivateKey {
- public BigInteger n, d;
-
- public PrivateKey(BigInteger n, BigInteger d) {
- this.n = n;
- this.d = d;
- }
- }
-
- //公钥
- static class PublicKey {
- public BigInteger n, e;
-
- public PublicKey(BigInteger n, BigInteger e) {
- this.n = n;
- this.e = e;
- }
- }
- }
-
-
- public static void main(String[] args) {
- SecretKey secretKey = RSA.generateKey();
- //明文内容不要超过1024位,超过后需要分段加密
- String text = "Hello world";
- String chipper = RSA.encrypt(text, secretKey.getPublicKey());
-
- System.out.println("加密后:\n" +
- //密文长度可能会随着随机密钥的改变而改变,最长不超过2048位
- "密文二进制长度:" + new BigInteger(chipper).bitLength()
- + "\n"
- + chipper);
- String origin = RSA.decrypt(chipper, secretKey.getPrivateKey());
- System.out.println("解密后:\n" + origin);
- }
- }
-
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。