BadPaddingException解密Android中的加密数据

时间:2014-07-28 05:15:29

标签: java android encryption cryptography

我是Android安全概念的新手。

我一直在阅读一些博客,以了解我们可以使用公钥加密数据,并可以使用相应的私钥对其进行解密。加密似乎没有任何问题,但当我尝试解密时,它会抛出:

  

javax.crypto.BadPaddingException:错误:0407106B:rsa例程:RSA_padding_check_PKCS1_type_2:块类型不是02。

我的代码如下:

public String RSAEncrypt(final String plain, PublicKey publicKey ) throws NoSuchAlgorithmException, NoSuchPaddingException,
    InvalidKeyException, IllegalBlockSizeException, BadPaddingException {

    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    byte [] encryptedBytes = cipher.doFinal(plain.getBytes());
    String encrypted = bytesToString(encryptedBytes);
    System.out.println("EEncrypted?????" + encrypted );
    return encrypted;
}

public String RSADecrypt(String encryptedBytes,PrivateKey privateKey ) throws NoSuchAlgorithmException, NoSuchPaddingException,
    InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException {
    Cipher cipher1 = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    cipher1.init(Cipher.DECRYPT_MODE, privateKey);
    byte [] decryptedBytes = cipher1.doFinal(stringToBytes(encryptedBytes));

    String decrypted = new String(decryptedBytes);
    System.out.println("DDecrypted?????" + decrypted);
    return decrypted;
    }

public  String bytesToString(byte[] b) {
    byte[] b2 = new byte[b.length + 1];
    b2[0] = 1;
    System.arraycopy(b, 0, b2, 1, b.length);
    return new BigInteger(b2).toString(36);
}

public  byte[] stringToBytes(String s) {
    byte[] b2 = new BigInteger(s, 36).toByteArray();
    return Arrays.copyOfRange(b2, 1, b2.length);
}

堆栈跟踪如下:

