PollardRho 算法Java实现

PollardRho 算法Java实现

理论参考

以下代码基于Java实现,目前只能在整数群上使用。

package top.metadev.algorithms;

import java.math.BigInteger;
import java.util.LinkedHashMap;

public class PollardRho {
    // sa+tb=(a,b)
    public static BigInteger[] ext_gcd(BigInteger a, BigInteger b) {
        BigInteger s1 = BigInteger.ONE, t1 = BigInteger.ZERO, r1 = a;
        BigInteger s2 = BigInteger.ZERO, t2 = BigInteger.ONE, r2 = b;
        BigInteger q = BigInteger.ZERO, temp1, temp2, temp3;
        while (!r2.equals(BigInteger.ZERO)) {
            q = r1.divide(r2);
            temp1 = s1.subtract(q.multiply(s2));
            temp2 = t1.subtract(q.multiply(t2));
            temp3 = r1.subtract(q.multiply(r2));
            s1 = s2;
            t1 = t2;
            r1 = r2;
            s2 = temp1;
            t2 = temp2;
            r2 = temp3;
        }
        return new BigInteger[]{s1, t1, r1};
    }

    private final BigInteger THREE = BigInteger.valueOf(3);
    private LinkedHashMap<BigInteger, Tuple> tupleMap = new LinkedHashMap<>();

    public PollardRho(BigInteger alpha, BigInteger beta, BigInteger p, BigInteger ord) {
        this.alpha = alpha;
        this.beta = beta;
        P = p;
        this.ord = ord;
        tupleMap.put(BigInteger.ZERO, new Tuple(BigInteger.ONE, BigInteger.ZERO, BigInteger.ZERO));
    }

    private class Tuple {
        private BigInteger x;
        private BigInteger a;
        private BigInteger b;

        public Tuple(BigInteger x, BigInteger a, BigInteger b) {
            this.x = x;
            this.a = a;
            this.b = b;
        }

        public Tuple() {
        }

        public BigInteger getX() {
            return x;
        }

        public void setX(BigInteger x) {
            this.x = x;
        }

        public BigInteger getA() {
            return a;
        }

        public void setA(BigInteger a) {
            this.a = a;
        }

        public BigInteger getB() {
            return b;
        }

        public void setB(BigInteger b) {
            this.b = b;
        }
    }

    private final BigInteger alpha, beta, P, ord;

    private Tuple f(Tuple tuple) {
        BigInteger mod = tuple.getX().mod(THREE);
        Tuple res = new Tuple();
        if (mod.equals(BigInteger.ONE)) {
            //1 class
            res.setX(tuple.getX().multiply(beta).mod(P));
            res.setA(tuple.getA().mod(ord));//不模ord结果会非常大的
            res.setB(tuple.getB().add(BigInteger.ONE).mod(ord));

        } else if (mod.equals(BigInteger.ZERO)) {
            //2 class
            res.setX(tuple.getX().modPow(BigInteger.TWO, P));
            res.setA(tuple.getA().multiply(BigInteger.TWO).mod(ord));
            res.setB(tuple.getB().multiply(BigInteger.TWO).mod(ord));
        } else {
            //3 class
            res.setX(tuple.getX().multiply(alpha).mod(P));
            res.setA(tuple.getA().add(BigInteger.ONE).mod(ord));
            res.setB(tuple.getB().mod(ord));
        }
        return res;
    }

    // res = log alpha {beta}
    public BigInteger getResult() {
        BigInteger index = BigInteger.ONE;
        BigInteger res = BigInteger.ZERO;
        while (index.compareTo(ord) < 0) {
            Tuple temp = tupleMap.get(index.subtract(BigInteger.ONE));
            Tuple next = f(temp);
            tupleMap.put(index, next);
            if (index.mod(BigInteger.TWO).equals(BigInteger.ZERO)) {
                Tuple res1 = tupleMap.get(index);
                Tuple res2 = tupleMap.get(index.divide(BigInteger.TWO));
                if (res1.getX().equals(res2.getX())) {
                    if (!ord.gcd(res2.getB().subtract(res1.getB())).equals(BigInteger.ONE)) {
                        System.out.println("用线性同余式求解");

                        BigInteger b = res2.getB().subtract(res1.getB());
                        BigInteger d = ord.gcd(b);
                        BigInteger a = res1.getA().subtract(res2.getA());
                        if (!a.divideAndRemainder(d)[1].equals(BigInteger.ZERO)) {
                            System.out.println("无解");
                            break;
                        }
                        BigInteger c0 = a.divide(d).multiply(b.divide(d).modInverse(ord.divide(d))).mod(ord.divide(d));
//                        for (BigInteger i = BigInteger.ZERO; i.compareTo(d) < 0; i = i.add(BigInteger.ONE)) {
//                            System.out.println(alpha.modPow(c0.add(ord.divide(d).multiply(i)), P));
//                            System.out.println(c0.add(ord.divide(d).multiply(i)));
//
//                        }
                        res = c0;


                        break;
                    }else{
                        res = res1.getA().subtract(res2.getA()).multiply(res2.getB().subtract(res1.getB()).modInverse(ord)).mod(ord);
                        System.out.println("计算完成。");
                        break;
                    }

                }

            }

            index = index.add(BigInteger.ONE);

        }
        return res;
    }

    //测试结果
    public static void main(String[] args) {
        PollardRho pollardRho = new PollardRho(BigInteger.valueOf(89), BigInteger.valueOf(618),
                BigInteger.valueOf(809), BigInteger.valueOf(101));
        BigInteger result = pollardRho.getResult();
        System.out.println(result);

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

都学点

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值