算法中的补0问题 RSA用p和q生成n, e, d, p, q, dp, dq, qInv结果qinv有少数前面少00导致无法注入

遇到这种问题怎么排查

1.p和q大部分生成的都是正常的。500台中有6台问题。
2.先把n, e, d, p, q, dp, dq, qInv全解出来,与工具解出来的对比一下。查不一致 特别是长度与数据内容。跟正确的对照一下,有什么不一样。
3.发现Qinv长度少一位。用工具试 工具自动加了00,有些工具没加。
4.为什么要用p和q,因为这样快。

使用这个工具可以生成,Bits要填对2048

在这里插入图片描述

出现问题的是JAVA代码

下面生成的qInv是127字符。 BigInteger qInv = q.modInverse§; 再转成 RSAPrivateCrtKey rsaKey 再获取rsaKey.getCrtCoefficient().toByteArray() 就是空的。

 // 从16进制字符串生成BigInteger
    public static BigInteger hexToBigInt(String hex) {
        return new BigInteger(hex, 16);
    }

    // 用p, q生成私钥(e = 65537)
    public static PrivateKey generatePrivateKeyFromPQ(String hexP, String hexQ) throws Exception {
        Log.d(TAG, "hexP:"+hexP);
        Log.d(TAG, "hexQ:"+hexQ);
        BigInteger p = hexToBigInt(hexP);
        BigInteger q = hexToBigInt(hexQ);
        BigInteger n = p.multiply(q);                            // n = p * q
        BigInteger phi = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));
        BigInteger e = BigInteger.valueOf(65537);                // 通常使用 65537 作为公钥指数
        BigInteger d = e.modInverse(phi);                        // 私钥指数 d = e^-1 mod φ(n)

        BigInteger dp = d.mod(p.subtract(BigInteger.ONE));       // d mod (p - 1)
        BigInteger dq = d.mod(q.subtract(BigInteger.ONE));       // d mod (q - 1)
        BigInteger qInv = q.modInverse(p);                       // q^-1 mod p(注意是 q 对 p 的逆)(这里可能需要补00)

        RSAPrivateCrtKeySpec keySpec = new RSAPrivateCrtKeySpec(
                n, e, d, p, q, dp, dq, qInv
        );

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);
    }

我补0后 正确

private int loadRsaPair2(String hexP, String hexQ) throws Exception
    {
        Log.d(TAG,"hexP:"+hexP);
        Log.d(TAG,"hexQ:"+hexQ);
        BigInteger p = hexToBigInt(hexP);
        BigInteger q = hexToBigInt(hexQ);
        BigInteger n = p.multiply(q);                            // n = p * q
        BigInteger phi = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));
        BigInteger e = BigInteger.valueOf(65537);                // 通常使用 65537 作为公钥指数
        BigInteger d = e.modInverse(phi);                        // 私钥指数 d = e^-1 mod φ(n)

        BigInteger dp2 = d.mod(p.subtract(BigInteger.ONE));       // d mod (p - 1)
        BigInteger dq2 = d.mod(q.subtract(BigInteger.ONE));       // d mod (q - 1)
        BigInteger qInv = q.modInverse(p);                       // q^-1 mod p(注意是 q 对 p 的逆)



        RSAPrivateCrtKeySpec keySpec = new RSAPrivateCrtKeySpec(
                n, e, d, p, q, dp2, dq2, qInv
        );
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey) keyFactory.generatePrivate(keySpec);



        int bits = rsaKey.getModulus().bitLength();
        int exponent = rsaKey.getPublicExponent().intValue();
        showText("bits:" + bits + " exponent: " + exponent);

        int length = bits / 8;
        byte[] modulus = copyArrays(rsaKey.getModulus().toByteArray(), length);
        byte[] primeP = copyArrays(rsaKey.getPrimeP().toByteArray(), length / 2);
        byte[] primeQ = copyArrays(rsaKey.getPrimeQ().toByteArray(), length / 2);
        byte[] dp = copyArrays(rsaKey.getPrimeExponentP().toByteArray(), length / 2);
        byte[] dq = copyArrays(rsaKey.getPrimeExponentQ().toByteArray(), length / 2);
       // byte[] invQ = copyArrays(rsaKey.getCrtCoefficient().toByteArray(), length / 2);
        byte[] invQ=new byte[128];
        byte[] temp =qInv.toByteArray();
        System.arraycopy(temp, 0,  invQ, invQ.length-temp.length,temp.length);


        Log.d(TAG, "modulus: "+BytesUtils.bytesToString(modulus));
        Log.d(TAG, "primeP: "+BytesUtils.bytesToString(primeP));
        Log.d(TAG, "primeQ: "+BytesUtils.bytesToString(primeQ));
        Log.d(TAG, "dp: "+BytesUtils.bytesToString(dp));
        Log.d(TAG, "dq: "+BytesUtils.bytesToString(dq));
        Log.d(TAG, "invQ: "+BytesUtils.bytesToString(invQ));

        int ret = ikey.setKeyGroupName("ftsafe_internal_group");
        if (ret != ErrCode.ERR_SUCCESS) {
            showText("Set keyGroup name error : " + ret + " " + ErrCode.toString(ret));
            return ret;
        }

        ret = ikey.loadRsaKeyPair(
                KeyType.KEY_TYPE_RSA,
                9, //固定值
                bits,
                modulus,
                exponent,
                primeP,
                primeQ,
                dp,
                dq,
                invQ
        );

        if (ret != ErrCode.ERR_SUCCESS) {
            showText("Load RsaKeyPair error : " + ret + " " + ErrCode.toString(ret));
            return ret;
        }
        return ErrCode.ERR_SUCCESS;
    }
    // 从16进制字符串生成BigInteger
    public static BigInteger hexToBigInt(String hex) {
        return new BigInteger(hex, 16);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小黄人软件

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

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

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

打赏作者

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

抵扣说明:

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

余额充值