07-28 11:27:35.119: I/System.out(22933): KEYSTORE : String to encrypt = > Hello
07-28 11:27:35.119: I/System.out(22933): KEYSTORE : [B@41bbf4d0
07-28 11:27:38.422: I/System.out(22933): KEYSTORE : String to Decrypt = > UJGAchuDhu3mqH5YPjmYqKBapJYMjJRk9g6HIy8bANooWorzwqgiEo+dOse6Nfq7i0yzw/Wt7TSdTNiYROxehkZvEx/mW5+Niw1CgZ2y9b/ijTeNTF+7aGPrqfDXJ38hUFdTPc6oNl2FVOIafncGOSK9po1JOAYeK0JiA2KrACfPLPjsLQSRzseThyYGxttRM7qbx/N0VTmlTeuNpLFld8Gtw3fHR8UoLGkH/OTFYPLZBVNE8t/oCCy8FpcCu9SGXxF8vh1R4rq15bfyyh9sBU9RuVtoLM0wDSbKixHhNOwwx2Z/A+SHDaQD9C+x3p1AnS9FYZm0Y07E+VYQWqzOpw
07-28 11:27:38.562: W/System.err(22933): javax.crypto.BadPaddingException: error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02
07-28 11:27:41.515: D/WifiNative-wlan0(773): doString: SIGNAL_POLL
07-28 11:27:41.515: W/WifiHW(773): QCOM Debug wifi_send_command "IFNAME=wlan0 SIGNAL_POLL"
07-28 11:27:41.525: D/wpa_supplicant(16189): nl80211: survey data missing!
07-2
07-28 11:27:56.612: W/WifiHW(773): QCOM Debug wifi_send_command "IFNAME=wlan0 SIGNAL_POLL"
07-28 11:27:56.612: D/wpa_supplicant(16189): nl80211: survey data missing!
07-28 11:27:56.622: I/wpa_supplicant(16189): environment dirty rate=0 [0][0][0]
07-28 11:27:56.622: D/WifiStateMachine(773): fetchRssiAndLinkSpeedNative RSSI = -62 abnormalRssiCnt = 0 newLinkSpeed = 58
07-28 11:27:56.622: D/WifiStateMachine(773): fetchRssiAndLinkSpeedNative mLinkspeedCount = 2, mLinkspeedSum: 116

我不确定哪里出错了。

3 个答案:

答案 0 :(得分:3)

当填充(填充太小的加密块的字节)与指定的格式(例如PKCS1,OAEP,...)不匹配时,会发生 BadPaddingException 。这可能有几个原因:

  1. 您正在使用不同的RSA模式进行解密。
  2. 您从加密获得的数据(字节[])与您传递给解密的数据不同。
  3. (您使用的KeyPair不正确。)
  4. 由于您正在初始化RSA,getInstance("RSA")用于加密,getInstance("RSA/ECB/PKCS1Padding")用于解密,因此 ECB / PKCS1Padding 可能不是Android上的默认值(即使它应该在Desktop-Java上。

    请在RSAEncrypt()中尝试此操作:

    cipher.getInstance("RSA/ECB/PKCS1Padding");
    

    如果这不起作用,请确保将加密时从cipher.doFinal()获得的完全相同的字节[]传递给解密中的cipher.doFinal()

    (您的代码可以在我的桌面Java7上运行。)

答案 1 :(得分:0)

因为您正在使用加密数据,所以不太可能将其直接转换为String(每个字节可能与String中的字符存储不对应) - 因此我期望{{ 1}}通常会失败。尝试首先将加密数据转换为Base64,然后始终可以在bytesToString(encryptedBytes)中存储。然后你只需反过来解密: -

String

然后你可以做一些东西(比如存储)encryptedDataStr或whaterver。然后......

// to encrypt and get a String object
byte[] encode = Base64.encode(encryptedBytes, Base64.NO_PADDING|Base64.NO_WRAP);
String encryptedDataStr = new String(encode);
祝你好运!

答案 2 :(得分:0)

你必须将消息分解为块。

可以使用以下课程。

//注意:RSA有块限制,文本大小必须< (SIZE / 8),否则您会看到[RSA块的数据过多]

public class RSA
{
private RSAPublicKey internalPublicKey;
private RSAPrivateCrtKey internalPrivateKey;
private int SIZE = -1;
private String cipherAlgorithm = "RSA/None/PKCS1PADDING";
private String keyAlgorithm = "RSA";
private int b64State = Base64.NO_WRAP;
private static int b64State_static = Base64.NO_WRAP;

public RSA(int size)
{
    SIZE = size;
    init();
}

public RSA(int size, RSAPublicKey puk, RSAPrivateCrtKey prk)
{
    if(puk == null)
        throw new RuntimeException("Err: PublicKey is null.");

    if(prk != null)
    {
        if(!puk.getModulus().equals(prk.getModulus()))
            throw new RuntimeException("Err: PublicKey not matched by PrivateKey.");
    }

    SIZE = size;
    internalPublicKey = puk;
    internalPrivateKey = prk;
}

private void init()
{
    try
    {
        //SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithSHA256And256BitAES-CBC-BC");
        KeyPairGenerator kpg = KeyPairGenerator.getInstance(keyAlgorithm);
        kpg.initialize(SIZE); //initialize(SIZE, new SecureRandom());

        KeyPair kp = kpg.genKeyPair();
        internalPublicKey = (RSAPublicKey) kp.getPublic();
        internalPrivateKey = (RSAPrivateCrtKey) kp.getPrivate();
    }
    catch(Exception e)
    {throw new RuntimeException("Err: init RSA. " + e.toString());}
}

public int getSize()
{
    return SIZE;
}

public RSAPublicKey getPublicKey()
{
    return internalPublicKey;
}

public RSAPrivateCrtKey getPrivateKey()
{
    return internalPrivateKey;
}

public String getPublicModule()
{
    String s = internalPublicKey.toString();

    return s.substring(s.indexOf("modulus")+8, s.indexOf(",publicExponent"));
}

public BigInteger getPublicModuleInt()
{
    return internalPublicKey.getModulus();
}

public String getPublicExponent()
{
    String s = internalPublicKey.toString();

    return s.substring(s.indexOf("publicExponent")+15, s.lastIndexOf("}"));
}

public BigInteger getPublicExponentInt()
{
    return internalPublicKey.getPublicExponent();
}

public String getPrivateExponent()
{
    String s = internalPrivateKey.toString();
    return s.substring(s.indexOf("privateExponent")+16, s.indexOf(",primeP"));
}

public String getPrimP()
{
    String s = internalPrivateKey.toString();
    return s.substring(s.indexOf("primeP=")+7, s.indexOf(",primeQ"));
}

public String getPrimQ()
{
    String s = internalPrivateKey.toString();
    return s.substring(s.indexOf("primeQ=")+7, s.indexOf(",primeExponentP"));
}

public String getPrimExponentP()
{
    String s = internalPrivateKey.toString();
    return s.substring(s.indexOf("primeExponentP=")+15, s.indexOf(",primeExponentQ"));
}

public String getPrimExponentQ()
{
    String s = internalPrivateKey.toString();
    return s.substring(s.indexOf("primeExponentQ=")+15, s.indexOf(",crtCoefficient"));
}

public String getCrtCoefficient()
{
    String s = internalPrivateKey.toString();
    return s.substring(s.indexOf("crtCoefficient=")+15, s.lastIndexOf(","));
}

public byte[] getPublicKeyAsByte()
{
    return internalPublicKey.getEncoded();
}

public byte[] getPrivateKeyAsByte()
{
    return internalPrivateKey.getEncoded();
}

public void changeCipherAlgorithm(String algorithm)
{
    cipherAlgorithm = algorithm;
}

public byte[] getEncrypt(byte[] plain)
{
    try
    {
        Cipher cipher = Cipher.getInstance(cipherAlgorithm);
        cipher.init(Cipher.ENCRYPT_MODE, internalPublicKey);

        return cipher.doFinal(plain);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(byte[] plain), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public byte[] getEncrypt(String plain)
{
    try
    {
        return getEncrypt(plain.getBytes("UTF-8"));
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(String x), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public String getEncryptToB64(byte[] plain)
{
    return Base64.encodeToString(getEncrypt(plain), b64State);
}

public byte[] getLargeEncrypt(byte[] plain, boolean byPadding) //byPadding = true if use RSA/xxx/xxxPADDING
{
    ByteArrayOutputStream out = new ByteArrayOutputStream();

    try
    {
        int n = byPadding ? (getSize()/8) -11: (getSize()/8);

        int offset = 0;

        while(offset < plain.length)
        {
            byte[] section = Arrays.copyOfRange(plain, offset, Math.min(offset+n, plain.length));

            byte[] cache = getEncrypt(section);
            out.write(cache, 0, cache.length);

            offset += n;
        }

        return out.toByteArray();
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getLargeEncrypt(String x), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public byte[] getLargeEncrypt(String plain, boolean byPadding) //byPadding = true if use RSA/xxx/xxxPADDING
{
    return getLargeEncrypt(plain.getBytes(Charset.forName("UTF-8")), byPadding);
}

public String getLargeEncryptToB64(String plain, boolean byPadding) //byPadding = true if use RSA/xxx/xxxPADDING
{
    return Base64.encodeToString(getLargeEncrypt(plain, byPadding), Base64.NO_WRAP);
}

public String getLargeEncryptToB64Block(String plain, boolean byPadding) //byPadding = true if use RSA/xxx/xxxPADDING
{
    StringBuilder sb = new StringBuilder();

    try
    {
        byte[] enc = plain.getBytes("UTF-8");
        int n = byPadding ? (getSize()/8) -11: (getSize()/8);

        int offset = 0;

        while(offset < enc.length)
        {
            byte[] section = Arrays.copyOfRange(enc, offset, Math.min(offset+n, enc.length));

            sb.append(getEncryptToB64(section));

            offset += n;
        }
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getLargeEncryptToB64Block(String x), ", Constants.DEFAULT_ALERT_STATE);
    }

    return sb.toString();
}

public String getLargeDecryptFromB64Block(String enc)
{
    ByteArrayOutputStream out = new ByteArrayOutputStream();

    try
    {
        int n = (getSize()/8)-11;
        int x = getEncryptToB64(TextHelper.generateString(n).getBytes("UTF-8")).length();
        String[] ex = TextHelper.splitFix(enc, x);

        for(int i=0; i<ex.length; i++)
        {
            byte[] sec = Base64.decode(ex[i], Base64.NO_WRAP);
            out.write(sec, 0, sec.length);
            //sb.append(getDecryptFromB64(ex[i]));
        }

        return getLargeDecryptToString(out.toByteArray());//sb.toString()
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getLargeDecryptFromB64Block(String x), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public byte[] getLargeDecrypt(byte[] enc)
{
    ByteArrayOutputStream out = new ByteArrayOutputStream();

    try
    {
        int n = (getSize()/8);
        int offset = 0;

        while(offset < enc.length)
        {
            byte[] section = Arrays.copyOfRange(enc, offset, Math.min(offset+n, enc.length));

            byte[] cache = getDecrypt(section);
            out.write(cache, 0, cache.length);

            offset += n;
        }

        return out.toByteArray();
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getLargeDecrypt(byte[] x), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public String getLargeDecryptToString(byte[] enc)
{
    return new String(getLargeDecrypt(enc), Charset.forName("UTF-8"));
}

public String getLargeDecryptFromB64(String encB64)
{
    return getLargeDecryptToString(Base64.decode(encB64, Base64.NO_WRAP));
}

public byte[] getDecrypt(byte[] encryptedBytes)
{
    try
    {
        Cipher cipher = Cipher.getInstance(cipherAlgorithm);
        cipher.init(Cipher.DECRYPT_MODE, internalPrivateKey);

        return cipher.doFinal(encryptedBytes);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getDecrypt(byte[] x), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public String getDecryptFromB64(String encrypted)
{
    try
    {
        byte[] b = Base64.decode(encrypted.getBytes("UTF-8"), b64State);
        return getDecryptAsString(b);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getDecryptFromB64(String x), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public String getDecryptAsString(byte[] encryptedBytes)
{
    return new String(getDecrypt(encryptedBytes), Charset.forName("UTF-8"));
}

public static byte[] getEncrypt(byte[] plain, PublicKey pk, Cipher cipher)
{
    try
    {
        cipher.init(Cipher.ENCRYPT_MODE, pk);
        return cipher.doFinal(plain);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(byte[] x, PublicKey pk, Cipher cipher), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static byte[] getEncrypt(String plain, PublicKey pk, Cipher cipher)
{
    try
    {
        return getEncrypt(plain.getBytes("UTF-8"), pk, cipher);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(String x, PublicKey pk, Cipher cipher), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static byte[] getDecrypt(byte[] encryptedBytes, PrivateKey pk, Cipher cipher)
{
    try
    {
        cipher.init(Cipher.DECRYPT_MODE, pk);
        return cipher.doFinal(encryptedBytes);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static String getDecryptAsString(byte[] encryptedBytes,  PrivateKey pk, Cipher cipher)
{
    try
    {
        return new String(getDecrypt(encryptedBytes, pk, cipher), "UTF-8");
    }
    catch(Exception e){}
    return null;
}

public static byte[] getDecrypt(final byte[] encryptedBytes, byte[] privateKey, Cipher cipher)
{
    try
    {
        KeyFactory keyFac = KeyFactory.getInstance("RSA");
        KeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
        PrivateKey pk = keyFac.generatePrivate(keySpec);

        cipher.init(Cipher.DECRYPT_MODE, pk);
        return cipher.doFinal(encryptedBytes);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static String getDecryptAsString(final byte[] encryptedBytes, byte[] privateKey, Cipher cipher)
{
    return new String(getDecrypt(encryptedBytes, privateKey, cipher), Charset.forName("UTF-8"));
}

public static byte[] sign(byte[] forSign, PrivateKey byThisKey)
{
    try
    {
        Signature privateSignature = Signature.getInstance("SHA1withRSA");//or SHA256withRSA
        privateSignature.initSign(byThisKey);
        privateSignature.update(forSign);

        return privateSignature.sign();
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: sign(), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static String sign(String forSign, PrivateKey byThisKey)
{
    return Base64.encodeToString(sign(forSign.getBytes(), byThisKey), b64State_static);
}

public static boolean verify(String plainText, String signature, PublicKey publicKey)
{
    Signature publicSignature;

    try
    {
        publicSignature = Signature.getInstance("SHA1withRSA");
        publicSignature.initVerify(publicKey);
        publicSignature.update(plainText.getBytes());

        byte[] signatureBytes = Base64.decode(signature, b64State_static);

        return publicSignature.verify(signatureBytes);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: verify(), ", Constants.DEFAULT_ALERT_STATE);
    }

    return false;
}

public static RSAPublicKey generatePublicKey(String modulus, String exponent)
{
    try
    {
        BigInteger modBigInteger = new BigInteger(modulus, 16);
        BigInteger exBigInteger = new BigInteger(exponent, 16);
        RSAPublicKeySpec spec = new RSAPublicKeySpec(modBigInteger, exBigInteger);

        KeyFactory factory = KeyFactory.getInstance("RSA");
        return (RSAPublicKey) factory.generatePublic(spec);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static RSAPublicKey generatePublicKey(BigInteger modulus, BigInteger exponent)
{
    try
    {
        RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent);

        KeyFactory factory = KeyFactory.getInstance("RSA");
        return (RSAPublicKey) factory.generatePublic(spec);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static RSAPublicKey generatePublicKeyFromDotNet(String modulus, String exponent)
{
    return generatePublicKey(RSA.parseDotNetBigInt(modulus), RSA.parseDotNetBigInt(exponent));
}

public static RSAPrivateCrtKey generatePrivateKeyFromDotNet(String modulus, String pubEx, String priEx, String p, String q, String dp, String dq,String invQ)
{
    return generatePrivateKey(RSA.parseDotNetBigInt(modulus), RSA.parseDotNetBigInt(pubEx), RSA.parseDotNetBigInt(priEx), RSA.parseDotNetBigInt(p)
    ,RSA.parseDotNetBigInt(q),RSA.parseDotNetBigInt(dp), RSA.parseDotNetBigInt(dq), RSA.parseDotNetBigInt(invQ));
}

public static PublicKey generateBCPublicKey(String modulus, String exponent)
{
    try
    {
        BigInteger modBigInteger = new BigInteger(modulus, 16);
        BigInteger exBigInteger = new BigInteger(exponent, 16);
        RSAPublicKeySpec spec = new RSAPublicKeySpec(modBigInteger, exBigInteger);

        KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
        return factory.generatePublic(spec);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getBCPublicKey(), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static RSAPrivateCrtKey generatePrivateKey(String modulus, String publicExpo, String privateExpo, String primP, String primQ, String ePrimP, String ePrimQ, String cof)
{
    try
    {
        BigInteger module = new BigInteger(modulus, 16);
        BigInteger expo1 = new BigInteger(publicExpo, 16);
        BigInteger expo2 = new BigInteger(privateExpo, 16);
        BigInteger prim_P = new BigInteger(primP, 16);
        BigInteger prim_Q = new BigInteger(primQ, 16);
        BigInteger prim_EP = new BigInteger(ePrimP, 16);
        BigInteger prim_EQ = new BigInteger(ePrimQ, 16);
        BigInteger coefficient = new BigInteger(cof, 16);
        /*BigInteger module = new BigInteger(1, Base64.encode(modulus.getBytes(), b64State));*/

        RSAPrivateCrtKeySpec spec = new RSAPrivateCrtKeySpec(module, expo1, expo2, prim_P, prim_Q, prim_EP, prim_EQ, coefficient);

        KeyFactory factory = KeyFactory.getInstance("RSA");
        return (RSAPrivateCrtKey) factory.generatePrivate(spec);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static RSAPrivateCrtKey generatePrivateKey(BigInteger modulus, BigInteger publicExpo, BigInteger privateExpo, BigInteger primP, BigInteger primQ, BigInteger ePrimP, BigInteger ePrimQ, BigInteger cof)
{
    try
    {
        RSAPrivateCrtKeySpec spec = new RSAPrivateCrtKeySpec(modulus, publicExpo, privateExpo, primP, primQ, ePrimP, ePrimQ, cof);

        KeyFactory factory = KeyFactory.getInstance("RSA");
        return (RSAPrivateCrtKey) factory.generatePrivate(spec);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static PrivateKey generateBCPrivateKey(String modulus, String publicExpo, String privateExpo, String primP, String primQ, String ePrimP, String ePrimQ, String cof)
{
    try
    {
        BigInteger module = new BigInteger(modulus, 16);
        BigInteger expo1 = new BigInteger(publicExpo, 16);
        BigInteger expo2 = new BigInteger(privateExpo, 16);
        BigInteger prim_P = new BigInteger(primP, 16);
        BigInteger prim_Q = new BigInteger(primQ, 16);
        BigInteger prim_EP = new BigInteger(ePrimP, 16);
        BigInteger prim_EQ = new BigInteger(ePrimQ, 16);
        BigInteger coefficient = new BigInteger(cof, 16);

        RSAPrivateCrtKeySpec spec = new RSAPrivateCrtKeySpec(module, expo1, expo2, prim_P, prim_Q, prim_EP, prim_EQ, coefficient);

        KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
        return factory.generatePrivate(spec);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static Cipher generateCipher(String alg,@Nullable String provider)
{
    try
    {
        if(provider == null)
            return Cipher.getInstance(alg);
        else
            return Cipher.getInstance(alg, provider);
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: generateCipher(), ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static BigInteger parseDotNetBigInt(String b64BigInt)
{
    try
    {
        String modulusHex = Hex.encodeHex(Base64.decode(b64BigInt.getBytes("UTF-8"), Base64.NO_WRAP));
        return new BigInteger(modulusHex, 16);
    }
    catch (Exception ex)
    {
        ThreadHelper.exceptionAlert(ex, Constants.TAG_FOR_LOG, "Err: parseDotNetBigInt(),", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static String privateKeyToXMLString(RSAPrivateCrtKey key)
{
    try
    {
        Document xml = privateKeyToXML(key);
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        StringWriter sw = new StringWriter();
        transformer.transform(new DOMSource(xml), new StreamResult(sw));
        return sw.getBuffer().toString();
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: privateKeyToXMLString(RSAPrivateCrtKey x),", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static String publicKeyToXMLString(RSAPublicKey key)
{
    try
    {
        Document xml = publicKeyToXML(key);

        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        StringWriter sw = new StringWriter();
        transformer.transform(new DOMSource(xml), new StreamResult(sw));

        return sw.getBuffer().toString();
    }
    catch(Exception e){}

    return null;
}

public static Document publicKeyToXML(RSAPublicKey key)
{
    try
    {
        Document result = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        Element rsaKeyValue = result.createElement("RSAKeyValue");
        result.appendChild(rsaKeyValue);
        Element modulus = result.createElement("Modulus");
        rsaKeyValue.appendChild(modulus);

        byte[] modulusBytes = key.getModulus().toByteArray();
        modulusBytes = stripLeadingZeros(modulusBytes);

        modulus.appendChild(result.createTextNode(new String(Base64.encode(modulusBytes, b64State_static))));

        Element exponent = result.createElement("Exponent");
        rsaKeyValue.appendChild(exponent);

        byte[] exponentBytes = key.getPublicExponent().toByteArray();

        exponent.appendChild(result.createTextNode(new String(Base64.encode(exponentBytes, b64State_static))));

        return result;
    }
    catch(Exception e){}

    return null;
}

public static Document privateKeyToXML(RSAPrivateCrtKey key)
{
    try
    {
        Document result = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

        Element rsaKeyValue = result.createElement("RSAKeyValue");
        result.appendChild(rsaKeyValue);

        Element modulus = result.createElement("Modulus");
        rsaKeyValue.appendChild(modulus);

        Element exponent = result.createElement("Exponent");
        rsaKeyValue.appendChild(exponent);

        Element P = result.createElement("P");
        rsaKeyValue.appendChild(P);

        Element Q = result.createElement("Q");
        rsaKeyValue.appendChild(Q);

        Element DP = result.createElement("DP");
        rsaKeyValue.appendChild(DP);

        Element DQ = result.createElement("DQ");
        rsaKeyValue.appendChild(DQ);

        Element InverseQ = result.createElement("InverseQ");
        rsaKeyValue.appendChild(InverseQ);

        Element D = result.createElement("D");
        rsaKeyValue.appendChild(D);

        byte[] modulusBytes = key.getModulus().toByteArray();
        modulusBytes = stripLeadingZeros(modulusBytes);
        modulus.appendChild(result.createTextNode(new String(Base64.encode(modulusBytes, b64State_static))));

        byte[] pubExponent = key.getPublicExponent().toByteArray();
        exponent.appendChild(result.createTextNode(new String(Base64.encode(pubExponent, b64State_static))));

        byte[] p = key.getPrimeP().toByteArray();
        P.appendChild(result.createTextNode(new String(Base64.encode(p, b64State_static))));

        byte[] q = key.getPrimeQ().toByteArray();
        Q.appendChild(result.createTextNode(new String(Base64.encode(q, b64State_static))));

        byte[] ep = key.getPrimeExponentP().toByteArray();
        DP.appendChild(result.createTextNode(new String(Base64.encode(ep, b64State_static))));

        byte[] eq = key.getPrimeExponentP().toByteArray();
        DQ.appendChild(result.createTextNode(new String(Base64.encode(eq, b64State_static))));

        byte[] cof = key.getCrtCoefficient().toByteArray();
        InverseQ.appendChild(result.createTextNode(new String(Base64.encode(cof, b64State_static))));

        byte[] priExponent = key.getPrivateExponent().toByteArray();
        D.appendChild(result.createTextNode(new String(Base64.encode(priExponent, b64State_static))));

        return result;
    }
    catch(Exception e)
    {
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static byte[] stripLeadingZeros(byte[] input)
{
    while (input[0] == (byte) 0)
    {
        input = Arrays.copyOfRange(input, 1, input.length);
    }

    return input;
}

public static void saveKey(File file, PublicKey key)
{
    try
    {
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key.getEncoded());
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(x509EncodedKeySpec.getEncoded());
        fos.close();
    }
    catch(Exception e){}
}

public static void saveKey(File file, PrivateKey key)
{
    try
    {
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key.getEncoded());
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(pkcs8EncodedKeySpec.getEncoded());
        fos.close();
    }
    catch(Exception e){}
}

public PublicKey openPublicKey(String path, String algorithm)
{
    try
    {
        File filePublicKey = new File(path);
        FileInputStream fis = new FileInputStream(path);
        byte[] encodedPublicKey = new byte[(int) filePublicKey.length()];
        fis.read(encodedPublicKey);
        fis.close();

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedPublicKey);
        return keyFactory.generatePublic(publicKeySpec);
    }
    catch(Exception e){}

    return null;
}

public PrivateKey openPrivateKey(String path, String algorithm)
{
    try
    {
        File filePrivateKey = new File(path);
        FileInputStream fis = new FileInputStream(path);
        byte[] encodedPrivateKey = new byte[(int) filePrivateKey.length()];
        fis.read(encodedPrivateKey);
        fis.close();

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);//RSA
        PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
        return keyFactory.generatePrivate(privateKeySpec);
    }
    catch(Exception e){}

    return null;
}

public static RSAPublicKey fetchPublicKeyFromXML(Document xml)
{
    try
    {
        Element root = XMLMaster.getRoot(xml);
        String mud = XMLMaster.getTextContent(root, "Modulus", 0);
        String pubE = XMLMaster.getNodeValue(root, "Exponent", 0);

        return generatePublicKeyFromDotNet(mud, pubE);
    }
    catch (Throwable e)
    {
        //throw new RuntimeException("Err: can not fetch PublicKey. " + e.toString());
        ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: can not fetch PublicKey. ", Constants.DEFAULT_ALERT_STATE);
    }

    return null;
}

public static RSAPrivateCrtKey fetchPrivateKeyFromXML(Document xml)
{
    try
    {
        Element root = XMLMaster.getRoot(xml);
        String mud = XMLMaster.getTextContent(root, "Modulus", 0);
        String pubE = XMLMaster.getNodeValue(root, "Exponent", 0);
        String priE = XMLMaster.getNodeValue(root, "D", 0);
        String p = XMLMaster.getNodeValue(root, "P", 0);
        String Q = XMLMaster.getNodeValue(root, "Q", 0);
        String EP = XMLMaster.getNodeValue(root, "DP", 0);
        String EQ = XMLMaster.getNodeValue(root, "DQ", 0);
        String cof = XMLMaster.getNodeValue(root, "InverseQ", 0);

        return generatePrivateKeyFromDotNet(mud, pubE, priE, p, Q, EP, EQ, cof);
    }
    catch (Throwable e)
    {
        throw new RuntimeException("Err: can not fetch PrivateKey. " + e.toString());
    }
}

public static PrivateKey loadPrivateKey(String privateKeyB64)
{
    try
    {
        byte[] buffer = Base64.decode(privateKeyB64, Base64.NO_WRAP);

        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);

        //Class c = Reflector.getClassByAddressName("com.android.org.conscrypt.OpenSSLRSAPrivateKey");
        //RSAPrivateKeySpec privSpec = new RSAPrivateKeySpec(modules, d);
    }
    catch (Throwable e)
    {
        throw new RuntimeException("Err: can not load PrivateKey. " + e.toString());
    }
}

public String convertCaseToString(BigInteger num)
{
    return num.toString(16);
} // Use: convertCaseToString(rsa.getPublicModule())

}